首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >CANbus帧的滤波器

CANbus帧的滤波器
EN

Code Review用户
提问于 2019-04-26 11:57:21
回答 1查看 333关注 0票数 4

这里的实际数据类型可能与发布答案无关。我在这里使用Qt类型,但这个问题也适用于其他结构化类型。

我使用QtSerialBus模块在Qt中通过can总线接收数据帧。我想查找每个接收到的帧,如果它与我在QList中维护的一个D4匹配。

为了查看一个过滤器是否与当前接收到的帧匹配,我最初想出了这些代码行。下面的编辑显示了代码的演变过程,这样任何人都可以看到进展。

代码语言:javascript
复制
bool MyCanClass::isFrameMatchedByFilter(const QCanBusFrame& frameToFilter)
{
    if (mFilterList.isEmpty()) {
        return true;
    } else {
        for (auto& filter : mFilterList) {
            // Go down the chain as far as needed and proceed to the next list entry as soon as a mismatch comes up
            // First ID/Mask filtering, format and type afterwards
            if ((frameToFilter.frameId() & filter.frameId) != (filter.frameId & filter.frameIdMask)) {
                continue;
            }
            // FrameFormat only matters if set either base or extended, not both
            if (filter.format != QCanBusDevice::Filter::FormatFilter::MatchBaseAndExtendedFormat) {
                if (!(frameToFilter.hasExtendedFrameFormat() == (filter.format == QCanBusDevice::Filter::FormatFilter::MatchExtendedFormat))) {
                    continue;
                }
            }
            // Invalid frame is the default and matches every frame type
            if (filter.type != QCanBusFrame::FrameType::InvalidFrame) {
                if (filter.type != frameToFilter.frameType()) {
                    continue;
                }
            }
            return true;
        }
        return false;
    }
}

我个人认为嵌套的水平和一般的方法在这里并不太不干净,但它可能会得到改进,以便它更容易理解,甚至更快。

编辑1

经过几个步骤的重构,基于我得到的答案,我重构了所有的东西,使它更模块化,更容易理解。

我可能会事先对过滤器列表中的in进行排序,以便通过二进制搜索获得速度,但我不确定是否值得这样做,所以现在我将继续这样做:

代码语言:javascript
复制
bool MyCanClass::isFrameOfInterest(const QCanBusFrame& frame)
{
    if (mFilterList.isEmpty()) {
        return true;
    } else {
        return isCanFrameMatchingFilterList(frame, mFilterList);
    }
}

bool isCanFrameMatchingFilterList(const QCanBusFrame& frame, const QList& filterList)
{
    for (auto& filter : filterList) {
        // Go down the chain as far as needed and proceed to the next list entry as soon as a mismatch comes up
        // First ID/Mask filtering, format and type afterwards
        if (!isCanIdMatchedByFilter(frame, filter)) {
            continue;
        }
        // FrameFormat only matters if set either base or extended, not both
        if (!isFrameFormatMatchedByFilter(frame, filter)) {
            continue;
        }
        // Invalid frame is the default and matches every frame type
        if (!isFrameTypeMatchedByFilter(frame, filter)) {
            continue;
        }
        return true;
    }
    return false;
}

bool isCanIdMatchedByFilter(const QCanBusFrame& frame, const QCanBusDevice::Filter& filter)
{
    return (frame.frameId() & filter.frameId) == (filter.frameId & filter.frameIdMask);
}

bool isFrameFormatMatchedByFilter(const QCanBusFrame& frame, const QCanBusDevice::Filter& filter)
{
    if (filter.format == QCanBusDevice::Filter::FormatFilter::MatchBaseAndExtendedFormat) {
        return true;
    }
    bool extended = frame.hasExtendedFrameFormat();
    if (filter.format == QCanBusDevice::Filter::FormatFilter::MatchBaseFormat) {
        return (extended) ? false : true;
    } else {
        return (extended) ? true : false;
    }
}

bool isFrameTypeMatchedByFilter(const QCanBusFrame& frame, const QCanBusDevice::Filter& filter)
{
    // invalid frame matches all frame types
    if (filter.type != QCanBusFrame::FrameType::InvalidFrame) {
        if (filter.type != frame.frameType()) {
            return false;
        }
    }
    return true;
}

虽然新的isFrameFormatMatchedByFilter()在第一个视图中更容易理解,但我假设至少需要两个额外的指令来在CPU上执行该代码,我错了吗?

要弄清楚您自己的代码的哪一部分被认为“太聪明”而哪些不是:)总是有点困难。)

EN

回答 1

Code Review用户

回答已采纳

发布于 2019-04-26 12:24:50

当然,它可以更清洁、更清晰:

  • 您的函数名为isFrameMatchedByFilter,但如果筛选列表中没有筛选器,则返回true :这是否意味着帧由一个空筛选器匹配?还不清楚,您需要找到另一个名称或更改函数的行为。
  • 你的论点叫做frameToFilter,但这是个坏主意。首先,因为这个函数中只有一个框架,而且frameframeToFilter短;其次,frameToFilter也可以被解释为一种从框架到过滤器的转换(例如,在to_string中)。
  • 整个循环可以包含在一个命名算法中:std::any_of,或者,如果您稍微改变语义,std::find_if:返回匹配的过滤器可能会很有趣,而不是一个简单的bool。然后,您只需要将返回迭代器与filter_list.end()进行比较,就可以生成bool
  • 面具系统伴随着认知成本。(frameToFilter.frameId() & filter.frameId) != (filter.frameId & filter.frameIdMask)可能意味着什么,我没有什么实质性的想法。一个函数,甚至一个简单的λ来启发读者是很好的。它还将封装此计算,您可以将其更改为更健壮的系统(就像enum -but,我不知道上下文,因此可能不是正确的选择)。
  • 这类事情:!(frameToFilter.hasExtendedFrameFormat() == (filter.format == QCanBusDevice::Filter::FormatFilter::MatchExtendedFormat))太聪明了。再一次,在它周围写一个一行,或者至少写一个凡人能读的方式(我的意思是,没有50%的机会不能正确理解它)。

能再快一点吗?这取决于几个因素:您可以重新安排匹配条件,使其具有最快的*如果还没有完成,首先进行最有区别的选择(但它看起来是正确的顺序);您可以按id对筛选器进行排序,并执行二进制搜索,而不是平面搜索;如果存在大量的匹配条件,则可以并行。但是像往常一样,只有当它值得-measure的时候才能进行优化。

票数 6
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/219177

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档