0

我有一系列由独立结构定义的消息。这些结构共享一个公共标头,在应用程序之间发送。我正在创建一个解码器,它将获取使用这些结构构建的消息中的原始数据捕获并将它们解码/解析为一些纯文本。

我有超过 1000 条不同的消息需要解码,所以我不确定是否在 XML 中定义所有结构格式,然后使用 XSL 或一些翻译是可行的方法,或者是否有更好的方法来做到这一点。

有时我需要解码包含超过一百万条消息的日志,因此性能是一个问题。

关于创建解码器/解析器的技术/工具/算法有什么建议吗?

struct:
struct {
  dword messageid;
  dword datavalue1;
  dword datavalue2;
} struct1;

原始数据示例:

0101010A0A0A0A0F0F0F0F

解码消息(所需输出):

message id: 0x01010101, datavalue1: 0x0A0A0A0A, datavalue2: 0x0F0F0F0F

我正在使用 C++ 进行此开发。

4

4 回答 4

0

关于“性能” - 如果您使用磁盘 IO 和可能的显示 IO,我怀疑您的解析器/解码器会产生很大的影响,除非您使用真正可怕的算法。

我也不确定问题是什么 - 鉴于现在的问题 - 您在一个结构中有 3 个 DWORD,并且您声称有超过 1000 条基于这些值的唯一消息。

您的解码消息并不意味着您需要任何类型的解析 - 只是直接输出似乎有效(从字节转换为十六进制值的 ascii 表示)

如果您确实有从值到字符串的映射,那么大 switch 语句很简单 - 或者如果您希望能够动态添加这些或更改显示,那么我将提供键/值对(映射) 在配置文件(文本、xml 等)中,然后在读取日志文件/原始数据时进行查找。

map 是我在这种情况下会使用的。

也许如果您提供另一个值和解码输出的具体示例,我可以提出更合适的建议。

于 2008-12-16T18:23:54.513 回答
0

If you have the message definitions already given in the syntax that you've used in your example, you should definitely not try to convert it manually into some other syntax (XML or otherwise).

Instead, you should try to write a compiler that takes these method definitions, and compiles them into a decoder function.

These days, the recommendation is to use ANTLR as the parser generator, using any of the ANTLR languages for the actual compiler (Java, Python, Ruby, C#, C++). That compiler then should output C code, which does the entire decoding and pretty-printing.

于 2008-12-17T00:08:10.683 回答
0

我将假设您需要做的就是格式化记录并输出它们。

使用自定义代码生成器。生成的代码将如下所示:

typedef struct { word messageid; } Header;

//repeated for each record type
typedef struct {
    word messageid;
    // <members here>
} Record_##;
//END


void Process(Input inp, Output out) {
    char buffer[BIG_ENOUGH];
    char *offset;

    offset = &buffer[BIG_ENOUGH];

    while(notEnd) {
        if(&offset[sizeof(LargestStruct)] >= &buffer[BIG_ENOUGH])
            // move remaining buffer to start and fill tail from inp

        Header *hpt = (Header*)offset;

        switch(hpt->messageid)
        {
            //repeated for each record type
            case <recond ID for given type>: 
            {
                Record_##* rpt = (Record_##*)offset;
                outp.format("name1: %t, ...\n", rpt->name1, ...);
                offset += sizeof(Record_##);
                break;
            }
            //END
        }
    }
}

其中大部分是样板,因此编写程序来生成它应该不难。

如果您需要更多处理,我认为可以对这个想法进行一些调整以使其也能正常工作。


编辑:重新阅读问题后,看起来您可能已经定义了结构。在这种情况下,您可以只#include使用它们并直接使用它们。但是,您最终会遇到如何解析结构以生成格式化函数的输入的问题。awk 或 sed 在那里可能很方便。

于 2009-07-28T16:42:13.680 回答
0

您可以使用 yacc 或 antlr,添加适当的解析规则,在解析时从中填充一些数据结构(可能是树),然后遍历数据结构并做任何您喜欢的事情。

于 2009-07-28T11:38:35.137 回答