简体   繁体   English

如何从protobuf中的枚举中获取下一个枚举值?

[英]How to get the next enum value from an enum in protobuf?

I have a protobuf message with non-consecutive enum values something like this:我有一个带有非连续枚举值的 protobuf 消息,如下所示:

message Information {
    enum Versions {
        version1 = 0;
        version2 = 1;
        version3 = 10;
        version4 = 20;   
        version5 = 30;    
    }
}

I want to have a C++ function GetNextVersion() which takes in one enum version and gives the next version as output.我想要一个 C++ function GetNextVersion() 它接受一个枚举版本并将下一个版本作为 output。 For eg: GetNextVersion(Information::version4) should give Information::version5 as output.例如:GetNextVersion(Information::version4) 应该给出 Information::version5 作为 output。 Is there any inbuilt and easy method to do this?有没有内置的简单方法可以做到这一点?

Is there any inbuilt and easy method to do this?有没有内置的简单方法可以做到这一点?

I see no easy method to get that.我认为没有简单的方法可以做到这一点。

But I can suggest metaprogramming approaches (at least on Linux) with C++ code generation.但我可以建议使用 C++ 代码生成的元编程方法(至少在 Linux 上)。

You could, assuming you have access to the source code of protobuf-c :你可以,假设你可以访问protobuf-c的源代码

  • write some GNU gawk script to parse that C++ code and generate the C++ code of GetNextVersion编写一些GNU gawk脚本来解析 C++ 代码并生成 GetNextVersion 的GetNextVersion代码

  • perhaps write some GNU sed (or a Python one) script doing the same.也许写一些GNU sed (或Python之一)脚本做同样的事情。

  • write some GCC plugin and use it to parse that C++ code and generate the C++ code of GetNextVersion编写一些GCC 插件并使用它来解析 C++ 代码并生成 GetNextVersion 的GetNextVersion代码

  • write some GNU emacs code doing the same.写一些GNU emacs代码做同样的事情。

  • wait a few months and (in spring 2021) use Bismon .等待几个月,(在 spring 2021 中)使用Bismon I am developing it, so contact me by email我正在开发它,所以请通过 email 与我联系

  • extend and adapt the Clang static analyzer for your needs.根据您的需要扩展和调整Clang static 分析仪

  • extend and adapt the SWIG tool for your needs.扩展和调整SWIG工具以满足您的需求。

  • extend and adapt the RPGGEN tool for your needs.根据您的需要扩展和调整RPGGEN工具。

  • use GNU bison or ANTLR to parse C++ code, or design your domain specific language with some documentedEBNF syntax and write some code generator with them.使用GNU bisonANTLR来解析 C++ 代码,或者使用一些文档化的EBNF语法设计您的领域特定语言并用它们编写一些代码生成器。

You could also keep the description of enum Versions in some database ( sqlite , PostGreSQL , etc...) or some JSON file or some CSV file (or an XML one, using XSLT or libexpat ) and emit it (for protobuf) and the source code of GetNextVersion using some Python script, or GNU m4 , or GPP . You could also keep the description of enum Versions in some database ( sqlite , PostGreSQL , etc...) or some JSON file or some CSV file (or an XML one, using XSLT or libexpat ) and emit it (for protobuf) and the使用一些Python脚本或GNU m4GPPGetNextVersion的源代码。

You could write a GNU guile script or some rules for CLIPS generating some C++ code with your protobuf description.你可以编写一个GNU guile脚本或一些规则,让 CLIPS使用你的 protobuf 描述生成一些 C++ 代码。

In a few months (spring 2021), the RefPerSys system might be helpful.几个月后(2021 年春季), RefPerSys系统可能会有所帮助。 Before that, you could contribute and extend it and reuse it for your needs.在此之前,您可以贡献和扩展它,并根据您的需要重用它。

A pragmatic approach could be to add a comment in your protobuf declaration to remind you of editing another file when you need to change the protobuf message and protocol.一种实用的方法可能是在您的 protobuf 声明中添加注释,以提醒您在需要更改 protobuf 消息和协议时编辑另一个文件。

You can use protobuf's reflection to achieve the goal:您可以使用 protobuf 的反射来实现目标:

Information::Versions GetNextVersion(Information::Versions ver) {
    const auto *desc = Information::Versions_descriptor();
    auto cur_idx = desc->FindValueByNumber(ver)->index();
    if (cur_idx >= desc->value_count() - 1) {
        throw runtime_error("no next enum");
    }

    auto next_idx = cur_idx + 1;
    return Information::Versions(desc->value(next_idx)->number());
}

int main() {
    try {
        auto ver = Information::version1;
        while (true) {
            cout << ver << endl;
            ver = GetNextVersion(ver);
        }
    } catch (const runtime_error &e) {
        cout << e.what() << endl;
    }
    return 0;
}

No, there isn't.不,没有。

You define your own data type, so you also must define the operators for it.您定义自己的数据类型,因此您还必须为其定义运算符。

So, your GetNextVersion()method contains that knowledge how to increment the version number.因此,您的 GetNextVersion() 方法包含如何增加版本号的知识。 If you had decided to use an integer, then the compiler knows already how to increment that, but you wanted something special and that is the price you have to pay for it.如果您决定使用 integer,那么编译器已经知道如何增加它,但是您想要一些特别的东西,这就是您必须为此付出的代价。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM