idl.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438
  1. /*
  2. * Copyright 2014 Google Inc. All rights reserved.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #ifndef FLATBUFFERS_IDL_H_
  17. #define FLATBUFFERS_IDL_H_
  18. #include <map>
  19. #include <memory>
  20. #include <functional>
  21. #include "flatbuffers/flatbuffers.h"
  22. // This file defines the data types representing a parsed IDL (Interface
  23. // Definition Language) / schema file.
  24. namespace flatbuffers {
  25. // The order of these matters for Is*() functions below.
  26. // Additionally, Parser::ParseType assumes bool..string is a contiguous range
  27. // of type tokens.
  28. #define FLATBUFFERS_GEN_TYPES_SCALAR(TD) \
  29. TD(NONE, "", uint8_t, byte, byte, byte) \
  30. TD(UTYPE, "", uint8_t, byte, byte, byte) /* begin scalar/int */ \
  31. TD(BOOL, "bool", uint8_t, byte, byte, byte) \
  32. TD(CHAR, "byte", int8_t, byte, int8, sbyte) \
  33. TD(UCHAR, "ubyte", uint8_t, byte, byte, byte) \
  34. TD(SHORT, "short", int16_t, short, int16, short) \
  35. TD(USHORT, "ushort", uint16_t, short, uint16, ushort) \
  36. TD(INT, "int", int32_t, int, int32, int) \
  37. TD(UINT, "uint", uint32_t, int, uint32, uint) \
  38. TD(LONG, "long", int64_t, long, int64, long) \
  39. TD(ULONG, "ulong", uint64_t, long, uint64, ulong) /* end int */ \
  40. TD(FLOAT, "float", float, float, float32, float) /* begin float */ \
  41. TD(DOUBLE, "double", double, double, float64, double) /* end float/scalar */
  42. #define FLATBUFFERS_GEN_TYPES_POINTER(TD) \
  43. TD(STRING, "string", Offset<void>, int, int, int) \
  44. TD(VECTOR, "", Offset<void>, int, int, int) \
  45. TD(STRUCT, "", Offset<void>, int, int, int) \
  46. TD(UNION, "", Offset<void>, int, int, int)
  47. // The fields are:
  48. // - enum
  49. // - FlatBuffers schema type.
  50. // - C++ type.
  51. // - Java type.
  52. // - Go type.
  53. // - C# / .Net type.
  54. // using these macros, we can now write code dealing with types just once, e.g.
  55. /*
  56. switch (type) {
  57. #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE) \
  58. case BASE_TYPE_ ## ENUM: \
  59. // do something specific to CTYPE here
  60. FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
  61. #undef FLATBUFFERS_TD
  62. }
  63. */
  64. #define FLATBUFFERS_GEN_TYPES(TD) \
  65. FLATBUFFERS_GEN_TYPES_SCALAR(TD) \
  66. FLATBUFFERS_GEN_TYPES_POINTER(TD)
  67. // Create an enum for all the types above.
  68. #ifdef __GNUC__
  69. __extension__ // Stop GCC complaining about trailing comma with -Wpendantic.
  70. #endif
  71. enum BaseType {
  72. #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE) \
  73. BASE_TYPE_ ## ENUM,
  74. FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
  75. #undef FLATBUFFERS_TD
  76. };
  77. #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE) \
  78. static_assert(sizeof(CTYPE) <= sizeof(largest_scalar_t), \
  79. "define largest_scalar_t as " #CTYPE);
  80. FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
  81. #undef FLATBUFFERS_TD
  82. inline bool IsScalar (BaseType t) { return t >= BASE_TYPE_UTYPE &&
  83. t <= BASE_TYPE_DOUBLE; }
  84. inline bool IsInteger(BaseType t) { return t >= BASE_TYPE_UTYPE &&
  85. t <= BASE_TYPE_ULONG; }
  86. inline bool IsFloat (BaseType t) { return t == BASE_TYPE_FLOAT ||
  87. t == BASE_TYPE_DOUBLE; }
  88. extern const char *const kTypeNames[];
  89. extern const char kTypeSizes[];
  90. inline size_t SizeOf(BaseType t) {
  91. return kTypeSizes[t];
  92. }
  93. struct StructDef;
  94. struct EnumDef;
  95. // Represents any type in the IDL, which is a combination of the BaseType
  96. // and additional information for vectors/structs_.
  97. struct Type {
  98. explicit Type(BaseType _base_type = BASE_TYPE_NONE,
  99. StructDef *_sd = nullptr, EnumDef *_ed = nullptr)
  100. : base_type(_base_type),
  101. element(BASE_TYPE_NONE),
  102. struct_def(_sd),
  103. enum_def(_ed)
  104. {}
  105. Type VectorType() const { return Type(element, struct_def, enum_def); }
  106. BaseType base_type;
  107. BaseType element; // only set if t == BASE_TYPE_VECTOR
  108. StructDef *struct_def; // only set if t or element == BASE_TYPE_STRUCT
  109. EnumDef *enum_def; // set if t == BASE_TYPE_UNION / BASE_TYPE_UTYPE,
  110. // or for an integral type derived from an enum.
  111. };
  112. // Represents a parsed scalar value, it's type, and field offset.
  113. struct Value {
  114. Value() : constant("0"), offset(static_cast<voffset_t>(
  115. ~(static_cast<voffset_t>(0U)))) {}
  116. Type type;
  117. std::string constant;
  118. voffset_t offset;
  119. };
  120. // Helper class that retains the original order of a set of identifiers and
  121. // also provides quick lookup.
  122. template<typename T> class SymbolTable {
  123. public:
  124. ~SymbolTable() {
  125. for (auto it = vec.begin(); it != vec.end(); ++it) {
  126. delete *it;
  127. }
  128. }
  129. bool Add(const std::string &name, T *e) {
  130. vec.emplace_back(e);
  131. auto it = dict.find(name);
  132. if (it != dict.end()) return true;
  133. dict[name] = e;
  134. return false;
  135. }
  136. T *Lookup(const std::string &name) const {
  137. auto it = dict.find(name);
  138. return it == dict.end() ? nullptr : it->second;
  139. }
  140. private:
  141. std::map<std::string, T *> dict; // quick lookup
  142. public:
  143. std::vector<T *> vec; // Used to iterate in order of insertion
  144. };
  145. // A name space, as set in the schema.
  146. struct Namespace {
  147. std::vector<std::string> components;
  148. };
  149. // Base class for all definition types (fields, structs_, enums_).
  150. struct Definition {
  151. Definition() : generated(false), defined_namespace(nullptr) {}
  152. std::string name;
  153. std::vector<std::string> doc_comment;
  154. SymbolTable<Value> attributes;
  155. bool generated; // did we already output code for this definition?
  156. Namespace *defined_namespace; // Where it was defined.
  157. };
  158. struct FieldDef : public Definition {
  159. FieldDef() : deprecated(false), required(false), padding(0), used(false) {}
  160. Value value;
  161. bool deprecated;
  162. bool required;
  163. size_t padding; // Bytes to always pad after this field.
  164. bool used; // Used during JSON parsing to check for repeated fields.
  165. };
  166. struct StructDef : public Definition {
  167. StructDef()
  168. : fixed(false),
  169. predecl(true),
  170. sortbysize(true),
  171. minalign(1),
  172. bytesize(0)
  173. {}
  174. void PadLastField(size_t _minalign) {
  175. auto padding = PaddingBytes(bytesize, _minalign);
  176. bytesize += padding;
  177. if (fields.vec.size()) fields.vec.back()->padding = padding;
  178. }
  179. SymbolTable<FieldDef> fields;
  180. bool fixed; // If it's struct, not a table.
  181. bool predecl; // If it's used before it was defined.
  182. bool sortbysize; // Whether fields come in the declaration or size order.
  183. size_t minalign; // What the whole object needs to be aligned to.
  184. size_t bytesize; // Size if fixed.
  185. };
  186. inline bool IsStruct(const Type &type) {
  187. return type.base_type == BASE_TYPE_STRUCT && type.struct_def->fixed;
  188. }
  189. inline size_t InlineSize(const Type &type) {
  190. return IsStruct(type) ? type.struct_def->bytesize : SizeOf(type.base_type);
  191. }
  192. inline size_t InlineAlignment(const Type &type) {
  193. return IsStruct(type) ? type.struct_def->minalign : SizeOf(type.base_type);
  194. }
  195. struct EnumVal {
  196. EnumVal(const std::string &_name, int64_t _val)
  197. : name(_name), value(_val), struct_def(nullptr) {}
  198. std::string name;
  199. std::vector<std::string> doc_comment;
  200. int64_t value;
  201. StructDef *struct_def; // only set if this is a union
  202. };
  203. struct EnumDef : public Definition {
  204. EnumDef() : is_union(false) {}
  205. EnumVal *ReverseLookup(int enum_idx, bool skip_union_default = true) {
  206. for (auto it = vals.vec.begin() + static_cast<int>(is_union &&
  207. skip_union_default);
  208. it != vals.vec.end(); ++it) {
  209. if ((*it)->value == enum_idx) {
  210. return *it;
  211. }
  212. }
  213. return nullptr;
  214. }
  215. SymbolTable<EnumVal> vals;
  216. bool is_union;
  217. Type underlying_type;
  218. };
  219. class Parser {
  220. public:
  221. Parser(bool proto_mode = false) :
  222. root_struct_def(nullptr),
  223. source_(nullptr),
  224. cursor_(nullptr),
  225. line_(1),
  226. proto_mode_(proto_mode) {
  227. // Just in case none are declared:
  228. namespaces_.push_back(new Namespace());
  229. }
  230. ~Parser() {
  231. for (auto it = namespaces_.begin(); it != namespaces_.end(); ++it) {
  232. delete *it;
  233. }
  234. }
  235. // Parse the string containing either schema or JSON data, which will
  236. // populate the SymbolTable's or the FlatBufferBuilder above.
  237. // include_paths is used to resolve any include statements, and typically
  238. // should at least include the project path (where you loaded source_ from).
  239. // include_paths must be nullptr terminated if specified.
  240. // If include_paths is nullptr, it will attempt to load from the current
  241. // directory.
  242. // If the source was loaded from a file and isn't an include file,
  243. // supply its name in source_filename.
  244. bool Parse(const char *_source, const char **include_paths = nullptr,
  245. const char *source_filename = nullptr);
  246. // Set the root type. May override the one set in the schema.
  247. bool SetRootType(const char *name);
  248. // Mark all definitions as already having code generated.
  249. void MarkGenerated();
  250. private:
  251. int64_t ParseHexNum(int nibbles);
  252. void Next();
  253. bool IsNext(int t);
  254. void Expect(int t);
  255. void ParseTypeIdent(Type &type);
  256. void ParseType(Type &type);
  257. FieldDef &AddField(StructDef &struct_def,
  258. const std::string &name,
  259. const Type &type);
  260. void ParseField(StructDef &struct_def);
  261. void ParseAnyValue(Value &val, FieldDef *field);
  262. uoffset_t ParseTable(const StructDef &struct_def);
  263. void SerializeStruct(const StructDef &struct_def, const Value &val);
  264. void AddVector(bool sortbysize, int count);
  265. uoffset_t ParseVector(const Type &type);
  266. void ParseMetaData(Definition &def);
  267. bool TryTypedValue(int dtoken, bool check, Value &e, BaseType req);
  268. void ParseSingleValue(Value &e);
  269. int64_t ParseIntegerFromString(Type &type);
  270. StructDef *LookupCreateStruct(const std::string &name);
  271. void ParseEnum(bool is_union);
  272. void ParseNamespace();
  273. StructDef &StartStruct();
  274. void ParseDecl();
  275. void ParseProtoDecl();
  276. Type ParseTypeFromProtoType();
  277. public:
  278. SymbolTable<StructDef> structs_;
  279. SymbolTable<EnumDef> enums_;
  280. std::vector<Namespace *> namespaces_;
  281. std::string error_; // User readable error_ if Parse() == false
  282. FlatBufferBuilder builder_; // any data contained in the file
  283. StructDef *root_struct_def;
  284. std::string file_identifier_;
  285. std::string file_extension_;
  286. std::map<std::string, bool> included_files_;
  287. private:
  288. const char *source_, *cursor_;
  289. int line_; // the current line being parsed
  290. int token_;
  291. bool proto_mode_;
  292. std::string attribute_;
  293. std::vector<std::string> doc_comment_;
  294. std::vector<std::pair<Value, FieldDef *>> field_stack_;
  295. std::vector<uint8_t> struct_stack_;
  296. };
  297. // Utility functions for multiple generators:
  298. extern std::string MakeCamel(const std::string &in, bool first = true);
  299. extern void GenComment(const std::vector<std::string> &dc,
  300. std::string *code_ptr,
  301. const char *prefix = "");
  302. // Container of options that may apply to any of the source/text generators.
  303. struct GeneratorOptions {
  304. bool strict_json;
  305. int indent_step;
  306. bool output_enum_identifiers;
  307. bool prefixed_enums;
  308. bool include_dependence_headers;
  309. // Possible options for the more general generator below.
  310. enum Language { kJava, kCSharp, kMAX };
  311. Language lang;
  312. GeneratorOptions() : strict_json(false), indent_step(2),
  313. output_enum_identifiers(true), prefixed_enums(true),
  314. include_dependence_headers(false),
  315. lang(GeneratorOptions::kJava) {}
  316. };
  317. // Generate text (JSON) from a given FlatBuffer, and a given Parser
  318. // object that has been populated with the corresponding schema.
  319. // If ident_step is 0, no indentation will be generated. Additionally,
  320. // if it is less than 0, no linefeeds will be generated either.
  321. // See idl_gen_text.cpp.
  322. // strict_json adds "quotes" around field names if true.
  323. extern void GenerateText(const Parser &parser,
  324. const void *flatbuffer,
  325. const GeneratorOptions &opts,
  326. std::string *text);
  327. // Generate a C++ header from the definitions in the Parser object.
  328. // See idl_gen_cpp.
  329. extern std::string GenerateCPP(const Parser &parser,
  330. const std::string &include_guard_ident,
  331. const GeneratorOptions &opts);
  332. extern bool GenerateCPP(const Parser &parser,
  333. const std::string &path,
  334. const std::string &file_name,
  335. const GeneratorOptions &opts);
  336. // Generate Go files from the definitions in the Parser object.
  337. // See idl_gen_go.cpp.
  338. extern bool GenerateGo(const Parser &parser,
  339. const std::string &path,
  340. const std::string &file_name,
  341. const GeneratorOptions &opts);
  342. // Generate Java files from the definitions in the Parser object.
  343. // See idl_gen_java.cpp.
  344. extern bool GenerateJava(const Parser &parser,
  345. const std::string &path,
  346. const std::string &file_name,
  347. const GeneratorOptions &opts);
  348. // Generate C# files from the definitions in the Parser object.
  349. // See idl_gen_csharp.cpp.
  350. extern bool GenerateCSharp(const Parser &parser,
  351. const std::string &path,
  352. const std::string &file_name,
  353. const GeneratorOptions &opts);
  354. // Generate Java/C#/.. files from the definitions in the Parser object.
  355. // See idl_gen_general.cpp.
  356. extern bool GenerateGeneral(const Parser &parser,
  357. const std::string &path,
  358. const std::string &file_name,
  359. const GeneratorOptions &opts);
  360. // Generate a schema file from the internal representation, useful after
  361. // parsing a .proto schema.
  362. extern std::string GenerateFBS(const Parser &parser,
  363. const std::string &file_name,
  364. const GeneratorOptions &opts);
  365. extern bool GenerateFBS(const Parser &parser,
  366. const std::string &path,
  367. const std::string &file_name,
  368. const GeneratorOptions &opts);
  369. } // namespace flatbuffers
  370. #endif // FLATBUFFERS_IDL_H_