idl_gen_php.cpp 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967
  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. // independent from idl_parser, since this code is not needed for most clients
  17. #include <string>
  18. #include "flatbuffers/flatbuffers.h"
  19. #include "flatbuffers/idl.h"
  20. #include "flatbuffers/util.h"
  21. #include "flatbuffers/code_generators.h"
  22. namespace flatbuffers {
  23. namespace php {
  24. // Hardcode spaces per indentation.
  25. const std::string Indent = " ";
  26. class PhpGenerator : public BaseGenerator {
  27. public:
  28. PhpGenerator(const Parser &parser, const std::string &path,
  29. const std::string &file_name)
  30. : BaseGenerator(parser, path, file_name, "\\", "\\"){};
  31. bool generate() {
  32. if (!generateEnums()) return false;
  33. if (!generateStructs()) return false;
  34. return true;
  35. }
  36. private:
  37. bool generateEnums() {
  38. for (auto it = parser_.enums_.vec.begin();
  39. it != parser_.enums_.vec.end(); ++it) {
  40. auto &enum_def = **it;
  41. std::string enumcode;
  42. GenEnum(enum_def, &enumcode);
  43. if (!SaveType(enum_def, enumcode, false)) return false;
  44. }
  45. return true;
  46. }
  47. bool generateStructs() {
  48. for (auto it = parser_.structs_.vec.begin();
  49. it != parser_.structs_.vec.end(); ++it) {
  50. auto &struct_def = **it;
  51. std::string declcode;
  52. GenStruct(struct_def, &declcode);
  53. if (!SaveType(struct_def, declcode, true)) return false;
  54. }
  55. return true;
  56. }
  57. // Begin by declaring namespace and imports.
  58. void BeginFile(const std::string name_space_name,
  59. const bool needs_imports, std::string *code_ptr) {
  60. std::string &code = *code_ptr;
  61. code += "<?php\n";
  62. code = code + "// " + FlatBuffersGeneratedWarning();
  63. code += "namespace " + name_space_name + ";\n\n";
  64. if (needs_imports) {
  65. code += "use \\Google\\FlatBuffers\\Struct;\n";
  66. code += "use \\Google\\FlatBuffers\\Table;\n";
  67. code += "use \\Google\\FlatBuffers\\ByteBuffer;\n";
  68. code += "use \\Google\\FlatBuffers\\FlatBufferBuilder;\n";
  69. code += "\n";
  70. }
  71. }
  72. // Save out the generated code for a Php Table type.
  73. bool SaveType(const Definition &def, const std::string &classcode,
  74. bool needs_imports) {
  75. if (!classcode.length()) return true;
  76. std::string code = "";
  77. BeginFile(FullNamespace("\\", *def.defined_namespace),
  78. needs_imports, &code);
  79. code += classcode;
  80. std::string filename = NamespaceDir(*def.defined_namespace) +
  81. def.name + ".php";
  82. return SaveFile(filename.c_str(), code, false);
  83. }
  84. // Begin a class declaration.
  85. static void BeginClass(const StructDef &struct_def, std::string *code_ptr) {
  86. std::string &code = *code_ptr;
  87. if (struct_def.fixed) {
  88. code += "class " + struct_def.name + " extends Struct\n";
  89. } else {
  90. code += "class " + struct_def.name + " extends Table\n";
  91. }
  92. code += "{\n";
  93. }
  94. static void EndClass(std::string *code_ptr) {
  95. std::string &code = *code_ptr;
  96. code += "}\n";
  97. }
  98. // Begin enum code with a class declaration.
  99. static void BeginEnum(const std::string class_name, std::string *code_ptr) {
  100. std::string &code = *code_ptr;
  101. code += "class " + class_name + "\n{\n";
  102. }
  103. // A single enum member.
  104. static void EnumMember(const EnumVal ev, std::string *code_ptr) {
  105. std::string &code = *code_ptr;
  106. code += Indent + "const ";
  107. code += ev.name;
  108. code += " = ";
  109. code += NumToString(ev.value) + ";\n";
  110. }
  111. // End enum code.
  112. static void EndEnum(std::string *code_ptr) {
  113. std::string &code = *code_ptr;
  114. code += "}\n";
  115. }
  116. // Initialize a new struct or table from existing data.
  117. static void NewRootTypeFromBuffer(const StructDef &struct_def,
  118. std::string *code_ptr) {
  119. std::string &code = *code_ptr;
  120. code += Indent + "/**\n";
  121. code += Indent + " * @param ByteBuffer $bb\n";
  122. code += Indent + " * @return " + struct_def.name + "\n";
  123. code += Indent + " */\n";
  124. code += Indent + "public static function getRootAs";
  125. code += struct_def.name;
  126. code += "(ByteBuffer $bb)\n";
  127. code += Indent + "{\n";
  128. code += Indent + Indent + "$obj = new " + struct_def.name + "();\n";
  129. code += Indent + Indent;
  130. code += "return ($obj->init($bb->getInt($bb->getPosition())";
  131. code += " + $bb->getPosition(), $bb));\n";
  132. code += Indent + "}\n\n";
  133. }
  134. // Initialize an existing object with other data, to avoid an allocation.
  135. static void InitializeExisting(const StructDef &struct_def,
  136. std::string *code_ptr) {
  137. std::string &code = *code_ptr;
  138. code += Indent + "/**\n";
  139. code += Indent + " * @param int $_i offset\n";
  140. code += Indent + " * @param ByteBuffer $_bb\n";
  141. code += Indent + " * @return " + struct_def.name + "\n";
  142. code += Indent + " **/\n";
  143. code += Indent + "public function init($_i, ByteBuffer $_bb)\n";
  144. code += Indent + "{\n";
  145. code += Indent + Indent + "$this->bb_pos = $_i;\n";
  146. code += Indent + Indent + "$this->bb = $_bb;\n";
  147. code += Indent + Indent + "return $this;\n";
  148. code += Indent + "}\n\n";
  149. }
  150. // Get the length of a vector.
  151. static void GetVectorLen(const FieldDef &field,
  152. std::string *code_ptr) {
  153. std::string &code = *code_ptr;
  154. code += Indent + "/**\n";
  155. code += Indent + " * @return int\n";
  156. code += Indent + " */\n";
  157. code += Indent + "public function get";
  158. code += MakeCamel(field.name) + "Length()\n";
  159. code += Indent + "{\n";
  160. code += Indent + Indent + "$o = $this->__offset(";
  161. code += NumToString(field.value.offset) + ");\n";
  162. code += Indent + Indent;
  163. code += "return $o != 0 ? $this->__vector_len($o) : 0;\n";
  164. code += Indent + "}\n\n";
  165. }
  166. // Get a [ubyte] vector as a byte array.
  167. static void GetUByte(const FieldDef &field,
  168. std::string *code_ptr) {
  169. std::string &code = *code_ptr;
  170. code += Indent + "/**\n";
  171. code += Indent + " * @return string\n";
  172. code += Indent + " */\n";
  173. code += Indent + "public function get";
  174. code += MakeCamel(field.name) + "Bytes()\n";
  175. code += Indent + "{\n";
  176. code += Indent + Indent + "return $this->__vector_as_bytes(";
  177. code += NumToString(field.value.offset) + ");\n";
  178. code += Indent + "}\n\n";
  179. }
  180. // Get the value of a struct's scalar.
  181. static void GetScalarFieldOfStruct(const FieldDef &field,
  182. std::string *code_ptr) {
  183. std::string &code = *code_ptr;
  184. std::string getter = GenGetter(field.value.type);
  185. code += Indent + "/**\n";
  186. code += Indent + " * @return ";
  187. code += GenTypeGet(field.value.type) + "\n";
  188. code += Indent + " */\n";
  189. code += Indent + "public function " + getter;
  190. code += MakeCamel(field.name) + "()\n";
  191. code += Indent + "{\n";
  192. code += Indent + Indent + "return ";
  193. code += "$this->bb->get";
  194. code += MakeCamel(GenTypeGet(field.value.type));
  195. code += "($this->bb_pos + ";
  196. code += NumToString(field.value.offset) + ")";
  197. code += ";\n";
  198. code += Indent + "}\n\n";
  199. }
  200. // Get the value of a table's scalar.
  201. void GetScalarFieldOfTable(const FieldDef &field, std::string *code_ptr) {
  202. std::string &code = *code_ptr;
  203. std::string getter = GenGetter(field.value.type);
  204. code += Indent + "/**\n";
  205. code += Indent + " * @return " + GenTypeGet(field.value.type) + "\n";
  206. code += Indent + " */\n";
  207. code += Indent + "public function get";
  208. code += MakeCamel(field.name);
  209. code += "()\n";
  210. code += Indent + "{\n";
  211. code += Indent + Indent +
  212. "$o = $this->__offset(" +
  213. NumToString(field.value.offset) +
  214. ");\n" + Indent + Indent + "return $o != 0 ? ";
  215. code += "$this->bb->get";
  216. code += MakeCamel(GenTypeGet(field.value.type)) + "($o + $this->bb_pos)";
  217. code += " : " + GenDefaultValue(field.value) + ";\n";
  218. code += Indent + "}\n\n";
  219. }
  220. // Get a struct by initializing an existing struct.
  221. // Specific to Struct.
  222. void GetStructFieldOfStruct(const FieldDef &field, std::string *code_ptr) {
  223. std::string &code = *code_ptr;
  224. code += Indent + "/**\n";
  225. code += Indent + " * @return " + GenTypeGet(field.value.type) + "\n";
  226. code += Indent + " */\n";
  227. code += Indent + "public function get";
  228. code += MakeCamel(field.name) + "()\n";
  229. code += Indent + "{\n";
  230. code += Indent + Indent + "$obj = new ";
  231. code += GenTypeGet(field.value.type) + "();\n";
  232. code += Indent + Indent + "$obj->init($this->bb_pos + ";
  233. code += NumToString(field.value.offset) + ", $this->bb);";
  234. code += "\n" + Indent + Indent + "return $obj;\n";
  235. code += Indent + "}\n\n";
  236. }
  237. // Get a struct by initializing an existing struct.
  238. // Specific to Table.
  239. void GetStructFieldOfTable(const FieldDef &field, std::string *code_ptr) {
  240. std::string &code = *code_ptr;
  241. code += Indent + "public function get";
  242. code += MakeCamel(field.name);
  243. code += "()\n";
  244. code += Indent + "{\n";
  245. code += Indent + Indent + "$obj = new ";
  246. code += MakeCamel(GenTypeGet(field.value.type)) + "();\n";
  247. code += Indent + Indent +
  248. "$o = $this->__offset(" +
  249. NumToString(field.value.offset) +
  250. ");\n";
  251. code += Indent + Indent;
  252. code += "return $o != 0 ? $obj->init(";
  253. if (field.value.type.struct_def->fixed)
  254. {
  255. code += "$o + $this->bb_pos, $this->bb) : ";
  256. } else {
  257. code += "$this->__indirect($o + $this->bb_pos), $this->bb) : ";
  258. }
  259. code += GenDefaultValue(field.value) + ";\n";
  260. code += Indent + "}\n\n";
  261. }
  262. // Get the value of a string.
  263. void GetStringField(const FieldDef &field, std::string *code_ptr) {
  264. std::string &code = *code_ptr;
  265. code += Indent + "public function get";
  266. code += MakeCamel(field.name);
  267. code += "()\n";
  268. code += Indent + "{\n";
  269. code += Indent + Indent +
  270. "$o = $this->__offset(" +
  271. NumToString(field.value.offset) +
  272. ");\n";
  273. code += Indent + Indent;
  274. code += "return $o != 0 ? $this->__string($o + $this->bb_pos) : ";
  275. code += GenDefaultValue(field.value) + ";\n";
  276. code += Indent + "}\n\n";
  277. }
  278. // Get the value of a union from an object.
  279. void GetUnionField(const FieldDef &field, std::string *code_ptr) {
  280. std::string &code = *code_ptr;
  281. code += Indent + "/**\n";
  282. code += Indent + " * @return" + GenTypeBasic(field.value.type) + "\n";
  283. code += Indent + " */\n";
  284. code += Indent + "public function get";
  285. code += MakeCamel(field.name) + "($obj)\n";
  286. code += Indent + "{\n";
  287. code += Indent + Indent +
  288. "$o = $this->__offset(" +
  289. NumToString(field.value.offset) +
  290. ");\n";
  291. code += Indent + Indent;
  292. code += "return $o != 0 ? $this->__union($obj, $o) : null;\n";
  293. code += Indent + "}\n\n";
  294. }
  295. // Get the value of a vector's struct member.
  296. void GetMemberOfVectorOfStruct(const StructDef &struct_def,
  297. const FieldDef &field, std::string *code_ptr) {
  298. std::string &code = *code_ptr;
  299. auto vectortype = field.value.type.VectorType();
  300. code += Indent + "/**\n";
  301. code += Indent + " * @return" + GenTypeBasic(field.value.type) + "\n";
  302. code += Indent + " */\n";
  303. code += Indent + "public function get";
  304. code += MakeCamel(field.name);
  305. code += "($j)\n";
  306. code += Indent + "{\n";
  307. code += Indent + Indent +
  308. "$o = $this->__offset(" +
  309. NumToString(field.value.offset) +
  310. ");\n";
  311. code += Indent + Indent + "$obj = new ";
  312. code += MakeCamel(GenTypeGet(field.value.type)) + "();\n";
  313. switch (field.value.type.base_type) {
  314. case BASE_TYPE_STRUCT:
  315. if (struct_def.fixed) {
  316. code += Indent + Indent;
  317. code += "return $o != 0 ? $obj->init($this->bb_pos +"
  318. + NumToString(field.value.offset) + ", $this->bb) : null;\n";
  319. } else {
  320. code += Indent + Indent + "return $o != 0 ? $obj->init(";
  321. code += field.value.type.struct_def->fixed
  322. ? "$o + $this->bb_pos"
  323. : "$this->__indirect($o + $this->bb_pos)";
  324. code += ", $this->bb) : null;\n";
  325. }
  326. break;
  327. case BASE_TYPE_STRING:
  328. code += "// base_type_string\n";
  329. // TODO(chobie): do we need this?
  330. break;
  331. case BASE_TYPE_VECTOR:
  332. if (vectortype.base_type == BASE_TYPE_STRUCT) {
  333. code += Indent + Indent + "return $o != 0 ? $obj->init(";
  334. if (vectortype.struct_def->fixed) {
  335. code += "$this->__vector($o) + $j *";
  336. code += NumToString(InlineSize(vectortype));
  337. } else {
  338. code += "$this->__indirect($this->__vector($o) + $j * ";
  339. code += NumToString(InlineSize(vectortype)) + ")";
  340. }
  341. code += ", $this->bb) : null;\n";
  342. }
  343. break;
  344. case BASE_TYPE_UNION:
  345. code += Indent + Indent + "return $o != 0 ? $this->";
  346. code += GenGetter(field.value.type) + "($obj, $o); null;\n";
  347. break;
  348. default:
  349. break;
  350. }
  351. code += Indent + "}\n\n";
  352. }
  353. // Get the value of a vector's non-struct member. Uses a named return
  354. // argument to conveniently set the zero value for the result.
  355. void GetMemberOfVectorOfNonStruct(const FieldDef &field,
  356. std::string *code_ptr) {
  357. std::string &code = *code_ptr;
  358. auto vectortype = field.value.type.VectorType();
  359. code += Indent + "/**\n";
  360. code += Indent + " * @param int offset\n";
  361. code += Indent + " * @return " + GenTypeGet(field.value.type) + "\n";
  362. code += Indent + " */\n";
  363. code += Indent + "public function get";
  364. code += MakeCamel(field.name);
  365. code += "($j)\n";
  366. code += Indent + "{\n";
  367. code += Indent + Indent +
  368. "$o = $this->__offset(" +
  369. NumToString(field.value.offset) +
  370. ");\n";
  371. if (field.value.type.VectorType().base_type == BASE_TYPE_STRING) {
  372. code += Indent + Indent;
  373. code += "return $o != 0 ? $this->__string($this->__vector($o) + $j * ";
  374. code += NumToString(InlineSize(vectortype)) + ") : ";
  375. code += GenDefaultValue(field.value) + ";\n";
  376. } else {
  377. code += Indent + Indent + "return $o != 0 ? $this->bb->get";
  378. code += MakeCamel(GenTypeGet(field.value.type));
  379. code += "($this->__vector($o) + $j * ";
  380. code += NumToString(InlineSize(vectortype)) + ") : ";
  381. code += GenDefaultValue(field.value) + ";\n";
  382. }
  383. code += Indent + "}\n\n";
  384. }
  385. // Recursively generate arguments for a constructor, to deal with nested
  386. // structs.
  387. static void StructBuilderArgs(const StructDef &struct_def,
  388. const char *nameprefix,
  389. std::string *code_ptr) {
  390. for (auto it = struct_def.fields.vec.begin();
  391. it != struct_def.fields.vec.end();
  392. ++it) {
  393. auto &field = **it;
  394. if (IsStruct(field.value.type)) {
  395. // Generate arguments for a struct inside a struct. To ensure names
  396. // don't clash, and to make it obvious
  397. // these arguments are constructing
  398. // a nested struct, prefix the name with the field name.
  399. StructBuilderArgs(*field.value.type.struct_def,
  400. (nameprefix + (field.name + "_")).c_str(),
  401. code_ptr);
  402. } else {
  403. std::string &code = *code_ptr;
  404. code += (std::string)", $" + nameprefix;
  405. code += MakeCamel(field.name, false);
  406. }
  407. }
  408. }
  409. // Recursively generate struct construction statements and instert manual
  410. // padding.
  411. static void StructBuilderBody(const StructDef &struct_def,
  412. const char *nameprefix,
  413. std::string *code_ptr) {
  414. std::string &code = *code_ptr;
  415. code += Indent + Indent + "$builder->prep(";
  416. code += NumToString(struct_def.minalign) + ", ";
  417. code += NumToString(struct_def.bytesize) + ");\n";
  418. for (auto it = struct_def.fields.vec.rbegin();
  419. it != struct_def.fields.vec.rend();
  420. ++it) {
  421. auto &field = **it;
  422. if (field.padding) {
  423. code += Indent + Indent + "$builder->pad(";
  424. code += NumToString(field.padding) + ");\n";
  425. }
  426. if (IsStruct(field.value.type)) {
  427. StructBuilderBody(*field.value.type.struct_def,
  428. (nameprefix + (field.name + "_")).c_str(),
  429. code_ptr);
  430. } else {
  431. code += Indent + Indent + "$builder->put" + GenMethod(field) + "($";
  432. code += nameprefix + MakeCamel(field.name, false) + ");\n";
  433. }
  434. }
  435. }
  436. // Get the value of a table's starting offset.
  437. static void GetStartOfTable(const StructDef &struct_def,
  438. std::string *code_ptr) {
  439. std::string &code = *code_ptr;
  440. code += Indent + "/**\n";
  441. code += Indent + " * @param FlatBufferBuilder $builder\n";
  442. code += Indent + " * @return void\n";
  443. code += Indent + " */\n";
  444. code += Indent + "public static function start" + struct_def.name;
  445. code += "(FlatBufferBuilder $builder)\n";
  446. code += Indent + "{\n";
  447. code += Indent + Indent + "$builder->StartObject(";
  448. code += NumToString(struct_def.fields.vec.size());
  449. code += ");\n";
  450. code += Indent + "}\n\n";
  451. code += Indent + "/**\n";
  452. code += Indent + " * @param FlatBufferBuilder $builder\n";
  453. code += Indent + " * @return " + struct_def.name + "\n";
  454. code += Indent + " */\n";
  455. code += Indent + "public static function create" + struct_def.name;
  456. code += "(FlatBufferBuilder $builder, ";
  457. for (auto it = struct_def.fields.vec.begin();
  458. it != struct_def.fields.vec.end();
  459. ++it) {
  460. auto &field = **it;
  461. if (field.deprecated) continue;
  462. code += "$" + field.name;
  463. if (!(it == (--struct_def.fields.vec.end()))) {
  464. code += ", ";
  465. }
  466. }
  467. code += ")\n";
  468. code += Indent + "{\n";
  469. code += Indent + Indent + "$builder->startObject(";
  470. code += NumToString(struct_def.fields.vec.size());
  471. code += ");\n";
  472. for (auto it = struct_def.fields.vec.begin();
  473. it != struct_def.fields.vec.end();
  474. ++it) {
  475. auto &field = **it;
  476. if (field.deprecated) continue;
  477. code += Indent + Indent + "self::add";
  478. code += MakeCamel(field.name) + "($builder, $" + field.name + ");\n";
  479. }
  480. code += Indent + Indent + "$o = $builder->endObject();\n";
  481. for (auto it = struct_def.fields.vec.begin();
  482. it != struct_def.fields.vec.end();
  483. ++it) {
  484. auto &field = **it;
  485. if (!field.deprecated && field.required) {
  486. code += Indent + Indent + "$builder->required($o, ";
  487. code += NumToString(field.value.offset);
  488. code += "); // " + field.name + "\n";
  489. }
  490. }
  491. code += Indent + Indent + "return $o;\n";
  492. code += Indent + "}\n\n";
  493. }
  494. // Set the value of a table's field.
  495. static void BuildFieldOfTable(const FieldDef &field,
  496. const size_t offset,
  497. std::string *code_ptr) {
  498. std::string &code = *code_ptr;
  499. code += Indent + "/**\n";
  500. code += Indent + " * @param FlatBufferBuilder $builder\n";
  501. code += Indent + " * @param " + GenTypeBasic(field.value.type) + "\n";
  502. code += Indent + " * @return void\n";
  503. code += Indent + " */\n";
  504. code += Indent + "public static function ";
  505. code += "add" + MakeCamel(field.name);
  506. code += "(FlatBufferBuilder $builder, ";
  507. code += "$" + MakeCamel(field.name, false);
  508. code += ")\n";
  509. code += Indent + "{\n";
  510. code += Indent + Indent + "$builder->add";
  511. code += GenMethod(field) + "X(";
  512. code += NumToString(offset) + ", ";
  513. code += "$" + MakeCamel(field.name, false);
  514. code += ", ";
  515. if (field.value.type.base_type == BASE_TYPE_BOOL) {
  516. code += "false";
  517. } else {
  518. code += field.value.constant;
  519. }
  520. code += ");\n";
  521. code += Indent + "}\n\n";
  522. }
  523. // Set the value of one of the members of a table's vector.
  524. static void BuildVectorOfTable(const FieldDef &field,
  525. std::string *code_ptr) {
  526. std::string &code = *code_ptr;
  527. auto vector_type = field.value.type.VectorType();
  528. auto alignment = InlineAlignment(vector_type);
  529. auto elem_size = InlineSize(vector_type);
  530. code += Indent + "/**\n";
  531. code += Indent + " * @param FlatBufferBuilder $builder\n";
  532. code += Indent + " * @param array offset array\n";
  533. code += Indent + " * @return int vector offset\n";
  534. code += Indent + " */\n";
  535. code += Indent + "public static function create";
  536. code += MakeCamel(field.name);
  537. code += "Vector(FlatBufferBuilder $builder, array $data)\n";
  538. code += Indent + "{\n";
  539. code += Indent + Indent + "$builder->startVector(";
  540. code += NumToString(elem_size);
  541. code += ", count($data), " + NumToString(alignment);
  542. code += ");\n";
  543. code += Indent + Indent;
  544. code += "for ($i = count($data) - 1; $i >= 0; $i--) {\n";
  545. if (IsScalar(field.value.type.VectorType().base_type)) {
  546. code += Indent + Indent + Indent;
  547. code += "$builder->add";
  548. code += MakeCamel(GenTypeBasic(field.value.type.VectorType()));
  549. code += "($data[$i]);\n";
  550. } else {
  551. code += Indent + Indent + Indent;
  552. code += "$builder->addOffset($data[$i]);\n";
  553. }
  554. code += Indent + Indent + "}\n";
  555. code += Indent + Indent + "return $builder->endVector();\n";
  556. code += Indent + "}\n\n";
  557. code += Indent + "/**\n";
  558. code += Indent + " * @param FlatBufferBuilder $builder\n";
  559. code += Indent + " * @param int $numElems\n";
  560. code += Indent + " * @return void\n";
  561. code += Indent + " */\n";
  562. code += Indent + "public static function start";
  563. code += MakeCamel(field.name);
  564. code += "Vector(FlatBufferBuilder $builder, $numElems)\n";
  565. code += Indent + "{\n";
  566. code += Indent + Indent + "$builder->startVector(";
  567. code += NumToString(elem_size);
  568. code += ", $numElems, " + NumToString(alignment);
  569. code += ");\n";
  570. code += Indent + "}\n\n";
  571. }
  572. // Get the offset of the end of a table.
  573. void GetEndOffsetOnTable(const StructDef &struct_def, std::string *code_ptr) {
  574. std::string &code = *code_ptr;
  575. code += Indent + "/**\n";
  576. code += Indent + " * @param FlatBufferBuilder $builder\n";
  577. code += Indent + " * @return int table offset\n";
  578. code += Indent + " */\n";
  579. code += Indent + "public static function end" + struct_def.name;
  580. code += "(FlatBufferBuilder $builder)\n";
  581. code += Indent + "{\n";
  582. code += Indent + Indent + "$o = $builder->endObject();\n";
  583. for (auto it = struct_def.fields.vec.begin();
  584. it != struct_def.fields.vec.end();
  585. ++it) {
  586. auto &field = **it;
  587. if (!field.deprecated && field.required) {
  588. code += Indent + Indent + "$builder->required($o, ";
  589. code += NumToString(field.value.offset);
  590. code += "); // " + field.name + "\n";
  591. }
  592. }
  593. code += Indent + Indent + "return $o;\n";
  594. code += Indent + "}\n";
  595. if (parser_.root_struct_def_ == &struct_def) {
  596. code += "\n";
  597. code += Indent + "public static function finish";
  598. code += struct_def.name;
  599. code += "Buffer(FlatBufferBuilder $builder, $offset)\n";
  600. code += Indent + "{\n";
  601. code += Indent + Indent + "$builder->finish($offset";
  602. if (parser_.file_identifier_.length())
  603. code += ", \"" + parser_.file_identifier_ + "\"";
  604. code += ");\n";
  605. code += Indent + "}\n";
  606. }
  607. }
  608. // Generate a struct field, conditioned on its child type(s).
  609. void GenStructAccessor(const StructDef &struct_def, const FieldDef &field,
  610. std::string *code_ptr) {
  611. GenComment(field.doc_comment, code_ptr, nullptr);
  612. if (IsScalar(field.value.type.base_type)) {
  613. if (struct_def.fixed) {
  614. GetScalarFieldOfStruct(field, code_ptr);
  615. } else {
  616. GetScalarFieldOfTable(field, code_ptr);
  617. }
  618. } else {
  619. switch (field.value.type.base_type) {
  620. case BASE_TYPE_STRUCT:
  621. if (struct_def.fixed) {
  622. GetStructFieldOfStruct(field, code_ptr);
  623. } else {
  624. GetStructFieldOfTable(field, code_ptr);
  625. }
  626. break;
  627. case BASE_TYPE_STRING:
  628. GetStringField(field, code_ptr);
  629. break;
  630. case BASE_TYPE_VECTOR: {
  631. auto vectortype = field.value.type.VectorType();
  632. if (vectortype.base_type == BASE_TYPE_STRUCT) {
  633. GetMemberOfVectorOfStruct(struct_def, field, code_ptr);
  634. } else {
  635. GetMemberOfVectorOfNonStruct(field, code_ptr);
  636. }
  637. break;
  638. }
  639. case BASE_TYPE_UNION:
  640. GetUnionField(field, code_ptr);
  641. break;
  642. default:
  643. assert(0);
  644. }
  645. }
  646. if (field.value.type.base_type == BASE_TYPE_VECTOR) {
  647. GetVectorLen(field, code_ptr);
  648. if (field.value.type.element == BASE_TYPE_UCHAR) {
  649. GetUByte(field, code_ptr);
  650. }
  651. }
  652. }
  653. // Generate table constructors, conditioned on its members' types.
  654. void GenTableBuilders(const StructDef &struct_def, std::string *code_ptr) {
  655. GetStartOfTable(struct_def, code_ptr);
  656. for (auto it = struct_def.fields.vec.begin();
  657. it != struct_def.fields.vec.end();
  658. ++it) {
  659. auto &field = **it;
  660. if (field.deprecated) continue;
  661. auto offset = it - struct_def.fields.vec.begin();
  662. if (field.value.type.base_type == BASE_TYPE_UNION) {
  663. std::string &code = *code_ptr;
  664. code += Indent + "public static function add";
  665. code += MakeCamel(field.name);
  666. code += "(FlatBufferBuilder $builder, $offset)\n";
  667. code += Indent + "{\n";
  668. code += Indent + Indent + "$builder->addOffsetX(";
  669. code += NumToString(offset) + ", $offset, 0);\n";
  670. code += Indent + "}\n\n";
  671. } else {
  672. BuildFieldOfTable(field, offset, code_ptr);
  673. }
  674. if (field.value.type.base_type == BASE_TYPE_VECTOR) {
  675. BuildVectorOfTable(field, code_ptr);
  676. }
  677. }
  678. GetEndOffsetOnTable(struct_def, code_ptr);
  679. }
  680. // Generate struct or table methods.
  681. void GenStruct(const StructDef &struct_def,
  682. std::string *code_ptr) {
  683. if (struct_def.generated) return;
  684. GenComment(struct_def.doc_comment, code_ptr, nullptr);
  685. BeginClass(struct_def, code_ptr);
  686. if (!struct_def.fixed) {
  687. // Generate a special accessor for the table that has been declared as
  688. // the root type.
  689. NewRootTypeFromBuffer(struct_def, code_ptr);
  690. }
  691. std::string &code = *code_ptr;
  692. if (!struct_def.fixed) {
  693. if (parser_.file_identifier_.length()) {
  694. // Return the identifier
  695. code += Indent + "public static function " + struct_def.name;
  696. code += "Identifier()\n";
  697. code += Indent + "{\n";
  698. code += Indent + Indent + "return \"";
  699. code += parser_.file_identifier_ + "\";\n";
  700. code += Indent + "}\n\n";
  701. // Check if a buffer has the identifier.
  702. code += Indent + "public static function " + struct_def.name;
  703. code += "BufferHasIdentifier(ByteBuffer $buf)\n";
  704. code += Indent + "{\n";
  705. code += Indent + Indent + "return self::";
  706. code += "__has_identifier($buf, self::";
  707. code += struct_def.name + "Identifier());\n";
  708. code += Indent + "}\n\n";
  709. }
  710. if (parser_.file_extension_.length()) {
  711. // Return the extension
  712. code += Indent + "public static function " + struct_def.name;
  713. code += "Extension()\n";
  714. code += Indent + "{\n";
  715. code += Indent + Indent + "return \"" + parser_.file_extension_;
  716. code += "\";\n";
  717. code += Indent + "}\n\n";
  718. }
  719. }
  720. // Generate the Init method that sets the field in a pre-existing
  721. // accessor object. This is to allow object reuse.
  722. InitializeExisting(struct_def, code_ptr);
  723. for (auto it = struct_def.fields.vec.begin();
  724. it != struct_def.fields.vec.end();
  725. ++it) {
  726. auto &field = **it;
  727. if (field.deprecated) continue;
  728. GenStructAccessor(struct_def, field, code_ptr);
  729. }
  730. if (struct_def.fixed) {
  731. // create a struct constructor function
  732. GenStructBuilder(struct_def, code_ptr);
  733. } else {
  734. // Create a set of functions that allow table construction.
  735. GenTableBuilders(struct_def, code_ptr);
  736. }
  737. EndClass(code_ptr);
  738. }
  739. // Generate enum declarations.
  740. static void GenEnum(const EnumDef &enum_def, std::string *code_ptr) {
  741. if (enum_def.generated) return;
  742. GenComment(enum_def.doc_comment, code_ptr, nullptr);
  743. BeginEnum(enum_def.name, code_ptr);
  744. for (auto it = enum_def.vals.vec.begin();
  745. it != enum_def.vals.vec.end();
  746. ++it) {
  747. auto &ev = **it;
  748. GenComment(ev.doc_comment, code_ptr, nullptr);
  749. EnumMember(ev, code_ptr);
  750. }
  751. std::string &code = *code_ptr;
  752. code += "\n";
  753. code += Indent + "private static $names = array(\n";
  754. for (auto it = enum_def.vals.vec.begin();
  755. it != enum_def.vals.vec.end(); ++it) {
  756. auto &ev = **it;
  757. code += Indent + Indent + "\"" + ev.name + "\",\n";
  758. }
  759. code += Indent + ");\n\n";
  760. code += Indent + "public static function Name($e)\n";
  761. code += Indent + "{\n";
  762. code += Indent + Indent + "if (!isset(self::$names[$e])) {\n";
  763. code += Indent + Indent + Indent + "throw new \\Exception();\n";
  764. code += Indent + Indent + "}\n";
  765. code += Indent + Indent + "return self::$names[$e];\n";
  766. code += Indent + "}\n";
  767. EndEnum(code_ptr);
  768. }
  769. // Returns the function name that is able to read a value of the given type.
  770. static std::string GenGetter(const Type &type) {
  771. switch (type.base_type) {
  772. case BASE_TYPE_STRING: return "__string";
  773. case BASE_TYPE_STRUCT: return "__struct";
  774. case BASE_TYPE_UNION: return "__union";
  775. case BASE_TYPE_VECTOR: return GenGetter(type.VectorType());
  776. default:
  777. return "Get";
  778. }
  779. }
  780. // Returns the method name for use with add/put calls.
  781. static std::string GenMethod(const FieldDef &field) {
  782. return IsScalar(field.value.type.base_type)
  783. ? MakeCamel(GenTypeBasic(field.value.type))
  784. : (IsStruct(field.value.type) ? "Struct" : "Offset");
  785. }
  786. static std::string GenTypeBasic(const Type &type) {
  787. static const char *ctypename[] = {
  788. #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \
  789. #NTYPE,
  790. FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
  791. #undef FLATBUFFERS_TD
  792. };
  793. return ctypename[type.base_type];
  794. }
  795. std::string GenDefaultValue(const Value &value) {
  796. if (value.type.enum_def) {
  797. if (auto val = value.type.enum_def->ReverseLookup(
  798. atoi(value.constant.c_str()), false)) {
  799. return WrapInNameSpace(*value.type.enum_def) + "::" + val->name;
  800. }
  801. }
  802. switch (value.type.base_type) {
  803. case BASE_TYPE_BOOL:
  804. return value.constant == "0" ? "false" : "true";
  805. case BASE_TYPE_STRING:
  806. return "null";
  807. case BASE_TYPE_LONG:
  808. case BASE_TYPE_ULONG:
  809. if (value.constant != "0") {
  810. int64_t constant = StringToInt(value.constant.c_str());
  811. return NumToString(constant);
  812. }
  813. return "0";
  814. default:
  815. return value.constant;
  816. }
  817. }
  818. static std::string GenTypePointer(const Type &type) {
  819. switch (type.base_type) {
  820. case BASE_TYPE_STRING:
  821. return "string";
  822. case BASE_TYPE_VECTOR:
  823. return GenTypeGet(type.VectorType());
  824. case BASE_TYPE_STRUCT:
  825. return type.struct_def->name;
  826. case BASE_TYPE_UNION:
  827. // fall through
  828. default:
  829. return "Table";
  830. }
  831. }
  832. static std::string GenTypeGet(const Type &type) {
  833. return IsScalar(type.base_type)
  834. ? GenTypeBasic(type)
  835. : GenTypePointer(type);
  836. }
  837. // Create a struct with a builder and the struct's arguments.
  838. static void GenStructBuilder(const StructDef &struct_def,
  839. std::string *code_ptr) {
  840. std::string &code = *code_ptr;
  841. code += "\n";
  842. code += Indent + "/**\n";
  843. code += Indent + " * @return int offset\n";
  844. code += Indent + " */\n";
  845. code += Indent + "public static function create" + struct_def.name;
  846. code += "(FlatBufferBuilder $builder";
  847. StructBuilderArgs(struct_def, "", code_ptr);
  848. code += ")\n";
  849. code += Indent + "{\n";
  850. StructBuilderBody(struct_def, "", code_ptr);
  851. code += Indent + Indent + "return $builder->offset();\n";
  852. code += Indent + "}\n";
  853. }
  854. };
  855. } // namespace php
  856. bool GeneratePhp(const Parser &parser, const std::string &path,
  857. const std::string &file_name) {
  858. php::PhpGenerator generator(parser, path, file_name);
  859. return generator.generate();
  860. }
  861. } // namespace flatbuffers