• C代码工具--自动生成enum值和名字映射代码


    这年头好像继续做C语言的人不多了,年轻人大多去互联网和移动应用。确实,那两个领域现在来钱快,且总是供不应求。就说刚刚在一个旧同事的微信群里,有人刚放出自己有团队可以做App几分钟,哇塞,好几个人说有项目,要求加好友私聊。我也想过转行,可惜人老珠黄,没有互联网或是应用团队愿意接收。估计再过些年,C程序世界里就只有我这样的小老头们继续自娱自乐了,羡慕死年轻人了!

    平常工作中,经常要做一些打印,或是日志。而这里面,enum类型的数据就很多,如果只是打印出它的整数值,显然会让测试人员很恼火,鬼知道那数字说的是什么。就算你给他个文档对着看,也丝毫不能得到原谅。最后,都得乖乖的把这个enum对应的名字打印出来才能平息。

    今天说的这个,就是帮忙搞定这个转换问题的。


    比如,有这么个example.h文件:

    enum InfoStateE{
      eInfoStateIdle,
      eInfoStateIniting,
      eInfoStateInited,
      eInfoStateReady,
      eInfoStateActive,
      eInfoStateStandby,
      eInfoStateRelease,
    };

    我们需要个函数,把enum值翻译成字符串;另外也要个函数,能查找字符串对应的enum值;可以提供名字的一部分。p_enum.pl就是做这个的,只需要执行:

    perl p_enum.pl example.h -o:example_map
    p_enum.pl接受目录,通配符,或是多个文件。-o:example_map是指定输出的文件名。这里我们得到了example_map.h和example_map.c两个文件:

    /*
    FILE: example_map.h
    This file was created at Fri Dec 11 16:40:56 CST 2015
    
    Auto-generated source. Don't change it manually.
    Contact with hhao020@gmail.com for bug reporting and supporting.
    */
    
    #ifndef EXAMPLE_MAP
    #define EXAMPLE_MAP
    
    #ifdef __cplusplus
        extern "C" {
    #endif
    
    #include "zType_Def.h"
    extern const char* InfoStateE2Name(dword_t e);
    extern dword_t InfoStateE2Value(char* name, int bAppro);
    extern int InfoStateEMapShow();
    
    #ifdef __cplusplus
    }
    #endif
    
    #endif /*EXAMPLE_MAP*/
    View Code
    /*
    FILE: example_map.c
    This file was created at Fri Dec 11 16:40:56 CST 2015
    
    Auto-generated source. Don't change it manually.
    Contact with hhao020@gmail.com for bug reporting and supporting.
    */
    
    #define _GNU_SOURCE 
    #include <string.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    
    #include "zAutoCodeApi.h"
    #ifndef ENUM_PRIMARY_FUNCTIONS
    static char *zEnum2Name(dword_t e, zEnum2NameMap_t arr[], int nSize)
    {
      int i;
    
      for(i=0; i<nSize; i++)
      {
        if(arr[i].e == e) return arr[i].name;
      }
      
      return 0;
    }
    
    static int zName2Enum(char* name, zEnum2NameMap_t arr[], int nSize, int bAppro)
    {
      int i;
    
      for(i=0; i<nSize; i++)
      {
        if(bAppro)
        {
          if(strcasestr(arr[i].name, name)) return arr[i].e;
        }
        else
        {
          if(!strcmp(arr[i].name, name)) return arr[i].e;
        }
      }
      
      return -1;
    }
    
    static int zEnumMapShow(zEnum2NameMap_t arr[], int nSize)
    {
      int i;
      for(i=0; i<nSize; i++)
      {
        printf("%3d %d-> %s 
    ", i, arr[i].e, arr[i].name);
      }
      
      return 0;
    }
    #endif /*ENUM_PRIMARY_FUNCTIONS*/
    
    #include "example_map.h"
    
    
    
    #include "example.h"
    
    zEnum2NameMap_t InfoStateE_map_t[]=
    {
      {eInfoStateIdle, "eInfoStateIdle"},
      {eInfoStateIniting, "eInfoStateIniting"},
      {eInfoStateInited, "eInfoStateInited"},
      {eInfoStateReady, "eInfoStateReady"},
      {eInfoStateActive, "eInfoStateActive"},
      {eInfoStateStandby, "eInfoStateStandby"},
      {eInfoStateRelease, "eInfoStateRelease"},
    }; /*InfoStateE_map_t*/
    
    const char* InfoStateE2Name(dword_t e)
    {
      char* pName = zEnum2Name(e, InfoStateE_map_t, TBL_SIZE(InfoStateE_map_t));
      
      if(pName) return pName;
      return "*NA*";
    }
    
    dword_t InfoStateE2Value(char* name, int bAppro)
    {
      return zName2Enum(name, InfoStateE_map_t, TBL_SIZE(InfoStateE_map_t), bAppro);
    };
    
    int InfoStateEMapShow()
    {
      return zEnumMapShow(InfoStateE_map_t, TBL_SIZE(InfoStateE_map_t));
    };
    View Code

    p_enum.pl是用了我自己做的lex和yacc库。本来是学习编译原理时的一些实验代码,后来发现它对于文本提取还是很强大,于是有了enum相关的自动生成工具。有兴趣的,可以参考,或者有问题留言。

    嗯,还有一点,p_enum.pl不支持enum定义里包含编译控制宏。如果你有这个需求,需要自己修改enum.lex和enum.yacc文件来支持。我非常厌恶编译宏,因此不会做这个更新。

    如何设置使用环境的补充说明:
    linux环境,perl_zlib建议解压在你的home目录下。然后在你的用户配置文件.bashrc(或是.profile,不同linux略有差别)里面添加zlib的路径。我的配置里是这样的:
    export PATH="$HOME/perl/Debug:$PATH"
    export PERL5LIB="$HOME/perl/zLib:$HOME/perl5/lib/perl5"
    PERL_MB_OPT="--install_base "$HOME/perl5""; export PERL_MB_OPT;
    PERL_MM_OPT="INSTALL_BASE=$HOME/perl5"; export PERL_MM_OPT;
    这当中只有PERL5LIB里的zLib路径是必须的。perl5是我用来装额外的perl库用的,一起贴出来供参考。

    windows环境,需要先运行zlib.bat来设置环境变量,然后才能运行p_enum.pl。当然,你还要确认安装了activeperl。

  • 相关阅读:
    [LeetCode] 215. Kth Largest Element in an Array 数组中第k大的元素
    [LeetCode] 23. Merge k Sorted Lists 合并k个有序链表
    [LeetCode] 146. LRU Cache 近期最少使用缓存
    [LeetCode] 381. Insert Delete GetRandom O(1)
    [LeetCode] 380. Insert Delete GetRandom O(1) 插入删除获得随机数O(1)时间
    [LeetCode] 57. Insert Interval 插入区间
    [LeetCode] 56. Merge Intervals 合并区间
    [LeetCode] 155. Min Stack 最小栈
    移动web开发-------meta
    font-family
  • 原文地址:https://www.cnblogs.com/hhao020/p/5044159.html
Copyright © 2020-2023  润新知