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 17 // independent from idl_parser, since this code is not needed for most clients 18 19 #include <string> 20 21 #include "flatbuffers/flatbuffers.h" 22 #include "flatbuffers/idl.h" 23 #include "flatbuffers/util.h" 24 #include "flatbuffers/code_generators.h" 25 26 namespace flatbuffers { 27 namespace python { 28 29 static std::string GenGetter(const Type &type); 30 static std::string GenMethod(const FieldDef &field); 31 static void GenStructBuilder(const StructDef &struct_def, 32 std::string *code_ptr); 33 static void GenReceiver(const StructDef &struct_def, std::string *code_ptr); 34 static std::string GenTypeBasic(const Type &type); 35 static std::string GenTypeGet(const Type &type); 36 static std::string TypeName(const FieldDef &field); 37 38 39 // Hardcode spaces per indentation. 40 const std::string Indent = " "; 41 42 // Most field accessors need to retrieve and test the field offset first, 43 // this is the prefix code for that. 44 std::string OffsetPrefix(const FieldDef &field) { 45 return "\n" + Indent + Indent + 46 "o = flatbuffers.number_types.UOffsetTFlags.py_type" + 47 "(self._tab.Offset(" + 48 NumToString(field.value.offset) + 49 "))\n" + Indent + Indent + "if o != 0:\n"; 50 } 51 52 // Begin a class declaration. 53 static void BeginClass(const StructDef &struct_def, std::string *code_ptr) { 54 std::string &code = *code_ptr; 55 code += "class " + struct_def.name + "(object):\n"; 56 code += Indent + "__slots__ = ['_tab']"; 57 code += "\n\n"; 58 } 59 60 // Begin enum code with a class declaration. 61 static void BeginEnum(const std::string class_name, std::string *code_ptr) { 62 std::string &code = *code_ptr; 63 code += "class " + class_name + "(object):\n"; 64 } 65 66 // A single enum member. 67 static void EnumMember(const EnumVal ev, std::string *code_ptr) { 68 std::string &code = *code_ptr; 69 code += Indent; 70 code += ev.name; 71 code += " = "; 72 code += NumToString(ev.value) + "\n"; 73 } 74 75 // End enum code. 76 static void EndEnum(std::string *code_ptr) { 77 std::string &code = *code_ptr; 78 code += "\n"; 79 } 80 81 // Initialize a new struct or table from existing data. 82 static void NewRootTypeFromBuffer(const StructDef &struct_def, 83 std::string *code_ptr) { 84 std::string &code = *code_ptr; 85 86 code += Indent + "@classmethod\n"; 87 code += Indent + "def GetRootAs"; 88 code += struct_def.name; 89 code += "(cls, buf, offset):"; 90 code += "\n"; 91 code += Indent + Indent; 92 code += "n = flatbuffers.encode.Get"; 93 code += "(flatbuffers.packer.uoffset, buf, offset)\n"; 94 code += Indent + Indent + "x = " + struct_def.name + "()\n"; 95 code += Indent + Indent + "x.Init(buf, n + offset)\n"; 96 code += Indent + Indent + "return x\n"; 97 code += "\n"; 98 } 99 100 // Initialize an existing object with other data, to avoid an allocation. 101 static void InitializeExisting(const StructDef &struct_def, 102 std::string *code_ptr) { 103 std::string &code = *code_ptr; 104 105 GenReceiver(struct_def, code_ptr); 106 code += "Init(self, buf, pos):\n"; 107 code += Indent + Indent + "self._tab = flatbuffers.table.Table(buf, pos)\n"; 108 code += "\n"; 109 } 110 111 // Get the length of a vector. 112 static void GetVectorLen(const StructDef &struct_def, 113 const FieldDef &field, 114 std::string *code_ptr) { 115 std::string &code = *code_ptr; 116 117 GenReceiver(struct_def, code_ptr); 118 code += MakeCamel(field.name) + "Length(self"; 119 code += "):" + OffsetPrefix(field); 120 code += Indent + Indent + Indent + "return self._tab.VectorLen(o)\n"; 121 code += Indent + Indent + "return 0\n\n"; 122 } 123 124 // Get the value of a struct's scalar. 125 static void GetScalarFieldOfStruct(const StructDef &struct_def, 126 const FieldDef &field, 127 std::string *code_ptr) { 128 std::string &code = *code_ptr; 129 std::string getter = GenGetter(field.value.type); 130 GenReceiver(struct_def, code_ptr); 131 code += MakeCamel(field.name); 132 code += "(self): return " + getter; 133 code += "self._tab.Pos + flatbuffers.number_types.UOffsetTFlags.py_type("; 134 code += NumToString(field.value.offset) + "))\n"; 135 } 136 137 // Get the value of a table's scalar. 138 static void GetScalarFieldOfTable(const StructDef &struct_def, 139 const FieldDef &field, 140 std::string *code_ptr) { 141 std::string &code = *code_ptr; 142 std::string getter = GenGetter(field.value.type); 143 GenReceiver(struct_def, code_ptr); 144 code += MakeCamel(field.name); 145 code += "(self):"; 146 code += OffsetPrefix(field); 147 code += Indent + Indent + Indent + "return " + getter; 148 code += "o + self._tab.Pos)\n"; 149 code += Indent + Indent + "return " + field.value.constant + "\n\n"; 150 } 151 152 // Get a struct by initializing an existing struct. 153 // Specific to Struct. 154 static void GetStructFieldOfStruct(const StructDef &struct_def, 155 const FieldDef &field, 156 std::string *code_ptr) { 157 std::string &code = *code_ptr; 158 GenReceiver(struct_def, code_ptr); 159 code += MakeCamel(field.name); 160 code += "(self, obj):\n"; 161 code += Indent + Indent + "obj.Init(self._tab.Bytes, self._tab.Pos + "; 162 code += NumToString(field.value.offset) + ")"; 163 code += "\n" + Indent + Indent + "return obj\n\n"; 164 } 165 166 // Get a struct by initializing an existing struct. 167 // Specific to Table. 168 static void GetStructFieldOfTable(const StructDef &struct_def, 169 const FieldDef &field, 170 std::string *code_ptr) { 171 std::string &code = *code_ptr; 172 GenReceiver(struct_def, code_ptr); 173 code += MakeCamel(field.name); 174 code += "(self):"; 175 code += OffsetPrefix(field); 176 if (field.value.type.struct_def->fixed) { 177 code += Indent + Indent + Indent + "x = o + self._tab.Pos\n"; 178 } else { 179 code += Indent + Indent + Indent; 180 code += "x = self._tab.Indirect(o + self._tab.Pos)\n"; 181 } 182 code += Indent + Indent + Indent; 183 code += "from ." + TypeName(field) + " import " + TypeName(field) + "\n"; 184 code += Indent + Indent + Indent + "obj = " + TypeName(field) + "()\n"; 185 code += Indent + Indent + Indent + "obj.Init(self._tab.Bytes, x)\n"; 186 code += Indent + Indent + Indent + "return obj\n"; 187 code += Indent + Indent + "return None\n\n"; 188 } 189 190 // Get the value of a string. 191 static void GetStringField(const StructDef &struct_def, 192 const FieldDef &field, 193 std::string *code_ptr) { 194 std::string &code = *code_ptr; 195 GenReceiver(struct_def, code_ptr); 196 code += MakeCamel(field.name); 197 code += "(self):"; 198 code += OffsetPrefix(field); 199 code += Indent + Indent + Indent + "return " + GenGetter(field.value.type); 200 code += "o + self._tab.Pos)\n"; 201 code += Indent + Indent + "return bytes()\n\n"; 202 } 203 204 // Get the value of a union from an object. 205 static void GetUnionField(const StructDef &struct_def, 206 const FieldDef &field, 207 std::string *code_ptr) { 208 std::string &code = *code_ptr; 209 GenReceiver(struct_def, code_ptr); 210 code += MakeCamel(field.name) + "(self):"; 211 code += OffsetPrefix(field); 212 213 // TODO(rw): this works and is not the good way to it: 214 bool is_native_table = TypeName(field) == "*flatbuffers.Table"; 215 if (is_native_table) { 216 code += Indent + Indent + Indent + "from flatbuffers.table import Table\n"; 217 } else { 218 code += Indent + Indent + Indent; 219 code += "from ." + TypeName(field) + " import " + TypeName(field) + "\n"; 220 } 221 code += Indent + Indent + Indent + "obj = Table(bytearray(), 0)\n"; 222 code += Indent + Indent + Indent + GenGetter(field.value.type); 223 code += "obj, o)\n" + Indent + Indent + Indent + "return obj\n"; 224 code += Indent + Indent + "return None\n\n"; 225 } 226 227 // Get the value of a vector's struct member. 228 static void GetMemberOfVectorOfStruct(const StructDef &struct_def, 229 const FieldDef &field, 230 std::string *code_ptr) { 231 std::string &code = *code_ptr; 232 auto vectortype = field.value.type.VectorType(); 233 234 GenReceiver(struct_def, code_ptr); 235 code += MakeCamel(field.name); 236 code += "(self, j):" + OffsetPrefix(field); 237 code += Indent + Indent + Indent + "x = self._tab.Vector(o)\n"; 238 code += Indent + Indent + Indent; 239 code += "x += flatbuffers.number_types.UOffsetTFlags.py_type(j) * "; 240 code += NumToString(InlineSize(vectortype)) + "\n"; 241 if (!(vectortype.struct_def->fixed)) { 242 code += Indent + Indent + Indent + "x = self._tab.Indirect(x)\n"; 243 } 244 code += Indent + Indent + Indent; 245 code += "from ." + TypeName(field) + " import " + TypeName(field) + "\n"; 246 code += Indent + Indent + Indent + "obj = " + TypeName(field) + "()\n"; 247 code += Indent + Indent + Indent + "obj.Init(self._tab.Bytes, x)\n"; 248 code += Indent + Indent + Indent + "return obj\n"; 249 code += Indent + Indent + "return None\n\n"; 250 } 251 252 // Get the value of a vector's non-struct member. Uses a named return 253 // argument to conveniently set the zero value for the result. 254 static void GetMemberOfVectorOfNonStruct(const StructDef &struct_def, 255 const FieldDef &field, 256 std::string *code_ptr) { 257 std::string &code = *code_ptr; 258 auto vectortype = field.value.type.VectorType(); 259 260 GenReceiver(struct_def, code_ptr); 261 code += MakeCamel(field.name); 262 code += "(self, j):"; 263 code += OffsetPrefix(field); 264 code += Indent + Indent + Indent + "a = self._tab.Vector(o)\n"; 265 code += Indent + Indent + Indent; 266 code += "return " + GenGetter(field.value.type); 267 code += "a + flatbuffers.number_types.UOffsetTFlags.py_type(j * "; 268 code += NumToString(InlineSize(vectortype)) + "))\n"; 269 if (vectortype.base_type == BASE_TYPE_STRING) { 270 code += Indent + Indent + "return \"\"\n"; 271 } else { 272 code += Indent + Indent + "return 0\n"; 273 } 274 code += "\n"; 275 } 276 277 // Returns a non-struct vector as a numpy array. Much faster 278 // than iterating over the vector element by element. 279 static void GetVectorOfNonStructAsNumpy(const StructDef &struct_def, 280 const FieldDef &field, 281 std::string *code_ptr) { 282 std::string &code = *code_ptr; 283 auto vectortype = field.value.type.VectorType(); 284 285 // Currently, we only support accessing as numpy array if 286 // the vector type is a scalar. 287 if (!(IsScalar(vectortype.base_type))) { 288 return; 289 } 290 291 GenReceiver(struct_def, code_ptr); 292 code += MakeCamel(field.name) + "AsNumpy(self):"; 293 code += OffsetPrefix(field); 294 295 code += Indent + Indent + Indent; 296 code += "return "; 297 code += "self._tab.GetVectorAsNumpy(flatbuffers.number_types."; 298 code += MakeCamel(GenTypeGet(field.value.type)); 299 code += "Flags, o)\n"; 300 301 if (vectortype.base_type == BASE_TYPE_STRING) { 302 code += Indent + Indent + "return \"\"\n"; 303 } else { 304 code += Indent + Indent + "return 0\n"; 305 } 306 code += "\n"; 307 } 308 309 // Begin the creator function signature. 310 static void BeginBuilderArgs(const StructDef &struct_def, 311 std::string *code_ptr) { 312 std::string &code = *code_ptr; 313 314 code += "\n"; 315 code += "def Create" + struct_def.name; 316 code += "(builder"; 317 } 318 319 // Recursively generate arguments for a constructor, to deal with nested 320 // structs. 321 static void StructBuilderArgs(const StructDef &struct_def, 322 const char *nameprefix, 323 std::string *code_ptr) { 324 for (auto it = struct_def.fields.vec.begin(); 325 it != struct_def.fields.vec.end(); 326 ++it) { 327 auto &field = **it; 328 if (IsStruct(field.value.type)) { 329 // Generate arguments for a struct inside a struct. To ensure names 330 // don't clash, and to make it obvious these arguments are constructing 331 // a nested struct, prefix the name with the field name. 332 StructBuilderArgs(*field.value.type.struct_def, 333 (nameprefix + (field.name + "_")).c_str(), 334 code_ptr); 335 } else { 336 std::string &code = *code_ptr; 337 code += (std::string)", " + nameprefix; 338 code += MakeCamel(field.name, false); 339 } 340 } 341 } 342 343 // End the creator function signature. 344 static void EndBuilderArgs(std::string *code_ptr) { 345 std::string &code = *code_ptr; 346 code += "):\n"; 347 } 348 349 // Recursively generate struct construction statements and instert manual 350 // padding. 351 static void StructBuilderBody(const StructDef &struct_def, 352 const char *nameprefix, 353 std::string *code_ptr) { 354 std::string &code = *code_ptr; 355 code += " builder.Prep(" + NumToString(struct_def.minalign) + ", "; 356 code += NumToString(struct_def.bytesize) + ")\n"; 357 for (auto it = struct_def.fields.vec.rbegin(); 358 it != struct_def.fields.vec.rend(); 359 ++it) { 360 auto &field = **it; 361 if (field.padding) 362 code += " builder.Pad(" + NumToString(field.padding) + ")\n"; 363 if (IsStruct(field.value.type)) { 364 StructBuilderBody(*field.value.type.struct_def, 365 (nameprefix + (field.name + "_")).c_str(), 366 code_ptr); 367 } else { 368 code += " builder.Prepend" + GenMethod(field) + "("; 369 code += nameprefix + MakeCamel(field.name, false) + ")\n"; 370 } 371 } 372 } 373 374 static void EndBuilderBody(std::string *code_ptr) { 375 std::string &code = *code_ptr; 376 code += " return builder.Offset()\n"; 377 } 378 379 // Get the value of a table's starting offset. 380 static void GetStartOfTable(const StructDef &struct_def, 381 std::string *code_ptr) { 382 std::string &code = *code_ptr; 383 code += "def " + struct_def.name + "Start"; 384 code += "(builder): "; 385 code += "builder.StartObject("; 386 code += NumToString(struct_def.fields.vec.size()); 387 code += ")\n"; 388 } 389 390 // Set the value of a table's field. 391 static void BuildFieldOfTable(const StructDef &struct_def, 392 const FieldDef &field, 393 const size_t offset, 394 std::string *code_ptr) { 395 std::string &code = *code_ptr; 396 code += "def " + struct_def.name + "Add" + MakeCamel(field.name); 397 code += "(builder, "; 398 code += MakeCamel(field.name, false); 399 code += "): "; 400 code += "builder.Prepend"; 401 code += GenMethod(field) + "Slot("; 402 code += NumToString(offset) + ", "; 403 if (!IsScalar(field.value.type.base_type) && (!struct_def.fixed)) { 404 code += "flatbuffers.number_types.UOffsetTFlags.py_type"; 405 code += "("; 406 code += MakeCamel(field.name, false) + ")"; 407 } else { 408 code += MakeCamel(field.name, false); 409 } 410 code += ", " + field.value.constant; 411 code += ")\n"; 412 } 413 414 // Set the value of one of the members of a table's vector. 415 static void BuildVectorOfTable(const StructDef &struct_def, 416 const FieldDef &field, 417 std::string *code_ptr) { 418 std::string &code = *code_ptr; 419 code += "def " + struct_def.name + "Start"; 420 code += MakeCamel(field.name); 421 code += "Vector(builder, numElems): return builder.StartVector("; 422 auto vector_type = field.value.type.VectorType(); 423 auto alignment = InlineAlignment(vector_type); 424 auto elem_size = InlineSize(vector_type); 425 code += NumToString(elem_size); 426 code += ", numElems, " + NumToString(alignment); 427 code += ")\n"; 428 } 429 430 // Get the offset of the end of a table. 431 static void GetEndOffsetOnTable(const StructDef &struct_def, 432 std::string *code_ptr) { 433 std::string &code = *code_ptr; 434 code += "def " + struct_def.name + "End"; 435 code += "(builder): "; 436 code += "return builder.EndObject()\n"; 437 } 438 439 // Generate the receiver for function signatures. 440 static void GenReceiver(const StructDef &struct_def, std::string *code_ptr) { 441 std::string &code = *code_ptr; 442 code += Indent + "# " + struct_def.name + "\n"; 443 code += Indent + "def "; 444 } 445 446 // Generate a struct field, conditioned on its child type(s). 447 static void GenStructAccessor(const StructDef &struct_def, 448 const FieldDef &field, 449 std::string *code_ptr) { 450 GenComment(field.doc_comment, code_ptr, nullptr, "# "); 451 if (IsScalar(field.value.type.base_type)) { 452 if (struct_def.fixed) { 453 GetScalarFieldOfStruct(struct_def, field, code_ptr); 454 } else { 455 GetScalarFieldOfTable(struct_def, field, code_ptr); 456 } 457 } else { 458 switch (field.value.type.base_type) { 459 case BASE_TYPE_STRUCT: 460 if (struct_def.fixed) { 461 GetStructFieldOfStruct(struct_def, field, code_ptr); 462 } else { 463 GetStructFieldOfTable(struct_def, field, code_ptr); 464 } 465 break; 466 case BASE_TYPE_STRING: 467 GetStringField(struct_def, field, code_ptr); 468 break; 469 case BASE_TYPE_VECTOR: { 470 auto vectortype = field.value.type.VectorType(); 471 if (vectortype.base_type == BASE_TYPE_STRUCT) { 472 GetMemberOfVectorOfStruct(struct_def, field, code_ptr); 473 } else { 474 GetMemberOfVectorOfNonStruct(struct_def, field, code_ptr); 475 GetVectorOfNonStructAsNumpy(struct_def, field, code_ptr); 476 } 477 break; 478 } 479 case BASE_TYPE_UNION: 480 GetUnionField(struct_def, field, code_ptr); 481 break; 482 default: 483 assert(0); 484 } 485 } 486 if (field.value.type.base_type == BASE_TYPE_VECTOR) { 487 GetVectorLen(struct_def, field, code_ptr); 488 } 489 } 490 491 // Generate table constructors, conditioned on its members' types. 492 static void GenTableBuilders(const StructDef &struct_def, 493 std::string *code_ptr) { 494 GetStartOfTable(struct_def, code_ptr); 495 496 for (auto it = struct_def.fields.vec.begin(); 497 it != struct_def.fields.vec.end(); 498 ++it) { 499 auto &field = **it; 500 if (field.deprecated) continue; 501 502 auto offset = it - struct_def.fields.vec.begin(); 503 BuildFieldOfTable(struct_def, field, offset, code_ptr); 504 if (field.value.type.base_type == BASE_TYPE_VECTOR) { 505 BuildVectorOfTable(struct_def, field, code_ptr); 506 } 507 } 508 509 GetEndOffsetOnTable(struct_def, code_ptr); 510 } 511 512 // Generate struct or table methods. 513 static void GenStruct(const StructDef &struct_def, 514 std::string *code_ptr) { 515 if (struct_def.generated) return; 516 517 GenComment(struct_def.doc_comment, code_ptr, nullptr, "# "); 518 BeginClass(struct_def, code_ptr); 519 if (!struct_def.fixed) { 520 // Generate a special accessor for the table that has been declared as 521 // the root type. 522 NewRootTypeFromBuffer(struct_def, code_ptr); 523 } 524 // Generate the Init method that sets the field in a pre-existing 525 // accessor object. This is to allow object reuse. 526 InitializeExisting(struct_def, code_ptr); 527 for (auto it = struct_def.fields.vec.begin(); 528 it != struct_def.fields.vec.end(); 529 ++it) { 530 auto &field = **it; 531 if (field.deprecated) continue; 532 533 GenStructAccessor(struct_def, field, code_ptr); 534 } 535 536 if (struct_def.fixed) { 537 // create a struct constructor function 538 GenStructBuilder(struct_def, code_ptr); 539 } else { 540 // Create a set of functions that allow table construction. 541 GenTableBuilders(struct_def, code_ptr); 542 } 543 } 544 545 // Generate enum declarations. 546 static void GenEnum(const EnumDef &enum_def, std::string *code_ptr) { 547 if (enum_def.generated) return; 548 549 GenComment(enum_def.doc_comment, code_ptr, nullptr, "# "); 550 BeginEnum(enum_def.name, code_ptr); 551 for (auto it = enum_def.vals.vec.begin(); 552 it != enum_def.vals.vec.end(); 553 ++it) { 554 auto &ev = **it; 555 GenComment(ev.doc_comment, code_ptr, nullptr, "# "); 556 EnumMember(ev, code_ptr); 557 } 558 EndEnum(code_ptr); 559 } 560 561 // Returns the function name that is able to read a value of the given type. 562 static std::string GenGetter(const Type &type) { 563 switch (type.base_type) { 564 case BASE_TYPE_STRING: return "self._tab.String("; 565 case BASE_TYPE_UNION: return "self._tab.Union("; 566 case BASE_TYPE_VECTOR: return GenGetter(type.VectorType()); 567 default: 568 return "self._tab.Get(flatbuffers.number_types." + \ 569 MakeCamel(GenTypeGet(type)) + \ 570 "Flags, "; 571 } 572 } 573 574 // Returns the method name for use with add/put calls. 575 static std::string GenMethod(const FieldDef &field) { 576 return IsScalar(field.value.type.base_type) 577 ? MakeCamel(GenTypeBasic(field.value.type)) 578 : (IsStruct(field.value.type) ? "Struct" : "UOffsetTRelative"); 579 } 580 581 static std::string GenTypeBasic(const Type &type) { 582 static const char *ctypename[] = { 583 #define FLATBUFFERS_TD(ENUM, IDLTYPE, \ 584 CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \ 585 #PTYPE, 586 FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) 587 #undef FLATBUFFERS_TD 588 }; 589 return ctypename[type.base_type]; 590 } 591 592 static std::string GenTypePointer(const Type &type) { 593 switch (type.base_type) { 594 case BASE_TYPE_STRING: 595 return "string"; 596 case BASE_TYPE_VECTOR: 597 return GenTypeGet(type.VectorType()); 598 case BASE_TYPE_STRUCT: 599 return type.struct_def->name; 600 case BASE_TYPE_UNION: 601 // fall through 602 default: 603 return "*flatbuffers.Table"; 604 } 605 } 606 607 static std::string GenTypeGet(const Type &type) { 608 return IsScalar(type.base_type) 609 ? GenTypeBasic(type) 610 : GenTypePointer(type); 611 } 612 613 static std::string TypeName(const FieldDef &field) { 614 return GenTypeGet(field.value.type); 615 } 616 617 // Create a struct with a builder and the struct's arguments. 618 static void GenStructBuilder(const StructDef &struct_def, 619 std::string *code_ptr) { 620 BeginBuilderArgs(struct_def, code_ptr); 621 StructBuilderArgs(struct_def, "", code_ptr); 622 EndBuilderArgs(code_ptr); 623 624 StructBuilderBody(struct_def, "", code_ptr); 625 EndBuilderBody(code_ptr); 626 } 627 628 class PythonGenerator : public BaseGenerator { 629 public: 630 PythonGenerator(const Parser &parser, const std::string &path, 631 const std::string &file_name) 632 : BaseGenerator(parser, path, file_name, "" /* not used */, 633 "" /* not used */){}; 634 bool generate() { 635 if (!generateEnums()) return false; 636 if (!generateStructs()) return false; 637 return true; 638 } 639 640 private: 641 bool generateEnums() { 642 for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end(); 643 ++it) { 644 auto &enum_def = **it; 645 std::string enumcode; 646 GenEnum(enum_def, &enumcode); 647 if (!SaveType(enum_def, enumcode, false)) return false; 648 } 649 return true; 650 } 651 652 bool generateStructs() { 653 for (auto it = parser_.structs_.vec.begin(); 654 it != parser_.structs_.vec.end(); ++it) { 655 auto &struct_def = **it; 656 std::string declcode; 657 GenStruct(struct_def, &declcode); 658 if (!SaveType(struct_def, declcode, true)) return false; 659 } 660 return true; 661 } 662 663 // Begin by declaring namespace and imports. 664 void BeginFile(const std::string name_space_name, const bool needs_imports, 665 std::string *code_ptr) { 666 std::string &code = *code_ptr; 667 code = code + "# " + FlatBuffersGeneratedWarning() + "\n\n"; 668 code += "# namespace: " + name_space_name + "\n\n"; 669 if (needs_imports) { 670 code += "import flatbuffers\n\n"; 671 } 672 } 673 674 // Save out the generated code for a Python Table type. 675 bool SaveType(const Definition &def, const std::string &classcode, 676 bool needs_imports) { 677 if (!classcode.length()) return true; 678 679 std::string namespace_dir = path_; 680 auto &namespaces = def.defined_namespace->components; 681 for (auto it = namespaces.begin(); it != namespaces.end(); ++it) { 682 if (it != namespaces.begin()) namespace_dir += kPathSeparator; 683 namespace_dir += *it; 684 std::string init_py_filename = namespace_dir + "/__init__.py"; 685 SaveFile(init_py_filename.c_str(), "", false); 686 } 687 688 std::string code = ""; 689 BeginFile(LastNamespacePart(*def.defined_namespace), needs_imports, &code); 690 code += classcode; 691 std::string filename = NamespaceDir(*def.defined_namespace) + 692 def.name + ".py"; 693 return SaveFile(filename.c_str(), code, false); 694 } 695 }; 696 697 } // namespace python 698 699 bool GeneratePython(const Parser &parser, const std::string &path, 700 const std::string &file_name) { 701 python::PythonGenerator generator(parser, path, file_name); 702 return generator.generate(); 703 } 704 705 } // namespace flatbuffers 706