flatbuffers C++ 宏代码欣赏

来源:互联网 发布:linux informix 安装 编辑:程序博客网 时间:2024/06/02 23:48

flatbuffers 是Google的一个开源序列化库,支持C/C++, Json, C#, Java等格式,每一种格式都由基本的数据结构组成,格式之间的数据结构也存在着差异,flatbuffers有它自己定义的数据结构。

而最常见的数据结构有:

BOOL,CHAR,UCHAR,SHORT,USHORT,INT,UINT,LONG,ULONG,FLOAT,DOUBLE


flatbuffers 在处理基本数据结构的分选的代码十分的简洁:

      switch (fd.value.type.base_type) {         #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE) \           case BASE_TYPE_ ## ENUM: \              GenField<CTYPE>(fd, table, struct_def.fixed, \                              opts, indent + Indent(opts), _text); \              break;          FLATBUFFERS_GEN_TYPES_SCALAR(FLATBUFFERS_TD)        #undef FLATBUFFERS_TD        // Generate drop-thru case statements for all pointer types:        #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE) \          case BASE_TYPE_ ## ENUM:          FLATBUFFERS_GEN_TYPES_POINTER(FLATBUFFERS_TD)        #undef FLATBUFFERS_TD            GenFieldOffset(fd, table, struct_def.fixed, indent + Indent(opts),                           union_sd, opts, _text);            break;      }


其中,涉及到的三个宏定义如下:

#define FLATBUFFERS_GEN_TYPES_SCALAR(TD) \  TD(NONE,   "",       uint8_t,  byte,   byte,    byte) \  TD(UTYPE,  "",       uint8_t,  byte,   byte,    byte) /* begin scalar/int */ \  TD(BOOL,   "bool",   uint8_t,  byte,   byte,    byte) \  TD(CHAR,   "byte",   int8_t,   byte,   int8,    sbyte) \  TD(UCHAR,  "ubyte",  uint8_t,  byte,   byte,    byte) \  TD(SHORT,  "short",  int16_t,  short,  int16,   short) \  TD(USHORT, "ushort", uint16_t, short,  uint16,  ushort) \  TD(INT,    "int",    int32_t,  int,    int32,   int) \  TD(UINT,   "uint",   uint32_t, int,    uint32,  uint) \  TD(LONG,   "long",   int64_t,  long,   int64,   long) \  TD(ULONG,  "ulong",  uint64_t, long,   uint64,  ulong)  /* end int */ \  TD(FLOAT,  "float",  float,    float,  float32, float)  /* begin float */ \  TD(DOUBLE, "double", double,   double, float64, double) /* end float/scalar */#define FLATBUFFERS_GEN_TYPES_POINTER(TD) \  TD(STRING, "string", Offset<void>, int, int, int) \  TD(VECTOR, "",       Offset<void>, int, int, int) \  TD(STRUCT, "",       Offset<void>, int, int, int) \  TD(UNION,  "",       Offset<void>, int, int, int)

#define FLATBUFFERS_GEN_TYPES(TD) \        FLATBUFFERS_GEN_TYPES_SCALAR(TD) \        FLATBUFFERS_GEN_TYPES_POINTER(TD)

enum BaseType {  #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE) \      BASE_TYPE_ ## ENUM,    FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)  #undef FLATBUFFERS_TD};


里面的一段注释很重要:

// The fields are:// - enum// - FlatBuffers schema type.// - C++ type.// - Java type.// - Go type.// - C# / .Net type.// using these macros, we can now write code dealing with types just once, e.g./*switch (type) {  #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE) \    case BASE_TYPE_ ## ENUM: \      // do something specific to CTYPE here    FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)  #undef FLATBUFFERS_TD}*/

</pre><p></p><p>FLATBUFFERS_GEN_TYPES(TD) FLATBUFFERS_GEN_TYPES_SCALAR(TD) FLATBUFFERS_GEN_TYPES_POINTER(TD)</p><p>三个宏其实是构建一个基本数据结构的矩阵,基本数据结构分为 SCALAR(标量)和POINTER(矢量)</p><p> 纵向是对所有基本数据结构的抽象,横轴是每种格式的实际元数据结构;</p><p></p><p>宏看不懂没关系,我们可以使用工具来分析:</p><p>$gcc -E idl_gen_text.cpp > out.txt</p><p>整理一下:</p><p><pre name="code" class="cpp">      switch (fd.value.type.base_type) {          case BASE_TYPE_NONE:           GenField<uint8_t>(fd, table, struct_def.fixed, opts, indent + Indent(opts), _text); break;           case BASE_TYPE_UTYPE:           GenField<uint8_t>(fd, table, struct_def.fixed, opts, indent + Indent(opts), _text); break;           case BASE_TYPE_BOOL:           GenField<uint8_t>(fd, table, struct_def.fixed, opts, indent + Indent(opts), _text); break;           case BASE_TYPE_CHAR:           GenField<int8_t>(fd, table, struct_def.fixed, opts, indent + Indent(opts), _text);          break;           case BASE_TYPE_UCHAR:           GenField<uint8_t>(fd, table, struct_def.fixed, opts, indent + Indent(opts), _text); break;           case BASE_TYPE_SHORT:           GenField<int16_t>(fd, table, struct_def.fixed, opts, indent + Indent(opts), _text); break;           case BASE_TYPE_USHORT:           GenField<uint16_t>(fd, table, struct_def.fixed, opts, indent + Indent(opts), _text); break;           case BASE_TYPE_INT:           GenField<int32_t>(fd, table, struct_def.fixed, opts, indent + Indent(opts), _text); break;           case BASE_TYPE_UINT:           GenField<uint32_t>(fd, table, struct_def.fixed, opts, indent + Indent(opts), _text); break;           case BASE_TYPE_LONG:           GenField<int64_t>(fd, table, struct_def.fixed, opts, indent + Indent(opts), _text); break;           case BASE_TYPE_ULONG:           GenField<uint64_t>(fd, table, struct_def.fixed, opts, indent + Indent(opts), _text); break;           case BASE_TYPE_FLOAT:           GenField<float>(fd, table, struct_def.fixed, opts, indent + Indent(opts), _text);           break;           case BASE_TYPE_DOUBLE:           GenField<double>(fd, table, struct_def.fixed, opts, indent + Indent(opts), _text);           break;          case BASE_TYPE_STRING:           case BASE_TYPE_VECTOR:           case BASE_TYPE_STRUCT:           case BASE_TYPE_UNION:            GenFieldOffset(fd, table, struct_def.fixed, indent + Indent(opts),                           union_sd, opts, _text);            break;      }

写得很精典!


0 0
原创粉丝点击