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 #include <algorithm> 18 #include <list> 19 #include <string> 20 21 #include <math.h> 22 23 #include "flatbuffers/idl.h" 24 #include "flatbuffers/util.h" 25 26 namespace flatbuffers { 27 28 const double kPi = 3.14159265358979323846; 29 30 const char *const kTypeNames[] = { 31 // clang-format off 32 #define FLATBUFFERS_TD(ENUM, IDLTYPE, \ 33 CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE) \ 34 IDLTYPE, 35 FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) 36 #undef FLATBUFFERS_TD 37 // clang-format on 38 nullptr 39 }; 40 41 const char kTypeSizes[] = { 42 // clang-format off 43 #define FLATBUFFERS_TD(ENUM, IDLTYPE, \ 44 CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE) \ 45 sizeof(CTYPE), 46 FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) 47 #undef FLATBUFFERS_TD 48 // clang-format on 49 }; 50 51 // The enums in the reflection schema should match the ones we use internally. 52 // Compare the last element to check if these go out of sync. 53 static_assert(BASE_TYPE_UNION == static_cast<BaseType>(reflection::Union), 54 "enums don't match"); 55 56 // Any parsing calls have to be wrapped in this macro, which automates 57 // handling of recursive error checking a bit. It will check the received 58 // CheckedError object, and return straight away on error. 59 #define ECHECK(call) \ 60 { \ 61 auto ce = (call); \ 62 if (ce.Check()) return ce; \ 63 } 64 65 // These two functions are called hundreds of times below, so define a short 66 // form: 67 #define NEXT() ECHECK(Next()) 68 #define EXPECT(tok) ECHECK(Expect(tok)) 69 70 static bool ValidateUTF8(const std::string &str) { 71 const char *s = &str[0]; 72 const char *const sEnd = s + str.length(); 73 while (s < sEnd) { 74 if (FromUTF8(&s) < 0) { return false; } 75 } 76 return true; 77 } 78 79 // Convert an underscore_based_indentifier in to camelCase. 80 // Also uppercases the first character if first is true. 81 std::string MakeCamel(const std::string &in, bool first) { 82 std::string s; 83 for (size_t i = 0; i < in.length(); i++) { 84 if (!i && first) 85 s += static_cast<char>(toupper(in[0])); 86 else if (in[i] == '_' && i + 1 < in.length()) 87 s += static_cast<char>(toupper(in[++i])); 88 else 89 s += in[i]; 90 } 91 return s; 92 } 93 94 void DeserializeDoc( std::vector<std::string> &doc, 95 const Vector<Offset<String>> *documentation) { 96 if (documentation == nullptr) return; 97 for (uoffset_t index = 0; index < documentation->size(); index++) 98 doc.push_back(documentation->Get(index)->str()); 99 } 100 101 void Parser::Message(const std::string &msg) { 102 error_ = file_being_parsed_.length() ? AbsolutePath(file_being_parsed_) : ""; 103 // clang-format off 104 #ifdef _WIN32 // MSVC alike 105 error_ += 106 "(" + NumToString(line_) + ", " + NumToString(CursorPosition()) + ")"; 107 #else // gcc alike 108 if (file_being_parsed_.length()) error_ += ":"; 109 error_ += NumToString(line_) + ": " + NumToString(CursorPosition()); 110 #endif 111 // clang-format on 112 error_ += ": " + msg; 113 } 114 115 void Parser::Warning(const std::string &msg) { Message("warning: " + msg); } 116 117 CheckedError Parser::Error(const std::string &msg) { 118 Message("error: " + msg); 119 return CheckedError(true); 120 } 121 122 inline CheckedError NoError() { return CheckedError(false); } 123 124 CheckedError Parser::RecurseError() { 125 return Error("maximum parsing recursion of " + 126 NumToString(FLATBUFFERS_MAX_PARSING_DEPTH) + " reached"); 127 } 128 129 template<typename F> CheckedError Parser::Recurse(F f) { 130 if (recurse_protection_counter >= (FLATBUFFERS_MAX_PARSING_DEPTH)) 131 return RecurseError(); 132 recurse_protection_counter++; 133 auto ce = f(); 134 recurse_protection_counter--; 135 return ce; 136 } 137 138 CheckedError Parser::InvalidNumber(const char *number, const std::string &msg) { 139 return Error("invalid number: \"" + std::string(number) + "\"" + msg); 140 } 141 // atot: templated version of atoi/atof: convert a string to an instance of T. 142 template<typename T> 143 inline CheckedError atot(const char *s, Parser &parser, T *val) { 144 auto done = StringToNumber(s, val); 145 if (done) return NoError(); 146 147 return parser.InvalidNumber( 148 s, (0 == *val) 149 ? "" 150 : (", constant does not fit [" + 151 NumToString(flatbuffers::numeric_limits<T>::lowest()) + "; " + 152 NumToString(flatbuffers::numeric_limits<T>::max()) + "]")); 153 } 154 template<> 155 inline CheckedError atot<Offset<void>>(const char *s, Parser &parser, 156 Offset<void> *val) { 157 (void)parser; 158 *val = Offset<void>(atoi(s)); 159 return NoError(); 160 } 161 162 std::string Namespace::GetFullyQualifiedName(const std::string &name, 163 size_t max_components) const { 164 // Early exit if we don't have a defined namespace. 165 if (components.empty() || !max_components) { return name; } 166 std::string stream_str; 167 for (size_t i = 0; i < std::min(components.size(), max_components); i++) { 168 if (i) { stream_str += '.'; } 169 stream_str += std::string(components[i]); 170 } 171 if (name.length()) { 172 stream_str += '.'; 173 stream_str += name; 174 } 175 return stream_str; 176 } 177 178 // Declare tokens we'll use. Single character tokens are represented by their 179 // ascii character code (e.g. '{'), others above 256. 180 // clang-format off 181 #define FLATBUFFERS_GEN_TOKENS(TD) \ 182 TD(Eof, 256, "end of file") \ 183 TD(StringConstant, 257, "string constant") \ 184 TD(IntegerConstant, 258, "integer constant") \ 185 TD(FloatConstant, 259, "float constant") \ 186 TD(Identifier, 260, "identifier") 187 #ifdef __GNUC__ 188 __extension__ // Stop GCC complaining about trailing comma with -Wpendantic. 189 #endif 190 enum { 191 #define FLATBUFFERS_TOKEN(NAME, VALUE, STRING) kToken ## NAME = VALUE, 192 FLATBUFFERS_GEN_TOKENS(FLATBUFFERS_TOKEN) 193 #undef FLATBUFFERS_TOKEN 194 }; 195 196 static std::string TokenToString(int t) { 197 static const char * const tokens[] = { 198 #define FLATBUFFERS_TOKEN(NAME, VALUE, STRING) STRING, 199 FLATBUFFERS_GEN_TOKENS(FLATBUFFERS_TOKEN) 200 #undef FLATBUFFERS_TOKEN 201 #define FLATBUFFERS_TD(ENUM, IDLTYPE, \ 202 CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE) \ 203 IDLTYPE, 204 FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) 205 #undef FLATBUFFERS_TD 206 }; 207 if (t < 256) { // A single ascii char token. 208 std::string s; 209 s.append(1, static_cast<char>(t)); 210 return s; 211 } else { // Other tokens. 212 return tokens[t - 256]; 213 } 214 } 215 // clang-format on 216 217 std::string Parser::TokenToStringId(int t) const { 218 return t == kTokenIdentifier ? attribute_ : TokenToString(t); 219 } 220 221 // Parses exactly nibbles worth of hex digits into a number, or error. 222 CheckedError Parser::ParseHexNum(int nibbles, uint64_t *val) { 223 FLATBUFFERS_ASSERT(nibbles > 0); 224 for (int i = 0; i < nibbles; i++) 225 if (!is_xdigit(cursor_[i])) 226 return Error("escape code must be followed by " + NumToString(nibbles) + 227 " hex digits"); 228 std::string target(cursor_, cursor_ + nibbles); 229 *val = StringToUInt(target.c_str(), 16); 230 cursor_ += nibbles; 231 return NoError(); 232 } 233 234 CheckedError Parser::SkipByteOrderMark() { 235 if (static_cast<unsigned char>(*cursor_) != 0xef) return NoError(); 236 cursor_++; 237 if (static_cast<unsigned char>(*cursor_) != 0xbb) 238 return Error("invalid utf-8 byte order mark"); 239 cursor_++; 240 if (static_cast<unsigned char>(*cursor_) != 0xbf) 241 return Error("invalid utf-8 byte order mark"); 242 cursor_++; 243 return NoError(); 244 } 245 246 static inline bool IsIdentifierStart(char c) { 247 return is_alpha(c) || (c == '_'); 248 } 249 250 CheckedError Parser::Next() { 251 doc_comment_.clear(); 252 bool seen_newline = cursor_ == source_; 253 attribute_.clear(); 254 attr_is_trivial_ascii_string_ = true; 255 for (;;) { 256 char c = *cursor_++; 257 token_ = c; 258 switch (c) { 259 case '\0': 260 cursor_--; 261 token_ = kTokenEof; 262 return NoError(); 263 case ' ': 264 case '\r': 265 case '\t': break; 266 case '\n': 267 MarkNewLine(); 268 seen_newline = true; 269 break; 270 case '{': 271 case '}': 272 case '(': 273 case ')': 274 case '[': 275 case ']': 276 case ',': 277 case ':': 278 case ';': 279 case '=': return NoError(); 280 case '\"': 281 case '\'': { 282 int unicode_high_surrogate = -1; 283 284 while (*cursor_ != c) { 285 if (*cursor_ < ' ' && static_cast<signed char>(*cursor_) >= 0) 286 return Error("illegal character in string constant"); 287 if (*cursor_ == '\\') { 288 attr_is_trivial_ascii_string_ = false; // has escape sequence 289 cursor_++; 290 if (unicode_high_surrogate != -1 && *cursor_ != 'u') { 291 return Error( 292 "illegal Unicode sequence (unpaired high surrogate)"); 293 } 294 switch (*cursor_) { 295 case 'n': 296 attribute_ += '\n'; 297 cursor_++; 298 break; 299 case 't': 300 attribute_ += '\t'; 301 cursor_++; 302 break; 303 case 'r': 304 attribute_ += '\r'; 305 cursor_++; 306 break; 307 case 'b': 308 attribute_ += '\b'; 309 cursor_++; 310 break; 311 case 'f': 312 attribute_ += '\f'; 313 cursor_++; 314 break; 315 case '\"': 316 attribute_ += '\"'; 317 cursor_++; 318 break; 319 case '\'': 320 attribute_ += '\''; 321 cursor_++; 322 break; 323 case '\\': 324 attribute_ += '\\'; 325 cursor_++; 326 break; 327 case '/': 328 attribute_ += '/'; 329 cursor_++; 330 break; 331 case 'x': { // Not in the JSON standard 332 cursor_++; 333 uint64_t val; 334 ECHECK(ParseHexNum(2, &val)); 335 attribute_ += static_cast<char>(val); 336 break; 337 } 338 case 'u': { 339 cursor_++; 340 uint64_t val; 341 ECHECK(ParseHexNum(4, &val)); 342 if (val >= 0xD800 && val <= 0xDBFF) { 343 if (unicode_high_surrogate != -1) { 344 return Error( 345 "illegal Unicode sequence (multiple high surrogates)"); 346 } else { 347 unicode_high_surrogate = static_cast<int>(val); 348 } 349 } else if (val >= 0xDC00 && val <= 0xDFFF) { 350 if (unicode_high_surrogate == -1) { 351 return Error( 352 "illegal Unicode sequence (unpaired low surrogate)"); 353 } else { 354 int code_point = 0x10000 + 355 ((unicode_high_surrogate & 0x03FF) << 10) + 356 (val & 0x03FF); 357 ToUTF8(code_point, &attribute_); 358 unicode_high_surrogate = -1; 359 } 360 } else { 361 if (unicode_high_surrogate != -1) { 362 return Error( 363 "illegal Unicode sequence (unpaired high surrogate)"); 364 } 365 ToUTF8(static_cast<int>(val), &attribute_); 366 } 367 break; 368 } 369 default: return Error("unknown escape code in string constant"); 370 } 371 } else { // printable chars + UTF-8 bytes 372 if (unicode_high_surrogate != -1) { 373 return Error( 374 "illegal Unicode sequence (unpaired high surrogate)"); 375 } 376 // reset if non-printable 377 attr_is_trivial_ascii_string_ &= check_in_range(*cursor_, ' ', '~'); 378 379 attribute_ += *cursor_++; 380 } 381 } 382 if (unicode_high_surrogate != -1) { 383 return Error("illegal Unicode sequence (unpaired high surrogate)"); 384 } 385 cursor_++; 386 if (!attr_is_trivial_ascii_string_ && !opts.allow_non_utf8 && 387 !ValidateUTF8(attribute_)) { 388 return Error("illegal UTF-8 sequence"); 389 } 390 token_ = kTokenStringConstant; 391 return NoError(); 392 } 393 case '/': 394 if (*cursor_ == '/') { 395 const char *start = ++cursor_; 396 while (*cursor_ && *cursor_ != '\n' && *cursor_ != '\r') cursor_++; 397 if (*start == '/') { // documentation comment 398 if (!seen_newline) 399 return Error( 400 "a documentation comment should be on a line on its own"); 401 doc_comment_.push_back(std::string(start + 1, cursor_)); 402 } 403 break; 404 } else if (*cursor_ == '*') { 405 cursor_++; 406 // TODO: make nested. 407 while (*cursor_ != '*' || cursor_[1] != '/') { 408 if (*cursor_ == '\n') MarkNewLine(); 409 if (!*cursor_) return Error("end of file in comment"); 410 cursor_++; 411 } 412 cursor_ += 2; 413 break; 414 } 415 FLATBUFFERS_FALLTHROUGH(); // else fall thru 416 default: 417 const auto has_sign = (c == '+') || (c == '-'); 418 // '-'/'+' and following identifier - can be a predefined constant like: 419 // NAN, INF, PI, etc. 420 if (IsIdentifierStart(c) || (has_sign && IsIdentifierStart(*cursor_))) { 421 // Collect all chars of an identifier: 422 const char *start = cursor_ - 1; 423 while (IsIdentifierStart(*cursor_) || is_digit(*cursor_)) cursor_++; 424 attribute_.append(start, cursor_); 425 token_ = has_sign ? kTokenStringConstant : kTokenIdentifier; 426 return NoError(); 427 } 428 429 auto dot_lvl = (c == '.') ? 0 : 1; // dot_lvl==0 <=> exactly one '.' seen 430 if (!dot_lvl && !is_digit(*cursor_)) return NoError(); // enum? 431 // Parser accepts hexadecimal-floating-literal (see C++ 5.13.4). 432 if (is_digit(c) || has_sign || !dot_lvl) { 433 const auto start = cursor_ - 1; 434 auto start_digits = !is_digit(c) ? cursor_ : cursor_ - 1; 435 if (!is_digit(c) && is_digit(*cursor_)){ 436 start_digits = cursor_; // see digit in cursor_ position 437 c = *cursor_++; 438 } 439 // hex-float can't begind with '.' 440 auto use_hex = dot_lvl && (c == '0') && is_alpha_char(*cursor_, 'X'); 441 if (use_hex) start_digits = ++cursor_; // '0x' is the prefix, skip it 442 // Read an integer number or mantisa of float-point number. 443 do { 444 if (use_hex) { 445 while (is_xdigit(*cursor_)) cursor_++; 446 } else { 447 while (is_digit(*cursor_)) cursor_++; 448 } 449 } while ((*cursor_ == '.') && (++cursor_) && (--dot_lvl >= 0)); 450 // Exponent of float-point number. 451 if ((dot_lvl >= 0) && (cursor_ > start_digits)) { 452 // The exponent suffix of hexadecimal float number is mandatory. 453 if (use_hex && !dot_lvl) start_digits = cursor_; 454 if ((use_hex && is_alpha_char(*cursor_, 'P')) || 455 is_alpha_char(*cursor_, 'E')) { 456 dot_lvl = 0; // Emulate dot to signal about float-point number. 457 cursor_++; 458 if (*cursor_ == '+' || *cursor_ == '-') cursor_++; 459 start_digits = cursor_; // the exponent-part has to have digits 460 // Exponent is decimal integer number 461 while (is_digit(*cursor_)) cursor_++; 462 if (*cursor_ == '.') { 463 cursor_++; // If see a dot treat it as part of invalid number. 464 dot_lvl = -1; // Fall thru to Error(). 465 } 466 } 467 } 468 // Finalize. 469 if ((dot_lvl >= 0) && (cursor_ > start_digits)) { 470 attribute_.append(start, cursor_); 471 token_ = dot_lvl ? kTokenIntegerConstant : kTokenFloatConstant; 472 return NoError(); 473 } else { 474 return Error("invalid number: " + std::string(start, cursor_)); 475 } 476 } 477 std::string ch; 478 ch = c; 479 if (false == check_in_range(c, ' ', '~')) ch = "code: " + NumToString(c); 480 return Error("illegal character: " + ch); 481 } 482 } 483 } 484 485 // Check if a given token is next. 486 bool Parser::Is(int t) const { return t == token_; } 487 488 bool Parser::IsIdent(const char *id) const { 489 return token_ == kTokenIdentifier && attribute_ == id; 490 } 491 492 // Expect a given token to be next, consume it, or error if not present. 493 CheckedError Parser::Expect(int t) { 494 if (t != token_) { 495 return Error("expecting: " + TokenToString(t) + 496 " instead got: " + TokenToStringId(token_)); 497 } 498 NEXT(); 499 return NoError(); 500 } 501 502 CheckedError Parser::ParseNamespacing(std::string *id, std::string *last) { 503 while (Is('.')) { 504 NEXT(); 505 *id += "."; 506 *id += attribute_; 507 if (last) *last = attribute_; 508 EXPECT(kTokenIdentifier); 509 } 510 return NoError(); 511 } 512 513 EnumDef *Parser::LookupEnum(const std::string &id) { 514 // Search thru parent namespaces. 515 for (int components = static_cast<int>(current_namespace_->components.size()); 516 components >= 0; components--) { 517 auto ed = enums_.Lookup( 518 current_namespace_->GetFullyQualifiedName(id, components)); 519 if (ed) return ed; 520 } 521 return nullptr; 522 } 523 524 StructDef *Parser::LookupStruct(const std::string &id) const { 525 auto sd = structs_.Lookup(id); 526 if (sd) sd->refcount++; 527 return sd; 528 } 529 530 CheckedError Parser::ParseTypeIdent(Type &type) { 531 std::string id = attribute_; 532 EXPECT(kTokenIdentifier); 533 ECHECK(ParseNamespacing(&id, nullptr)); 534 auto enum_def = LookupEnum(id); 535 if (enum_def) { 536 type = enum_def->underlying_type; 537 if (enum_def->is_union) type.base_type = BASE_TYPE_UNION; 538 } else { 539 type.base_type = BASE_TYPE_STRUCT; 540 type.struct_def = LookupCreateStruct(id); 541 } 542 return NoError(); 543 } 544 545 // Parse any IDL type. 546 CheckedError Parser::ParseType(Type &type) { 547 if (token_ == kTokenIdentifier) { 548 if (IsIdent("bool")) { 549 type.base_type = BASE_TYPE_BOOL; 550 NEXT(); 551 } else if (IsIdent("byte") || IsIdent("int8")) { 552 type.base_type = BASE_TYPE_CHAR; 553 NEXT(); 554 } else if (IsIdent("ubyte") || IsIdent("uint8")) { 555 type.base_type = BASE_TYPE_UCHAR; 556 NEXT(); 557 } else if (IsIdent("short") || IsIdent("int16")) { 558 type.base_type = BASE_TYPE_SHORT; 559 NEXT(); 560 } else if (IsIdent("ushort") || IsIdent("uint16")) { 561 type.base_type = BASE_TYPE_USHORT; 562 NEXT(); 563 } else if (IsIdent("int") || IsIdent("int32")) { 564 type.base_type = BASE_TYPE_INT; 565 NEXT(); 566 } else if (IsIdent("uint") || IsIdent("uint32")) { 567 type.base_type = BASE_TYPE_UINT; 568 NEXT(); 569 } else if (IsIdent("long") || IsIdent("int64")) { 570 type.base_type = BASE_TYPE_LONG; 571 NEXT(); 572 } else if (IsIdent("ulong") || IsIdent("uint64")) { 573 type.base_type = BASE_TYPE_ULONG; 574 NEXT(); 575 } else if (IsIdent("float") || IsIdent("float32")) { 576 type.base_type = BASE_TYPE_FLOAT; 577 NEXT(); 578 } else if (IsIdent("double") || IsIdent("float64")) { 579 type.base_type = BASE_TYPE_DOUBLE; 580 NEXT(); 581 } else if (IsIdent("string")) { 582 type.base_type = BASE_TYPE_STRING; 583 NEXT(); 584 } else { 585 ECHECK(ParseTypeIdent(type)); 586 } 587 } else if (token_ == '[') { 588 NEXT(); 589 Type subtype; 590 ECHECK(Recurse([&]() { return ParseType(subtype); })); 591 if (subtype.base_type == BASE_TYPE_VECTOR) { 592 // We could support this, but it will complicate things, and it's 593 // easier to work around with a struct around the inner vector. 594 return Error("nested vector types not supported (wrap in table first)."); 595 } 596 type = Type(BASE_TYPE_VECTOR, subtype.struct_def, subtype.enum_def); 597 type.element = subtype.base_type; 598 EXPECT(']'); 599 } else { 600 return Error("illegal type syntax"); 601 } 602 return NoError(); 603 } 604 605 CheckedError Parser::AddField(StructDef &struct_def, const std::string &name, 606 const Type &type, FieldDef **dest) { 607 auto &field = *new FieldDef(); 608 field.value.offset = 609 FieldIndexToOffset(static_cast<voffset_t>(struct_def.fields.vec.size())); 610 field.name = name; 611 field.file = struct_def.file; 612 field.value.type = type; 613 if (struct_def.fixed) { // statically compute the field offset 614 auto size = InlineSize(type); 615 auto alignment = InlineAlignment(type); 616 // structs_ need to have a predictable format, so we need to align to 617 // the largest scalar 618 struct_def.minalign = std::max(struct_def.minalign, alignment); 619 struct_def.PadLastField(alignment); 620 field.value.offset = static_cast<voffset_t>(struct_def.bytesize); 621 struct_def.bytesize += size; 622 } 623 if (struct_def.fields.Add(name, &field)) 624 return Error("field already exists: " + name); 625 *dest = &field; 626 return NoError(); 627 } 628 629 CheckedError Parser::ParseField(StructDef &struct_def) { 630 std::string name = attribute_; 631 632 if (LookupStruct(name)) 633 return Error("field name can not be the same as table/struct name"); 634 635 std::vector<std::string> dc = doc_comment_; 636 EXPECT(kTokenIdentifier); 637 EXPECT(':'); 638 Type type; 639 ECHECK(ParseType(type)); 640 641 if (struct_def.fixed && !IsScalar(type.base_type) && !IsStruct(type)) 642 return Error("structs_ may contain only scalar or struct fields"); 643 644 FieldDef *typefield = nullptr; 645 if (type.base_type == BASE_TYPE_UNION) { 646 // For union fields, add a second auto-generated field to hold the type, 647 // with a special suffix. 648 ECHECK(AddField(struct_def, name + UnionTypeFieldSuffix(), 649 type.enum_def->underlying_type, &typefield)); 650 } else if (type.base_type == BASE_TYPE_VECTOR && 651 type.element == BASE_TYPE_UNION) { 652 // Only cpp, js and ts supports the union vector feature so far. 653 if (!SupportsVectorOfUnions()) { 654 return Error( 655 "Vectors of unions are not yet supported in all " 656 "the specified programming languages."); 657 } 658 // For vector of union fields, add a second auto-generated vector field to 659 // hold the types, with a special suffix. 660 Type union_vector(BASE_TYPE_VECTOR, nullptr, type.enum_def); 661 union_vector.element = BASE_TYPE_UTYPE; 662 ECHECK(AddField(struct_def, name + UnionTypeFieldSuffix(), union_vector, 663 &typefield)); 664 } 665 666 FieldDef *field; 667 ECHECK(AddField(struct_def, name, type, &field)); 668 669 if (token_ == '=') { 670 NEXT(); 671 if (!IsScalar(type.base_type) || 672 (struct_def.fixed && field->value.constant != "0")) 673 return Error( 674 "default values currently only supported for scalars in tables"); 675 ECHECK(ParseSingleValue(&field->name, field->value, true)); 676 } 677 if (type.enum_def && 678 !type.enum_def->is_union && 679 !type.enum_def->attributes.Lookup("bit_flags") && 680 !type.enum_def->ReverseLookup(StringToInt( 681 field->value.constant.c_str()))) { 682 return Error("default value of " + field->value.constant + " for field " + 683 name + " is not part of enum " + type.enum_def->name); 684 } 685 // Append .0 if the value has not it (skip hex and scientific floats). 686 // This suffix needed for generated C++ code. 687 if (IsFloat(type.base_type)) { 688 auto &text = field->value.constant; 689 FLATBUFFERS_ASSERT(false == text.empty()); 690 auto s = text.c_str(); 691 while(*s == ' ') s++; 692 if (*s == '-' || *s == '+') s++; 693 // 1) A float constants (nan, inf, pi, etc) is a kind of identifier. 694 // 2) A float number needn't ".0" at the end if it has exponent. 695 if ((false == IsIdentifierStart(*s)) && 696 (std::string::npos == field->value.constant.find_first_of(".eEpP"))) { 697 field->value.constant += ".0"; 698 } 699 } 700 701 if (type.enum_def && IsScalar(type.base_type) && !struct_def.fixed && 702 !type.enum_def->attributes.Lookup("bit_flags") && 703 !type.enum_def->ReverseLookup(StringToInt( 704 field->value.constant.c_str()))) 705 Warning("enum " + type.enum_def->name + 706 " does not have a declaration for this field\'s default of " + 707 field->value.constant); 708 709 field->doc_comment = dc; 710 ECHECK(ParseMetaData(&field->attributes)); 711 field->deprecated = field->attributes.Lookup("deprecated") != nullptr; 712 auto hash_name = field->attributes.Lookup("hash"); 713 if (hash_name) { 714 switch ((type.base_type == BASE_TYPE_VECTOR) ? type.element : type.base_type) { 715 case BASE_TYPE_SHORT: 716 case BASE_TYPE_USHORT: { 717 if (FindHashFunction16(hash_name->constant.c_str()) == nullptr) 718 return Error("Unknown hashing algorithm for 16 bit types: " + 719 hash_name->constant); 720 break; 721 } 722 case BASE_TYPE_INT: 723 case BASE_TYPE_UINT: { 724 if (FindHashFunction32(hash_name->constant.c_str()) == nullptr) 725 return Error("Unknown hashing algorithm for 32 bit types: " + 726 hash_name->constant); 727 break; 728 } 729 case BASE_TYPE_LONG: 730 case BASE_TYPE_ULONG: { 731 if (FindHashFunction64(hash_name->constant.c_str()) == nullptr) 732 return Error("Unknown hashing algorithm for 64 bit types: " + 733 hash_name->constant); 734 break; 735 } 736 default: 737 return Error( 738 "only short, ushort, int, uint, long and ulong data types support hashing."); 739 } 740 } 741 auto cpp_type = field->attributes.Lookup("cpp_type"); 742 if (cpp_type) { 743 if (!hash_name) 744 return Error("cpp_type can only be used with a hashed field"); 745 /// forcing cpp_ptr_type to 'naked' if unset 746 auto cpp_ptr_type = field->attributes.Lookup("cpp_ptr_type"); 747 if (!cpp_ptr_type) { 748 auto val = new Value(); 749 val->type = cpp_type->type; 750 val->constant = "naked"; 751 field->attributes.Add("cpp_ptr_type", val); 752 } 753 } 754 if (field->deprecated && struct_def.fixed) 755 return Error("can't deprecate fields in a struct"); 756 field->required = field->attributes.Lookup("required") != nullptr; 757 if (field->required && 758 (struct_def.fixed || IsScalar(type.base_type))) 759 return Error("only non-scalar fields in tables may be 'required'"); 760 field->key = field->attributes.Lookup("key") != nullptr; 761 if (field->key) { 762 if (struct_def.has_key) return Error("only one field may be set as 'key'"); 763 struct_def.has_key = true; 764 if (!IsScalar(type.base_type)) { 765 field->required = true; 766 if (type.base_type != BASE_TYPE_STRING) 767 return Error("'key' field must be string or scalar type"); 768 } 769 } 770 field->shared = field->attributes.Lookup("shared") != nullptr; 771 if (field->shared && field->value.type.base_type != BASE_TYPE_STRING) 772 return Error("shared can only be defined on strings"); 773 774 auto field_native_custom_alloc = 775 field->attributes.Lookup("native_custom_alloc"); 776 if (field_native_custom_alloc) 777 return Error( 778 "native_custom_alloc can only be used with a table or struct " 779 "definition"); 780 781 field->native_inline = field->attributes.Lookup("native_inline") != nullptr; 782 if (field->native_inline && !IsStruct(field->value.type)) 783 return Error("native_inline can only be defined on structs"); 784 785 auto nested = field->attributes.Lookup("nested_flatbuffer"); 786 if (nested) { 787 if (nested->type.base_type != BASE_TYPE_STRING) 788 return Error( 789 "nested_flatbuffer attribute must be a string (the root type)"); 790 if (type.base_type != BASE_TYPE_VECTOR || type.element != BASE_TYPE_UCHAR) 791 return Error( 792 "nested_flatbuffer attribute may only apply to a vector of ubyte"); 793 // This will cause an error if the root type of the nested flatbuffer 794 // wasn't defined elsewhere. 795 LookupCreateStruct(nested->constant); 796 797 // Keep a pointer to StructDef in FieldDef to simplify re-use later 798 auto nested_qualified_name = 799 current_namespace_->GetFullyQualifiedName(nested->constant); 800 field->nested_flatbuffer = LookupStruct(nested_qualified_name); 801 } 802 803 if (field->attributes.Lookup("flexbuffer")) { 804 field->flexbuffer = true; 805 uses_flexbuffers_ = true; 806 if (type.base_type != BASE_TYPE_VECTOR || 807 type.element != BASE_TYPE_UCHAR) 808 return Error("flexbuffer attribute may only apply to a vector of ubyte"); 809 } 810 811 if (typefield) { 812 if (!IsScalar(typefield->value.type.base_type)) { 813 // this is a union vector field 814 typefield->required = field->required; 815 } 816 // If this field is a union, and it has a manually assigned id, 817 // the automatically added type field should have an id as well (of N - 1). 818 auto attr = field->attributes.Lookup("id"); 819 if (attr) { 820 auto id = atoi(attr->constant.c_str()); 821 auto val = new Value(); 822 val->type = attr->type; 823 val->constant = NumToString(id - 1); 824 typefield->attributes.Add("id", val); 825 } 826 } 827 828 EXPECT(';'); 829 return NoError(); 830 } 831 832 CheckedError Parser::ParseString(Value &val) { 833 auto s = attribute_; 834 EXPECT(kTokenStringConstant); 835 val.constant = NumToString(builder_.CreateString(s).o); 836 return NoError(); 837 } 838 839 CheckedError Parser::ParseComma() { 840 if (!opts.protobuf_ascii_alike) EXPECT(','); 841 return NoError(); 842 } 843 844 CheckedError Parser::ParseAnyValue(Value &val, FieldDef *field, 845 size_t parent_fieldn, 846 const StructDef *parent_struct_def) { 847 switch (val.type.base_type) { 848 case BASE_TYPE_UNION: { 849 FLATBUFFERS_ASSERT(field); 850 std::string constant; 851 // Find corresponding type field we may have already parsed. 852 for (auto elem = field_stack_.rbegin(); 853 elem != field_stack_.rbegin() + parent_fieldn; ++elem) { 854 auto &type = elem->second->value.type; 855 if (type.base_type == BASE_TYPE_UTYPE && 856 type.enum_def == val.type.enum_def) { 857 constant = elem->first.constant; 858 break; 859 } 860 } 861 if (constant.empty()) { 862 // We haven't seen the type field yet. Sadly a lot of JSON writers 863 // output these in alphabetical order, meaning it comes after this 864 // value. So we scan past the value to find it, then come back here. 865 auto type_name = field->name + UnionTypeFieldSuffix(); 866 FLATBUFFERS_ASSERT(parent_struct_def); 867 auto type_field = parent_struct_def->fields.Lookup(type_name); 868 FLATBUFFERS_ASSERT(type_field); // Guaranteed by ParseField(). 869 // Remember where we are in the source file, so we can come back here. 870 auto backup = *static_cast<ParserState *>(this); 871 ECHECK(SkipAnyJsonValue()); // The table. 872 ECHECK(ParseComma()); 873 auto next_name = attribute_; 874 if (Is(kTokenStringConstant)) { 875 NEXT(); 876 } else { 877 EXPECT(kTokenIdentifier); 878 } 879 if (next_name != type_name) 880 return Error("missing type field after this union value: " + 881 type_name); 882 EXPECT(':'); 883 Value type_val = type_field->value; 884 ECHECK(ParseAnyValue(type_val, type_field, 0, nullptr)); 885 constant = type_val.constant; 886 // Got the information we needed, now rewind: 887 *static_cast<ParserState *>(this) = backup; 888 } 889 uint8_t enum_idx; 890 ECHECK(atot(constant.c_str(), *this, &enum_idx)); 891 auto enum_val = val.type.enum_def->ReverseLookup(enum_idx); 892 if (!enum_val) return Error("illegal type id for: " + field->name); 893 if (enum_val->union_type.base_type == BASE_TYPE_STRUCT) { 894 ECHECK(ParseTable(*enum_val->union_type.struct_def, &val.constant, 895 nullptr)); 896 if (enum_val->union_type.struct_def->fixed) { 897 // All BASE_TYPE_UNION values are offsets, so turn this into one. 898 SerializeStruct(*enum_val->union_type.struct_def, val); 899 builder_.ClearOffsets(); 900 val.constant = NumToString(builder_.GetSize()); 901 } 902 } else if (enum_val->union_type.base_type == BASE_TYPE_STRING) { 903 ECHECK(ParseString(val)); 904 } else { 905 FLATBUFFERS_ASSERT(false); 906 } 907 break; 908 } 909 case BASE_TYPE_STRUCT: 910 ECHECK(ParseTable(*val.type.struct_def, &val.constant, nullptr)); 911 break; 912 case BASE_TYPE_STRING: { 913 ECHECK(ParseString(val)); 914 break; 915 } 916 case BASE_TYPE_VECTOR: { 917 uoffset_t off; 918 ECHECK(ParseVector(val.type.VectorType(), &off)); 919 val.constant = NumToString(off); 920 break; 921 } 922 case BASE_TYPE_INT: 923 case BASE_TYPE_UINT: 924 case BASE_TYPE_LONG: 925 case BASE_TYPE_ULONG: { 926 if (field && field->attributes.Lookup("hash") && 927 (token_ == kTokenIdentifier || token_ == kTokenStringConstant)) { 928 ECHECK(ParseHash(val, field)); 929 } else { 930 ECHECK(ParseSingleValue(field ? &field->name : nullptr, val, false)); 931 } 932 break; 933 } 934 default: 935 ECHECK(ParseSingleValue(field ? &field->name : nullptr, val, false)); 936 break; 937 } 938 return NoError(); 939 } 940 941 void Parser::SerializeStruct(const StructDef &struct_def, const Value &val) { 942 FLATBUFFERS_ASSERT(val.constant.length() == struct_def.bytesize); 943 builder_.Align(struct_def.minalign); 944 builder_.PushBytes(reinterpret_cast<const uint8_t *>(val.constant.c_str()), 945 struct_def.bytesize); 946 builder_.AddStructOffset(val.offset, builder_.GetSize()); 947 } 948 949 template <typename F> 950 CheckedError Parser::ParseTableDelimiters(size_t &fieldn, 951 const StructDef *struct_def, 952 F body) { 953 // We allow tables both as JSON object{ .. } with field names 954 // or vector[..] with all fields in order 955 char terminator = '}'; 956 bool is_nested_vector = struct_def && Is('['); 957 if (is_nested_vector) { 958 NEXT(); 959 terminator = ']'; 960 } else { 961 EXPECT('{'); 962 } 963 for (;;) { 964 if ((!opts.strict_json || !fieldn) && Is(terminator)) break; 965 std::string name; 966 if (is_nested_vector) { 967 if (fieldn >= struct_def->fields.vec.size()) { 968 return Error("too many unnamed fields in nested array"); 969 } 970 name = struct_def->fields.vec[fieldn]->name; 971 } else { 972 name = attribute_; 973 if (Is(kTokenStringConstant)) { 974 NEXT(); 975 } else { 976 EXPECT(opts.strict_json ? kTokenStringConstant : kTokenIdentifier); 977 } 978 if (!opts.protobuf_ascii_alike || !(Is('{') || Is('['))) EXPECT(':'); 979 } 980 ECHECK(body(name, fieldn, struct_def)); 981 if (Is(terminator)) break; 982 ECHECK(ParseComma()); 983 } 984 NEXT(); 985 if (is_nested_vector && fieldn != struct_def->fields.vec.size()) { 986 return Error("wrong number of unnamed fields in table vector"); 987 } 988 return NoError(); 989 } 990 991 CheckedError Parser::ParseTable(const StructDef &struct_def, std::string *value, 992 uoffset_t *ovalue) { 993 size_t fieldn_outer = 0; 994 auto err = ParseTableDelimiters( 995 fieldn_outer, &struct_def, 996 [&](const std::string &name, size_t &fieldn, 997 const StructDef *struct_def_inner) -> CheckedError { 998 if (name == "$schema") { 999 ECHECK(Expect(kTokenStringConstant)); 1000 return NoError(); 1001 } 1002 auto field = struct_def_inner->fields.Lookup(name); 1003 if (!field) { 1004 if (!opts.skip_unexpected_fields_in_json) { 1005 return Error("unknown field: " + name); 1006 } else { 1007 ECHECK(SkipAnyJsonValue()); 1008 } 1009 } else { 1010 if (IsIdent("null") && !IsScalar(field->value.type.base_type)) { 1011 ECHECK(Next()); // Ignore this field. 1012 } else { 1013 Value val = field->value; 1014 if (field->flexbuffer) { 1015 flexbuffers::Builder builder(1024, 1016 flexbuffers::BUILDER_FLAG_SHARE_ALL); 1017 ECHECK(ParseFlexBufferValue(&builder)); 1018 builder.Finish(); 1019 // Force alignment for nested flexbuffer 1020 builder_.ForceVectorAlignment(builder.GetSize(), sizeof(uint8_t), 1021 sizeof(largest_scalar_t)); 1022 auto off = builder_.CreateVector(builder.GetBuffer()); 1023 val.constant = NumToString(off.o); 1024 } else if (field->nested_flatbuffer) { 1025 ECHECK( 1026 ParseNestedFlatbuffer(val, field, fieldn, struct_def_inner)); 1027 } else { 1028 ECHECK(Recurse([&]() { 1029 return ParseAnyValue(val, field, fieldn, struct_def_inner); 1030 })); 1031 } 1032 // Hardcoded insertion-sort with error-check. 1033 // If fields are specified in order, then this loop exits 1034 // immediately. 1035 auto elem = field_stack_.rbegin(); 1036 for (; elem != field_stack_.rbegin() + fieldn; ++elem) { 1037 auto existing_field = elem->second; 1038 if (existing_field == field) 1039 return Error("field set more than once: " + field->name); 1040 if (existing_field->value.offset < field->value.offset) break; 1041 } 1042 // Note: elem points to before the insertion point, thus .base() 1043 // points to the correct spot. 1044 field_stack_.insert(elem.base(), std::make_pair(val, field)); 1045 fieldn++; 1046 } 1047 } 1048 return NoError(); 1049 }); 1050 ECHECK(err); 1051 1052 // Check if all required fields are parsed. 1053 for (auto field_it = struct_def.fields.vec.begin(); 1054 field_it != struct_def.fields.vec.end(); ++field_it) { 1055 auto required_field = *field_it; 1056 if (!required_field->required) { continue; } 1057 bool found = false; 1058 for (auto pf_it = field_stack_.end() - fieldn_outer; 1059 pf_it != field_stack_.end(); ++pf_it) { 1060 auto parsed_field = pf_it->second; 1061 if (parsed_field == required_field) { 1062 found = true; 1063 break; 1064 } 1065 } 1066 if (!found) { 1067 return Error("required field is missing: " + required_field->name + 1068 " in " + struct_def.name); 1069 } 1070 } 1071 1072 if (struct_def.fixed && fieldn_outer != struct_def.fields.vec.size()) 1073 return Error("struct: wrong number of initializers: " + struct_def.name); 1074 1075 auto start = struct_def.fixed ? builder_.StartStruct(struct_def.minalign) 1076 : builder_.StartTable(); 1077 1078 for (size_t size = struct_def.sortbysize ? sizeof(largest_scalar_t) : 1; size; 1079 size /= 2) { 1080 // Go through elements in reverse, since we're building the data backwards. 1081 for (auto it = field_stack_.rbegin(); 1082 it != field_stack_.rbegin() + fieldn_outer; ++it) { 1083 auto &field_value = it->first; 1084 auto field = it->second; 1085 if (!struct_def.sortbysize || 1086 size == SizeOf(field_value.type.base_type)) { 1087 switch (field_value.type.base_type) { 1088 // clang-format off 1089 #define FLATBUFFERS_TD(ENUM, IDLTYPE, \ 1090 CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE) \ 1091 case BASE_TYPE_ ## ENUM: \ 1092 builder_.Pad(field->padding); \ 1093 if (struct_def.fixed) { \ 1094 CTYPE val; \ 1095 ECHECK(atot(field_value.constant.c_str(), *this, &val)); \ 1096 builder_.PushElement(val); \ 1097 } else { \ 1098 CTYPE val, valdef; \ 1099 ECHECK(atot(field_value.constant.c_str(), *this, &val)); \ 1100 ECHECK(atot(field->value.constant.c_str(), *this, &valdef)); \ 1101 builder_.AddElement(field_value.offset, val, valdef); \ 1102 } \ 1103 break; 1104 FLATBUFFERS_GEN_TYPES_SCALAR(FLATBUFFERS_TD); 1105 #undef FLATBUFFERS_TD 1106 #define FLATBUFFERS_TD(ENUM, IDLTYPE, \ 1107 CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE) \ 1108 case BASE_TYPE_ ## ENUM: \ 1109 builder_.Pad(field->padding); \ 1110 if (IsStruct(field->value.type)) { \ 1111 SerializeStruct(*field->value.type.struct_def, field_value); \ 1112 } else { \ 1113 CTYPE val; \ 1114 ECHECK(atot(field_value.constant.c_str(), *this, &val)); \ 1115 builder_.AddOffset(field_value.offset, val); \ 1116 } \ 1117 break; 1118 FLATBUFFERS_GEN_TYPES_POINTER(FLATBUFFERS_TD); 1119 #undef FLATBUFFERS_TD 1120 // clang-format on 1121 } 1122 } 1123 } 1124 } 1125 for (size_t i = 0; i < fieldn_outer; i++) field_stack_.pop_back(); 1126 1127 if (struct_def.fixed) { 1128 builder_.ClearOffsets(); 1129 builder_.EndStruct(); 1130 FLATBUFFERS_ASSERT(value); 1131 // Temporarily store this struct in the value string, since it is to 1132 // be serialized in-place elsewhere. 1133 value->assign( 1134 reinterpret_cast<const char *>(builder_.GetCurrentBufferPointer()), 1135 struct_def.bytesize); 1136 builder_.PopBytes(struct_def.bytesize); 1137 FLATBUFFERS_ASSERT(!ovalue); 1138 } else { 1139 auto val = builder_.EndTable(start); 1140 if (ovalue) *ovalue = val; 1141 if (value) *value = NumToString(val); 1142 } 1143 return NoError(); 1144 } 1145 1146 template <typename F> 1147 CheckedError Parser::ParseVectorDelimiters(size_t &count, F body) { 1148 EXPECT('['); 1149 for (;;) { 1150 if ((!opts.strict_json || !count) && Is(']')) break; 1151 ECHECK(body(count)); 1152 count++; 1153 if (Is(']')) break; 1154 ECHECK(ParseComma()); 1155 } 1156 NEXT(); 1157 return NoError(); 1158 } 1159 1160 CheckedError Parser::ParseVector(const Type &type, uoffset_t *ovalue) { 1161 size_t count = 0; 1162 auto err = ParseVectorDelimiters(count, [&](size_t &) -> CheckedError { 1163 Value val; 1164 val.type = type; 1165 ECHECK(Recurse([&]() { return ParseAnyValue(val, nullptr, 0, nullptr); })); 1166 field_stack_.push_back(std::make_pair(val, nullptr)); 1167 return NoError(); 1168 }); 1169 ECHECK(err); 1170 1171 builder_.StartVector(count * InlineSize(type) / InlineAlignment(type), 1172 InlineAlignment(type)); 1173 for (size_t i = 0; i < count; i++) { 1174 // start at the back, since we're building the data backwards. 1175 auto &val = field_stack_.back().first; 1176 switch (val.type.base_type) { 1177 // clang-format off 1178 #define FLATBUFFERS_TD(ENUM, IDLTYPE, \ 1179 CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE) \ 1180 case BASE_TYPE_ ## ENUM: \ 1181 if (IsStruct(val.type)) SerializeStruct(*val.type.struct_def, val); \ 1182 else { \ 1183 CTYPE elem; \ 1184 ECHECK(atot(val.constant.c_str(), *this, &elem)); \ 1185 builder_.PushElement(elem); \ 1186 } \ 1187 break; 1188 FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) 1189 #undef FLATBUFFERS_TD 1190 // clang-format on 1191 } 1192 field_stack_.pop_back(); 1193 } 1194 1195 builder_.ClearOffsets(); 1196 *ovalue = builder_.EndVector(count); 1197 return NoError(); 1198 } 1199 1200 CheckedError Parser::ParseNestedFlatbuffer(Value &val, FieldDef *field, 1201 size_t fieldn, 1202 const StructDef *parent_struct_def) { 1203 if (token_ == '[') { // backwards compat for 'legacy' ubyte buffers 1204 ECHECK(ParseAnyValue(val, field, fieldn, parent_struct_def)); 1205 } else { 1206 auto cursor_at_value_begin = cursor_; 1207 ECHECK(SkipAnyJsonValue()); 1208 std::string substring(cursor_at_value_begin - 1, cursor_ - 1); 1209 1210 // Create and initialize new parser 1211 Parser nested_parser; 1212 FLATBUFFERS_ASSERT(field->nested_flatbuffer); 1213 nested_parser.root_struct_def_ = field->nested_flatbuffer; 1214 nested_parser.enums_ = enums_; 1215 nested_parser.opts = opts; 1216 nested_parser.uses_flexbuffers_ = uses_flexbuffers_; 1217 1218 // Parse JSON substring into new flatbuffer builder using nested_parser 1219 bool ok = nested_parser.Parse(substring.c_str(), nullptr, nullptr); 1220 1221 // Clean nested_parser to avoid deleting the elements in 1222 // the SymbolTables on destruction 1223 nested_parser.enums_.dict.clear(); 1224 nested_parser.enums_.vec.clear(); 1225 1226 if (!ok) { 1227 ECHECK(Error(nested_parser.error_)); 1228 } 1229 // Force alignment for nested flatbuffer 1230 builder_.ForceVectorAlignment(nested_parser.builder_.GetSize(), sizeof(uint8_t), 1231 nested_parser.builder_.GetBufferMinAlignment()); 1232 1233 auto off = builder_.CreateVector(nested_parser.builder_.GetBufferPointer(), 1234 nested_parser.builder_.GetSize()); 1235 val.constant = NumToString(off.o); 1236 } 1237 return NoError(); 1238 } 1239 1240 CheckedError Parser::ParseMetaData(SymbolTable<Value> *attributes) { 1241 if (Is('(')) { 1242 NEXT(); 1243 for (;;) { 1244 auto name = attribute_; 1245 if (false == (Is(kTokenIdentifier) || Is(kTokenStringConstant))) 1246 return Error("attribute name must be either identifier or string: " + 1247 name); 1248 if (known_attributes_.find(name) == known_attributes_.end()) 1249 return Error("user define attributes must be declared before use: " + 1250 name); 1251 NEXT(); 1252 auto e = new Value(); 1253 attributes->Add(name, e); 1254 if (Is(':')) { 1255 NEXT(); 1256 ECHECK(ParseSingleValue(&name, *e, true)); 1257 } 1258 if (Is(')')) { 1259 NEXT(); 1260 break; 1261 } 1262 EXPECT(','); 1263 } 1264 } 1265 return NoError(); 1266 } 1267 1268 CheckedError Parser::TryTypedValue(const std::string *name, int dtoken, 1269 bool check, Value &e, BaseType req, 1270 bool *destmatch) { 1271 bool match = dtoken == token_; 1272 if (match) { 1273 FLATBUFFERS_ASSERT(*destmatch == false); 1274 *destmatch = true; 1275 e.constant = attribute_; 1276 // Check token match 1277 if (!check) { 1278 if (e.type.base_type == BASE_TYPE_NONE) { 1279 e.type.base_type = req; 1280 } else { 1281 return Error( 1282 std::string("type mismatch: expecting: ") + 1283 kTypeNames[e.type.base_type] + ", found: " + kTypeNames[req] + 1284 ", name: " + (name ? *name : "") + ", value: " + e.constant); 1285 } 1286 } 1287 // The exponent suffix of hexadecimal float-point number is mandatory. 1288 // A hex-integer constant is forbidden as an initializer of float number. 1289 if ((kTokenFloatConstant != dtoken) && IsFloat(e.type.base_type)) { 1290 const auto &s = e.constant; 1291 const auto k = s.find_first_of("0123456789."); 1292 if ((std::string::npos != k) && (s.length() > (k + 1)) && 1293 (s.at(k) == '0' && is_alpha_char(s.at(k + 1), 'X')) && 1294 (std::string::npos == s.find_first_of("pP", k + 2))) { 1295 return Error( 1296 "invalid number, the exponent suffix of hexadecimal " 1297 "floating-point literals is mandatory: \"" + 1298 s + "\""); 1299 } 1300 } 1301 1302 NEXT(); 1303 } 1304 return NoError(); 1305 } 1306 1307 CheckedError Parser::ParseEnumFromString(Type &type, int64_t *result) { 1308 *result = 0; 1309 // Parse one or more enum identifiers, separated by spaces. 1310 const char *next = attribute_.c_str(); 1311 do { 1312 const char *divider = strchr(next, ' '); 1313 std::string word; 1314 if (divider) { 1315 word = std::string(next, divider); 1316 next = divider + strspn(divider, " "); 1317 } else { 1318 word = next; 1319 next += word.length(); 1320 } 1321 if (type.enum_def) { // The field has an enum type 1322 auto enum_val = type.enum_def->vals.Lookup(word); 1323 if (!enum_val) 1324 return Error("unknown enum value: " + word + 1325 ", for enum: " + type.enum_def->name); 1326 *result |= enum_val->value; 1327 } else { // No enum type, probably integral field. 1328 if (!IsInteger(type.base_type)) 1329 return Error("not a valid value for this field: " + word); 1330 // TODO: could check if its a valid number constant here. 1331 const char *dot = strrchr(word.c_str(), '.'); 1332 if (!dot) 1333 return Error("enum values need to be qualified by an enum type"); 1334 std::string enum_def_str(word.c_str(), dot); 1335 std::string enum_val_str(dot + 1, word.c_str() + word.length()); 1336 auto enum_def = LookupEnum(enum_def_str); 1337 if (!enum_def) return Error("unknown enum: " + enum_def_str); 1338 auto enum_val = enum_def->vals.Lookup(enum_val_str); 1339 if (!enum_val) return Error("unknown enum value: " + enum_val_str); 1340 *result |= enum_val->value; 1341 } 1342 } while (*next); 1343 return NoError(); 1344 } 1345 1346 CheckedError Parser::ParseHash(Value &e, FieldDef *field) { 1347 FLATBUFFERS_ASSERT(field); 1348 Value *hash_name = field->attributes.Lookup("hash"); 1349 switch (e.type.base_type) { 1350 case BASE_TYPE_SHORT: { 1351 auto hash = FindHashFunction16(hash_name->constant.c_str()); 1352 int16_t hashed_value = static_cast<int16_t>(hash(attribute_.c_str())); 1353 e.constant = NumToString(hashed_value); 1354 break; 1355 } 1356 case BASE_TYPE_USHORT: { 1357 auto hash = FindHashFunction16(hash_name->constant.c_str()); 1358 uint16_t hashed_value = hash(attribute_.c_str()); 1359 e.constant = NumToString(hashed_value); 1360 break; 1361 } 1362 case BASE_TYPE_INT: { 1363 auto hash = FindHashFunction32(hash_name->constant.c_str()); 1364 int32_t hashed_value = static_cast<int32_t>(hash(attribute_.c_str())); 1365 e.constant = NumToString(hashed_value); 1366 break; 1367 } 1368 case BASE_TYPE_UINT: { 1369 auto hash = FindHashFunction32(hash_name->constant.c_str()); 1370 uint32_t hashed_value = hash(attribute_.c_str()); 1371 e.constant = NumToString(hashed_value); 1372 break; 1373 } 1374 case BASE_TYPE_LONG: { 1375 auto hash = FindHashFunction64(hash_name->constant.c_str()); 1376 int64_t hashed_value = static_cast<int64_t>(hash(attribute_.c_str())); 1377 e.constant = NumToString(hashed_value); 1378 break; 1379 } 1380 case BASE_TYPE_ULONG: { 1381 auto hash = FindHashFunction64(hash_name->constant.c_str()); 1382 uint64_t hashed_value = hash(attribute_.c_str()); 1383 e.constant = NumToString(hashed_value); 1384 break; 1385 } 1386 default: FLATBUFFERS_ASSERT(0); 1387 } 1388 NEXT(); 1389 return NoError(); 1390 } 1391 1392 CheckedError Parser::TokenError() { 1393 return Error("cannot parse value starting with: " + TokenToStringId(token_)); 1394 } 1395 1396 CheckedError Parser::ParseSingleValue(const std::string *name, Value &e, 1397 bool check_now) { 1398 // First see if this could be a conversion function: 1399 if (token_ == kTokenIdentifier && *cursor_ == '(') { 1400 // todo: Extract processing of conversion functions to ParseFunction. 1401 const auto functionname = attribute_; 1402 if (!IsFloat(e.type.base_type)) { 1403 return Error(functionname + ": type of argument mismatch, expecting: " + 1404 kTypeNames[BASE_TYPE_DOUBLE] + 1405 ", found: " + kTypeNames[e.type.base_type] + 1406 ", name: " + (name ? *name : "") + ", value: " + e.constant); 1407 } 1408 NEXT(); 1409 EXPECT('('); 1410 ECHECK(Recurse([&]() { return ParseSingleValue(name, e, false); })); 1411 EXPECT(')'); 1412 // calculate with double precision 1413 double x, y = 0.0; 1414 ECHECK(atot(e.constant.c_str(), *this, &x)); 1415 auto func_match = false; 1416 // clang-format off 1417 #define FLATBUFFERS_FN_DOUBLE(name, op) \ 1418 if (!func_match && functionname == name) { y = op; func_match = true; } 1419 FLATBUFFERS_FN_DOUBLE("deg", x / kPi * 180); 1420 FLATBUFFERS_FN_DOUBLE("rad", x * kPi / 180); 1421 FLATBUFFERS_FN_DOUBLE("sin", sin(x)); 1422 FLATBUFFERS_FN_DOUBLE("cos", cos(x)); 1423 FLATBUFFERS_FN_DOUBLE("tan", tan(x)); 1424 FLATBUFFERS_FN_DOUBLE("asin", asin(x)); 1425 FLATBUFFERS_FN_DOUBLE("acos", acos(x)); 1426 FLATBUFFERS_FN_DOUBLE("atan", atan(x)); 1427 // TODO(wvo): add more useful conversion functions here. 1428 #undef FLATBUFFERS_FN_DOUBLE 1429 // clang-format on 1430 if (true != func_match) { 1431 return Error(std::string("Unknown conversion function: ") + functionname + 1432 ", field name: " + (name ? *name : "") + 1433 ", value: " + e.constant); 1434 } 1435 e.constant = NumToString(y); 1436 return NoError(); 1437 } 1438 1439 auto match = false; 1440 // clang-format off 1441 #define TRY_ECHECK(force, dtoken, check, req) \ 1442 if (!match && ((check) || IsConstTrue(force))) \ 1443 ECHECK(TryTypedValue(name, dtoken, check, e, req, &match)) 1444 // clang-format on 1445 1446 if (token_ == kTokenStringConstant || token_ == kTokenIdentifier) { 1447 const auto kTokenStringOrIdent = token_; 1448 // The string type is a most probable type, check it first. 1449 TRY_ECHECK(false, kTokenStringConstant, 1450 e.type.base_type == BASE_TYPE_STRING, BASE_TYPE_STRING); 1451 1452 // avoid escaped and non-ascii in the string 1453 if ((token_ == kTokenStringConstant) && IsScalar(e.type.base_type) && 1454 !attr_is_trivial_ascii_string_) { 1455 return Error( 1456 std::string("type mismatch or invalid value, an initializer of " 1457 "non-string field must be trivial ASCII string: type: ") + 1458 kTypeNames[e.type.base_type] + ", name: " + (name ? *name : "") + 1459 ", value: " + attribute_); 1460 } 1461 1462 // A boolean as true/false. Boolean as Integer check below. 1463 if (!match && IsBool(e.type.base_type)) { 1464 auto is_true = attribute_ == "true"; 1465 if (is_true || attribute_ == "false") { 1466 attribute_ = is_true ? "1" : "0"; 1467 // accepts both kTokenStringConstant and kTokenIdentifier 1468 TRY_ECHECK(false, kTokenStringOrIdent, IsBool(e.type.base_type), 1469 BASE_TYPE_BOOL); 1470 } 1471 } 1472 // Check if this could be a string/identifier enum value. 1473 // Enum can have only true integer base type. 1474 if (!match && IsInteger(e.type.base_type) && !IsBool(e.type.base_type) && 1475 IsIdentifierStart(*attribute_.c_str())) { 1476 int64_t val; 1477 ECHECK(ParseEnumFromString(e.type, &val)); 1478 e.constant = NumToString(val); 1479 NEXT(); 1480 match = true; 1481 } 1482 // float/integer number in string 1483 if ((token_ == kTokenStringConstant) && IsScalar(e.type.base_type)) { 1484 // remove trailing whitespaces from attribute_ 1485 auto last = attribute_.find_last_not_of(' '); 1486 if (std::string::npos != last) // has non-whitespace 1487 attribute_.resize(last + 1); 1488 } 1489 // Float numbers or nan, inf, pi, etc. 1490 TRY_ECHECK(false, kTokenStringOrIdent, IsFloat(e.type.base_type), 1491 BASE_TYPE_FLOAT); 1492 // An integer constant in string. 1493 TRY_ECHECK(false, kTokenStringOrIdent, IsInteger(e.type.base_type), 1494 BASE_TYPE_INT); 1495 // Unknown tokens will be interpreted as string type. 1496 TRY_ECHECK(true, kTokenStringConstant, e.type.base_type == BASE_TYPE_STRING, 1497 BASE_TYPE_STRING); 1498 } else { 1499 // Try a float number. 1500 TRY_ECHECK(false, kTokenFloatConstant, IsFloat(e.type.base_type), 1501 BASE_TYPE_FLOAT); 1502 // Integer token can init any scalar (integer of float). 1503 TRY_ECHECK(true, kTokenIntegerConstant, IsScalar(e.type.base_type), 1504 BASE_TYPE_INT); 1505 } 1506 #undef TRY_ECHECK 1507 1508 if (!match) return TokenError(); 1509 1510 // The check_now flag must be true when parse a fbs-schema. 1511 // This flag forces to check default scalar values or metadata of field. 1512 // For JSON parser the flag should be false. 1513 // If it is set for JSON each value will be checked twice (see ParseTable). 1514 if (check_now && IsScalar(e.type.base_type)) { 1515 // "re-pack" an integer scalar to remove any ambiguities like leading zeros 1516 // which can be treated as octal-literal (idl_gen_cpp/GenDefaultConstant). 1517 const auto repack = IsInteger(e.type.base_type); 1518 switch (e.type.base_type) { 1519 // clang-format off 1520 #define FLATBUFFERS_TD(ENUM, IDLTYPE, \ 1521 CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE) \ 1522 case BASE_TYPE_ ## ENUM: {\ 1523 CTYPE val; \ 1524 ECHECK(atot(e.constant.c_str(), *this, &val)); \ 1525 if(repack) e.constant = NumToString(val); \ 1526 break; } 1527 FLATBUFFERS_GEN_TYPES_SCALAR(FLATBUFFERS_TD); 1528 #undef FLATBUFFERS_TD 1529 default: break; 1530 // clang-format on 1531 } 1532 } 1533 return NoError(); 1534 } 1535 1536 StructDef *Parser::LookupCreateStruct(const std::string &name, 1537 bool create_if_new, bool definition) { 1538 std::string qualified_name = current_namespace_->GetFullyQualifiedName(name); 1539 // See if it exists pre-declared by an unqualified use. 1540 auto struct_def = LookupStruct(name); 1541 if (struct_def && struct_def->predecl) { 1542 if (definition) { 1543 // Make sure it has the current namespace, and is registered under its 1544 // qualified name. 1545 struct_def->defined_namespace = current_namespace_; 1546 structs_.Move(name, qualified_name); 1547 } 1548 return struct_def; 1549 } 1550 // See if it exists pre-declared by an qualified use. 1551 struct_def = LookupStruct(qualified_name); 1552 if (struct_def && struct_def->predecl) { 1553 if (definition) { 1554 // Make sure it has the current namespace. 1555 struct_def->defined_namespace = current_namespace_; 1556 } 1557 return struct_def; 1558 } 1559 if (!definition) { 1560 // Search thru parent namespaces. 1561 for (size_t components = current_namespace_->components.size(); 1562 components && !struct_def; components--) { 1563 struct_def = LookupStruct( 1564 current_namespace_->GetFullyQualifiedName(name, components - 1)); 1565 } 1566 } 1567 if (!struct_def && create_if_new) { 1568 struct_def = new StructDef(); 1569 if (definition) { 1570 structs_.Add(qualified_name, struct_def); 1571 struct_def->name = name; 1572 struct_def->defined_namespace = current_namespace_; 1573 } else { 1574 // Not a definition. 1575 // Rather than failing, we create a "pre declared" StructDef, due to 1576 // circular references, and check for errors at the end of parsing. 1577 // It is defined in the current namespace, as the best guess what the 1578 // final namespace will be. 1579 structs_.Add(name, struct_def); 1580 struct_def->name = name; 1581 struct_def->defined_namespace = current_namespace_; 1582 struct_def->original_location.reset( 1583 new std::string(file_being_parsed_ + ":" + NumToString(line_))); 1584 } 1585 } 1586 return struct_def; 1587 } 1588 1589 CheckedError Parser::ParseEnum(bool is_union, EnumDef **dest) { 1590 std::vector<std::string> enum_comment = doc_comment_; 1591 NEXT(); 1592 std::string enum_name = attribute_; 1593 EXPECT(kTokenIdentifier); 1594 EnumDef *enum_def; 1595 ECHECK(StartEnum(enum_name, is_union, &enum_def)); 1596 enum_def->doc_comment = enum_comment; 1597 if (!is_union && !opts.proto_mode) { 1598 // Give specialized error message, since this type spec used to 1599 // be optional in the first FlatBuffers release. 1600 if (!Is(':')) { 1601 return Error( 1602 "must specify the underlying integer type for this" 1603 " enum (e.g. \': short\', which was the default)."); 1604 } else { 1605 NEXT(); 1606 } 1607 // Specify the integer type underlying this enum. 1608 ECHECK(ParseType(enum_def->underlying_type)); 1609 if (!IsInteger(enum_def->underlying_type.base_type) || 1610 IsBool(enum_def->underlying_type.base_type)) 1611 return Error("underlying enum type must be integral"); 1612 // Make this type refer back to the enum it was derived from. 1613 enum_def->underlying_type.enum_def = enum_def; 1614 } 1615 ECHECK(ParseMetaData(&enum_def->attributes)); 1616 EXPECT('{'); 1617 if (is_union) enum_def->vals.Add("NONE", new EnumVal("NONE", 0)); 1618 std::set<std::pair<BaseType, StructDef*>> union_types; 1619 for (;;) { 1620 if (opts.proto_mode && attribute_ == "option") { 1621 ECHECK(ParseProtoOption()); 1622 } else { 1623 auto value_name = attribute_; 1624 auto full_name = value_name; 1625 std::vector<std::string> value_comment = doc_comment_; 1626 EXPECT(kTokenIdentifier); 1627 if (is_union) { 1628 ECHECK(ParseNamespacing(&full_name, &value_name)); 1629 if (opts.union_value_namespacing) { 1630 // Since we can't namespace the actual enum identifiers, turn 1631 // namespace parts into part of the identifier. 1632 value_name = full_name; 1633 std::replace(value_name.begin(), value_name.end(), '.', '_'); 1634 } 1635 } 1636 auto prevsize = enum_def->vals.vec.size(); 1637 auto prevvalue = prevsize > 0 ? enum_def->vals.vec.back()->value : 0; 1638 auto &ev = *new EnumVal(value_name, 0); 1639 if (enum_def->vals.Add(value_name, &ev)) 1640 return Error("enum value already exists: " + value_name); 1641 ev.doc_comment = value_comment; 1642 if (is_union) { 1643 if (Is(':')) { 1644 NEXT(); 1645 ECHECK(ParseType(ev.union_type)); 1646 if (ev.union_type.base_type != BASE_TYPE_STRUCT && 1647 ev.union_type.base_type != BASE_TYPE_STRING) 1648 return Error("union value type may only be table/struct/string"); 1649 } else { 1650 ev.union_type = Type(BASE_TYPE_STRUCT, LookupCreateStruct(full_name)); 1651 } 1652 if (!enum_def->uses_multiple_type_instances) { 1653 auto union_type_key = std::make_pair(ev.union_type.base_type, ev.union_type.struct_def); 1654 if (union_types.count(union_type_key) > 0) { 1655 enum_def->uses_multiple_type_instances = true; 1656 } else { 1657 union_types.insert(union_type_key); 1658 } 1659 } 1660 } 1661 if (Is('=')) { 1662 NEXT(); 1663 ECHECK(atot(attribute_.c_str(), *this, &ev.value)); 1664 EXPECT(kTokenIntegerConstant); 1665 if (!opts.proto_mode && prevsize && 1666 enum_def->vals.vec[prevsize - 1]->value >= ev.value) 1667 return Error("enum values must be specified in ascending order"); 1668 } else if (prevsize == 0) { 1669 // already set to zero 1670 } else if (prevvalue != flatbuffers::numeric_limits<int64_t>::max()) { 1671 ev.value = prevvalue + 1; 1672 } else { 1673 return Error("enum value overflows"); 1674 } 1675 1676 // Check that value fits into the underlying type. 1677 switch (enum_def->underlying_type.base_type) { 1678 // clang-format off 1679 #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, \ 1680 PTYPE, RTYPE) \ 1681 case BASE_TYPE_##ENUM: { \ 1682 int64_t min_value = static_cast<int64_t>( \ 1683 flatbuffers::numeric_limits<CTYPE>::lowest()); \ 1684 int64_t max_value = static_cast<int64_t>( \ 1685 flatbuffers::numeric_limits<CTYPE>::max()); \ 1686 if (ev.value < min_value || ev.value > max_value) { \ 1687 return Error( \ 1688 "enum value does not fit [" + NumToString(min_value) + \ 1689 "; " + NumToString(max_value) + "]"); \ 1690 } \ 1691 break; \ 1692 } 1693 FLATBUFFERS_GEN_TYPES_SCALAR(FLATBUFFERS_TD); 1694 #undef FLATBUFFERS_TD 1695 default: break; 1696 // clang-format on 1697 } 1698 1699 if (opts.proto_mode && Is('[')) { 1700 NEXT(); 1701 // ignore attributes on enums. 1702 while (token_ != ']') NEXT(); 1703 NEXT(); 1704 } 1705 } 1706 if (!Is(opts.proto_mode ? ';' : ',')) break; 1707 NEXT(); 1708 if (Is('}')) break; 1709 } 1710 EXPECT('}'); 1711 if (enum_def->attributes.Lookup("bit_flags")) { 1712 for (auto it = enum_def->vals.vec.begin(); it != enum_def->vals.vec.end(); 1713 ++it) { 1714 if (static_cast<size_t>((*it)->value) >= 1715 SizeOf(enum_def->underlying_type.base_type) * 8) 1716 return Error("bit flag out of range of underlying integral type"); 1717 (*it)->value = 1LL << (*it)->value; 1718 } 1719 } 1720 if (dest) *dest = enum_def; 1721 types_.Add(current_namespace_->GetFullyQualifiedName(enum_def->name), 1722 new Type(BASE_TYPE_UNION, nullptr, enum_def)); 1723 return NoError(); 1724 } 1725 1726 CheckedError Parser::StartStruct(const std::string &name, StructDef **dest) { 1727 auto &struct_def = *LookupCreateStruct(name, true, true); 1728 if (!struct_def.predecl) return Error("datatype already exists: " + name); 1729 struct_def.predecl = false; 1730 struct_def.name = name; 1731 struct_def.file = file_being_parsed_; 1732 // Move this struct to the back of the vector just in case it was predeclared, 1733 // to preserve declaration order. 1734 *std::remove(structs_.vec.begin(), structs_.vec.end(), &struct_def) = 1735 &struct_def; 1736 *dest = &struct_def; 1737 return NoError(); 1738 } 1739 1740 CheckedError Parser::CheckClash(std::vector<FieldDef *> &fields, 1741 StructDef *struct_def, const char *suffix, 1742 BaseType basetype) { 1743 auto len = strlen(suffix); 1744 for (auto it = fields.begin(); it != fields.end(); ++it) { 1745 auto &fname = (*it)->name; 1746 if (fname.length() > len && 1747 fname.compare(fname.length() - len, len, suffix) == 0 && 1748 (*it)->value.type.base_type != BASE_TYPE_UTYPE) { 1749 auto field = 1750 struct_def->fields.Lookup(fname.substr(0, fname.length() - len)); 1751 if (field && field->value.type.base_type == basetype) 1752 return Error("Field " + fname + 1753 " would clash with generated functions for field " + 1754 field->name); 1755 } 1756 } 1757 return NoError(); 1758 } 1759 1760 bool Parser::SupportsVectorOfUnions() const { 1761 return opts.lang_to_generate != 0 && 1762 (opts.lang_to_generate & ~(IDLOptions::kCpp | IDLOptions::kJs | 1763 IDLOptions::kTs | IDLOptions::kPhp | 1764 IDLOptions::kJava | IDLOptions::kCSharp)) == 0; 1765 } 1766 1767 Namespace *Parser::UniqueNamespace(Namespace *ns) { 1768 for (auto it = namespaces_.begin(); it != namespaces_.end(); ++it) { 1769 if (ns->components == (*it)->components) { 1770 delete ns; 1771 return *it; 1772 } 1773 } 1774 namespaces_.push_back(ns); 1775 return ns; 1776 } 1777 1778 std::string Parser::UnqualifiedName(std::string full_qualified_name) { 1779 Namespace *ns = new Namespace(); 1780 1781 std::size_t current, previous = 0; 1782 current = full_qualified_name.find('.'); 1783 while (current != std::string::npos) { 1784 ns->components.push_back( 1785 full_qualified_name.substr(previous, current - previous)); 1786 previous = current + 1; 1787 current = full_qualified_name.find('.', previous); 1788 } 1789 current_namespace_ = UniqueNamespace(ns); 1790 return full_qualified_name.substr(previous, current - previous); 1791 } 1792 1793 static bool compareFieldDefs(const FieldDef *a, const FieldDef *b) { 1794 auto a_id = atoi(a->attributes.Lookup("id")->constant.c_str()); 1795 auto b_id = atoi(b->attributes.Lookup("id")->constant.c_str()); 1796 return a_id < b_id; 1797 } 1798 1799 CheckedError Parser::ParseDecl() { 1800 std::vector<std::string> dc = doc_comment_; 1801 bool fixed = IsIdent("struct"); 1802 if (!fixed && !IsIdent("table")) return Error("declaration expected"); 1803 NEXT(); 1804 std::string name = attribute_; 1805 EXPECT(kTokenIdentifier); 1806 StructDef *struct_def; 1807 ECHECK(StartStruct(name, &struct_def)); 1808 struct_def->doc_comment = dc; 1809 struct_def->fixed = fixed; 1810 ECHECK(ParseMetaData(&struct_def->attributes)); 1811 struct_def->sortbysize = 1812 struct_def->attributes.Lookup("original_order") == nullptr && !fixed; 1813 EXPECT('{'); 1814 while (token_ != '}') ECHECK(ParseField(*struct_def)); 1815 auto force_align = struct_def->attributes.Lookup("force_align"); 1816 if (fixed) { 1817 if (force_align) { 1818 auto align = static_cast<size_t>(atoi(force_align->constant.c_str())); 1819 if (force_align->type.base_type != BASE_TYPE_INT || 1820 align < struct_def->minalign || align > FLATBUFFERS_MAX_ALIGNMENT || 1821 align & (align - 1)) 1822 return Error( 1823 "force_align must be a power of two integer ranging from the" 1824 "struct\'s natural alignment to " + 1825 NumToString(FLATBUFFERS_MAX_ALIGNMENT)); 1826 struct_def->minalign = align; 1827 } 1828 if (!struct_def->bytesize) return Error("size 0 structs not allowed"); 1829 } 1830 struct_def->PadLastField(struct_def->minalign); 1831 // Check if this is a table that has manual id assignments 1832 auto &fields = struct_def->fields.vec; 1833 if (!fixed && fields.size()) { 1834 size_t num_id_fields = 0; 1835 for (auto it = fields.begin(); it != fields.end(); ++it) { 1836 if ((*it)->attributes.Lookup("id")) num_id_fields++; 1837 } 1838 // If any fields have ids.. 1839 if (num_id_fields) { 1840 // Then all fields must have them. 1841 if (num_id_fields != fields.size()) 1842 return Error( 1843 "either all fields or no fields must have an 'id' attribute"); 1844 // Simply sort by id, then the fields are the same as if no ids had 1845 // been specified. 1846 std::sort(fields.begin(), fields.end(), compareFieldDefs); 1847 // Verify we have a contiguous set, and reassign vtable offsets. 1848 for (int i = 0; i < static_cast<int>(fields.size()); i++) { 1849 if (i != atoi(fields[i]->attributes.Lookup("id")->constant.c_str())) 1850 return Error("field id\'s must be consecutive from 0, id " + 1851 NumToString(i) + " missing or set twice"); 1852 fields[i]->value.offset = FieldIndexToOffset(static_cast<voffset_t>(i)); 1853 } 1854 } 1855 } 1856 1857 ECHECK( 1858 CheckClash(fields, struct_def, UnionTypeFieldSuffix(), BASE_TYPE_UNION)); 1859 ECHECK(CheckClash(fields, struct_def, "Type", BASE_TYPE_UNION)); 1860 ECHECK(CheckClash(fields, struct_def, "_length", BASE_TYPE_VECTOR)); 1861 ECHECK(CheckClash(fields, struct_def, "Length", BASE_TYPE_VECTOR)); 1862 ECHECK(CheckClash(fields, struct_def, "_byte_vector", BASE_TYPE_STRING)); 1863 ECHECK(CheckClash(fields, struct_def, "ByteVector", BASE_TYPE_STRING)); 1864 EXPECT('}'); 1865 types_.Add(current_namespace_->GetFullyQualifiedName(struct_def->name), 1866 new Type(BASE_TYPE_STRUCT, struct_def, nullptr)); 1867 return NoError(); 1868 } 1869 1870 CheckedError Parser::ParseService() { 1871 std::vector<std::string> service_comment = doc_comment_; 1872 NEXT(); 1873 auto service_name = attribute_; 1874 EXPECT(kTokenIdentifier); 1875 auto &service_def = *new ServiceDef(); 1876 service_def.name = service_name; 1877 service_def.file = file_being_parsed_; 1878 service_def.doc_comment = service_comment; 1879 service_def.defined_namespace = current_namespace_; 1880 if (services_.Add(current_namespace_->GetFullyQualifiedName(service_name), 1881 &service_def)) 1882 return Error("service already exists: " + service_name); 1883 ECHECK(ParseMetaData(&service_def.attributes)); 1884 EXPECT('{'); 1885 do { 1886 std::vector<std::string> doc_comment = doc_comment_; 1887 auto rpc_name = attribute_; 1888 EXPECT(kTokenIdentifier); 1889 EXPECT('('); 1890 Type reqtype, resptype; 1891 ECHECK(ParseTypeIdent(reqtype)); 1892 EXPECT(')'); 1893 EXPECT(':'); 1894 ECHECK(ParseTypeIdent(resptype)); 1895 if (reqtype.base_type != BASE_TYPE_STRUCT || reqtype.struct_def->fixed || 1896 resptype.base_type != BASE_TYPE_STRUCT || resptype.struct_def->fixed) 1897 return Error("rpc request and response types must be tables"); 1898 auto &rpc = *new RPCCall(); 1899 rpc.name = rpc_name; 1900 rpc.request = reqtype.struct_def; 1901 rpc.response = resptype.struct_def; 1902 rpc.doc_comment = doc_comment; 1903 if (service_def.calls.Add(rpc_name, &rpc)) 1904 return Error("rpc already exists: " + rpc_name); 1905 ECHECK(ParseMetaData(&rpc.attributes)); 1906 EXPECT(';'); 1907 } while (token_ != '}'); 1908 NEXT(); 1909 return NoError(); 1910 } 1911 1912 bool Parser::SetRootType(const char *name) { 1913 root_struct_def_ = LookupStruct(name); 1914 if (!root_struct_def_) 1915 root_struct_def_ = 1916 LookupStruct(current_namespace_->GetFullyQualifiedName(name)); 1917 return root_struct_def_ != nullptr; 1918 } 1919 1920 void Parser::MarkGenerated() { 1921 // This function marks all existing definitions as having already 1922 // been generated, which signals no code for included files should be 1923 // generated. 1924 for (auto it = enums_.vec.begin(); it != enums_.vec.end(); ++it) { 1925 (*it)->generated = true; 1926 } 1927 for (auto it = structs_.vec.begin(); it != structs_.vec.end(); ++it) { 1928 if (!(*it)->predecl) { (*it)->generated = true; } 1929 } 1930 for (auto it = services_.vec.begin(); it != services_.vec.end(); ++it) { 1931 (*it)->generated = true; 1932 } 1933 } 1934 1935 CheckedError Parser::ParseNamespace() { 1936 NEXT(); 1937 auto ns = new Namespace(); 1938 namespaces_.push_back(ns); // Store it here to not leak upon error. 1939 if (token_ != ';') { 1940 for (;;) { 1941 ns->components.push_back(attribute_); 1942 EXPECT(kTokenIdentifier); 1943 if (Is('.')) NEXT() else break; 1944 } 1945 } 1946 namespaces_.pop_back(); 1947 current_namespace_ = UniqueNamespace(ns); 1948 EXPECT(';'); 1949 return NoError(); 1950 } 1951 1952 static bool compareEnumVals(const EnumVal *a, const EnumVal *b) { 1953 return a->value < b->value; 1954 } 1955 1956 // Best effort parsing of .proto declarations, with the aim to turn them 1957 // in the closest corresponding FlatBuffer equivalent. 1958 // We parse everything as identifiers instead of keywords, since we don't 1959 // want protobuf keywords to become invalid identifiers in FlatBuffers. 1960 CheckedError Parser::ParseProtoDecl() { 1961 bool isextend = IsIdent("extend"); 1962 if (IsIdent("package")) { 1963 // These are identical in syntax to FlatBuffer's namespace decl. 1964 ECHECK(ParseNamespace()); 1965 } else if (IsIdent("message") || isextend) { 1966 std::vector<std::string> struct_comment = doc_comment_; 1967 NEXT(); 1968 StructDef *struct_def = nullptr; 1969 Namespace *parent_namespace = nullptr; 1970 if (isextend) { 1971 if (Is('.')) NEXT(); // qualified names may start with a . ? 1972 auto id = attribute_; 1973 EXPECT(kTokenIdentifier); 1974 ECHECK(ParseNamespacing(&id, nullptr)); 1975 struct_def = LookupCreateStruct(id, false); 1976 if (!struct_def) 1977 return Error("cannot extend unknown message type: " + id); 1978 } else { 1979 std::string name = attribute_; 1980 EXPECT(kTokenIdentifier); 1981 ECHECK(StartStruct(name, &struct_def)); 1982 // Since message definitions can be nested, we create a new namespace. 1983 auto ns = new Namespace(); 1984 // Copy of current namespace. 1985 *ns = *current_namespace_; 1986 // But with current message name. 1987 ns->components.push_back(name); 1988 ns->from_table++; 1989 parent_namespace = current_namespace_; 1990 current_namespace_ = UniqueNamespace(ns); 1991 } 1992 struct_def->doc_comment = struct_comment; 1993 ECHECK(ParseProtoFields(struct_def, isextend, false)); 1994 if (!isextend) { current_namespace_ = parent_namespace; } 1995 if (Is(';')) NEXT(); 1996 } else if (IsIdent("enum")) { 1997 // These are almost the same, just with different terminator: 1998 EnumDef *enum_def; 1999 ECHECK(ParseEnum(false, &enum_def)); 2000 if (Is(';')) NEXT(); 2001 // Protobuf allows them to be specified in any order, so sort afterwards. 2002 auto &v = enum_def->vals.vec; 2003 std::sort(v.begin(), v.end(), compareEnumVals); 2004 2005 // Temp: remove any duplicates, as .fbs files can't handle them. 2006 for (auto it = v.begin(); it != v.end();) { 2007 if (it != v.begin() && it[0]->value == it[-1]->value) 2008 it = v.erase(it); 2009 else 2010 ++it; 2011 } 2012 } else if (IsIdent("syntax")) { // Skip these. 2013 NEXT(); 2014 EXPECT('='); 2015 EXPECT(kTokenStringConstant); 2016 EXPECT(';'); 2017 } else if (IsIdent("option")) { // Skip these. 2018 ECHECK(ParseProtoOption()); 2019 EXPECT(';'); 2020 } else if (IsIdent("service")) { // Skip these. 2021 NEXT(); 2022 EXPECT(kTokenIdentifier); 2023 ECHECK(ParseProtoCurliesOrIdent()); 2024 } else { 2025 return Error("don\'t know how to parse .proto declaration starting with " + 2026 TokenToStringId(token_)); 2027 } 2028 return NoError(); 2029 } 2030 2031 CheckedError Parser::StartEnum(const std::string &enum_name, bool is_union, 2032 EnumDef **dest) { 2033 auto &enum_def = *new EnumDef(); 2034 enum_def.name = enum_name; 2035 enum_def.file = file_being_parsed_; 2036 enum_def.doc_comment = doc_comment_; 2037 enum_def.is_union = is_union; 2038 enum_def.defined_namespace = current_namespace_; 2039 if (enums_.Add(current_namespace_->GetFullyQualifiedName(enum_name), 2040 &enum_def)) 2041 return Error("enum already exists: " + enum_name); 2042 enum_def.underlying_type.base_type = is_union ? BASE_TYPE_UTYPE 2043 : BASE_TYPE_INT; 2044 enum_def.underlying_type.enum_def = &enum_def; 2045 if (dest) *dest = &enum_def; 2046 return NoError(); 2047 } 2048 2049 CheckedError Parser::ParseProtoFields(StructDef *struct_def, bool isextend, 2050 bool inside_oneof) { 2051 EXPECT('{'); 2052 while (token_ != '}') { 2053 if (IsIdent("message") || IsIdent("extend") || IsIdent("enum")) { 2054 // Nested declarations. 2055 ECHECK(ParseProtoDecl()); 2056 } else if (IsIdent("extensions")) { // Skip these. 2057 NEXT(); 2058 EXPECT(kTokenIntegerConstant); 2059 if (Is(kTokenIdentifier)) { 2060 NEXT(); // to 2061 NEXT(); // num 2062 } 2063 EXPECT(';'); 2064 } else if (IsIdent("option")) { // Skip these. 2065 ECHECK(ParseProtoOption()); 2066 EXPECT(';'); 2067 } else if (IsIdent("reserved")) { // Skip these. 2068 NEXT(); 2069 while (!Is(';')) { NEXT(); } // A variety of formats, just skip. 2070 NEXT(); 2071 } else { 2072 std::vector<std::string> field_comment = doc_comment_; 2073 // Parse the qualifier. 2074 bool required = false; 2075 bool repeated = false; 2076 bool oneof = false; 2077 if (!inside_oneof) { 2078 if (IsIdent("optional")) { 2079 // This is the default. 2080 NEXT(); 2081 } else if (IsIdent("required")) { 2082 required = true; 2083 NEXT(); 2084 } else if (IsIdent("repeated")) { 2085 repeated = true; 2086 NEXT(); 2087 } else if (IsIdent("oneof")) { 2088 oneof = true; 2089 NEXT(); 2090 } else { 2091 // can't error, proto3 allows decls without any of the above. 2092 } 2093 } 2094 StructDef *anonymous_struct = nullptr; 2095 EnumDef *oneof_union = nullptr; 2096 Type type; 2097 if (IsIdent("group") || oneof) { 2098 if (!oneof) NEXT(); 2099 if (oneof && opts.proto_oneof_union) { 2100 auto name = MakeCamel(attribute_, true) + "Union"; 2101 ECHECK(StartEnum(name, true, &oneof_union)); 2102 type = Type(BASE_TYPE_UNION, nullptr, oneof_union); 2103 } else { 2104 auto name = "Anonymous" + NumToString(anonymous_counter++); 2105 ECHECK(StartStruct(name, &anonymous_struct)); 2106 type = Type(BASE_TYPE_STRUCT, anonymous_struct); 2107 } 2108 } else { 2109 ECHECK(ParseTypeFromProtoType(&type)); 2110 } 2111 // Repeated elements get mapped to a vector. 2112 if (repeated) { 2113 type.element = type.base_type; 2114 type.base_type = BASE_TYPE_VECTOR; 2115 if (type.element == BASE_TYPE_VECTOR) { 2116 // We have a vector or vectors, which FlatBuffers doesn't support. 2117 // For now make it a vector of string (since the source is likely 2118 // "repeated bytes"). 2119 // TODO(wvo): A better solution would be to wrap this in a table. 2120 type.element = BASE_TYPE_STRING; 2121 } 2122 } 2123 std::string name = attribute_; 2124 EXPECT(kTokenIdentifier); 2125 if (!oneof) { 2126 // Parse the field id. Since we're just translating schemas, not 2127 // any kind of binary compatibility, we can safely ignore these, and 2128 // assign our own. 2129 EXPECT('='); 2130 EXPECT(kTokenIntegerConstant); 2131 } 2132 FieldDef *field = nullptr; 2133 if (isextend) { 2134 // We allow a field to be re-defined when extending. 2135 // TODO: are there situations where that is problematic? 2136 field = struct_def->fields.Lookup(name); 2137 } 2138 if (!field) ECHECK(AddField(*struct_def, name, type, &field)); 2139 field->doc_comment = field_comment; 2140 if (!IsScalar(type.base_type)) field->required = required; 2141 // See if there's a default specified. 2142 if (Is('[')) { 2143 NEXT(); 2144 for (;;) { 2145 auto key = attribute_; 2146 ECHECK(ParseProtoKey()); 2147 EXPECT('='); 2148 auto val = attribute_; 2149 ECHECK(ParseProtoCurliesOrIdent()); 2150 if (key == "default") { 2151 // Temp: skip non-numeric defaults (enums). 2152 auto numeric = strpbrk(val.c_str(), "0123456789-+."); 2153 if (IsScalar(type.base_type) && numeric == val.c_str()) 2154 field->value.constant = val; 2155 } else if (key == "deprecated") { 2156 field->deprecated = val == "true"; 2157 } 2158 if (!Is(',')) break; 2159 NEXT(); 2160 } 2161 EXPECT(']'); 2162 } 2163 if (anonymous_struct) { 2164 ECHECK(ParseProtoFields(anonymous_struct, false, oneof)); 2165 if (Is(';')) NEXT(); 2166 } else if (oneof_union) { 2167 // Parse into a temporary StructDef, then transfer fields into an 2168 // EnumDef describing the oneof as a union. 2169 StructDef oneof_struct; 2170 ECHECK(ParseProtoFields(&oneof_struct, false, oneof)); 2171 if (Is(';')) NEXT(); 2172 for (auto field_it = oneof_struct.fields.vec.begin(); 2173 field_it != oneof_struct.fields.vec.end(); ++field_it) { 2174 const auto &oneof_field = **field_it; 2175 const auto &oneof_type = oneof_field.value.type; 2176 if (oneof_type.base_type != BASE_TYPE_STRUCT || 2177 !oneof_type.struct_def || oneof_type.struct_def->fixed) 2178 return Error("oneof '" + name + 2179 "' cannot be mapped to a union because member '" + 2180 oneof_field.name + "' is not a table type."); 2181 auto enum_val = new EnumVal(oneof_type.struct_def->name, 2182 oneof_union->vals.vec.size()); 2183 enum_val->union_type = oneof_type; 2184 enum_val->doc_comment = oneof_field.doc_comment; 2185 oneof_union->vals.Add(oneof_field.name, enum_val); 2186 } 2187 } else { 2188 EXPECT(';'); 2189 } 2190 } 2191 } 2192 NEXT(); 2193 return NoError(); 2194 } 2195 2196 CheckedError Parser::ParseProtoKey() { 2197 if (token_ == '(') { 2198 NEXT(); 2199 // Skip "(a.b)" style custom attributes. 2200 while (token_ == '.' || token_ == kTokenIdentifier) NEXT(); 2201 EXPECT(')'); 2202 while (Is('.')) { 2203 NEXT(); 2204 EXPECT(kTokenIdentifier); 2205 } 2206 } else { 2207 EXPECT(kTokenIdentifier); 2208 } 2209 return NoError(); 2210 } 2211 2212 CheckedError Parser::ParseProtoCurliesOrIdent() { 2213 if (Is('{')) { 2214 NEXT(); 2215 for (int nesting = 1; nesting;) { 2216 if (token_ == '{') 2217 nesting++; 2218 else if (token_ == '}') 2219 nesting--; 2220 NEXT(); 2221 } 2222 } else { 2223 NEXT(); // Any single token. 2224 } 2225 return NoError(); 2226 } 2227 2228 CheckedError Parser::ParseProtoOption() { 2229 NEXT(); 2230 ECHECK(ParseProtoKey()); 2231 EXPECT('='); 2232 ECHECK(ParseProtoCurliesOrIdent()); 2233 return NoError(); 2234 } 2235 2236 // Parse a protobuf type, and map it to the corresponding FlatBuffer one. 2237 CheckedError Parser::ParseTypeFromProtoType(Type *type) { 2238 struct type_lookup { 2239 const char *proto_type; 2240 BaseType fb_type, element; 2241 }; 2242 static type_lookup lookup[] = { 2243 { "float", BASE_TYPE_FLOAT, BASE_TYPE_NONE }, 2244 { "double", BASE_TYPE_DOUBLE, BASE_TYPE_NONE }, 2245 { "int32", BASE_TYPE_INT, BASE_TYPE_NONE }, 2246 { "int64", BASE_TYPE_LONG, BASE_TYPE_NONE }, 2247 { "uint32", BASE_TYPE_UINT, BASE_TYPE_NONE }, 2248 { "uint64", BASE_TYPE_ULONG, BASE_TYPE_NONE }, 2249 { "sint32", BASE_TYPE_INT, BASE_TYPE_NONE }, 2250 { "sint64", BASE_TYPE_LONG, BASE_TYPE_NONE }, 2251 { "fixed32", BASE_TYPE_UINT, BASE_TYPE_NONE }, 2252 { "fixed64", BASE_TYPE_ULONG, BASE_TYPE_NONE }, 2253 { "sfixed32", BASE_TYPE_INT, BASE_TYPE_NONE }, 2254 { "sfixed64", BASE_TYPE_LONG, BASE_TYPE_NONE }, 2255 { "bool", BASE_TYPE_BOOL, BASE_TYPE_NONE }, 2256 { "string", BASE_TYPE_STRING, BASE_TYPE_NONE }, 2257 { "bytes", BASE_TYPE_VECTOR, BASE_TYPE_UCHAR }, 2258 { nullptr, BASE_TYPE_NONE, BASE_TYPE_NONE } 2259 }; 2260 for (auto tl = lookup; tl->proto_type; tl++) { 2261 if (attribute_ == tl->proto_type) { 2262 type->base_type = tl->fb_type; 2263 type->element = tl->element; 2264 NEXT(); 2265 return NoError(); 2266 } 2267 } 2268 if (Is('.')) NEXT(); // qualified names may start with a . ? 2269 ECHECK(ParseTypeIdent(*type)); 2270 return NoError(); 2271 } 2272 2273 CheckedError Parser::SkipAnyJsonValue() { 2274 switch (token_) { 2275 case '{': { 2276 size_t fieldn_outer = 0; 2277 return ParseTableDelimiters( 2278 fieldn_outer, nullptr, 2279 [&](const std::string &, size_t &fieldn, 2280 const StructDef *) -> CheckedError { 2281 ECHECK(Recurse([&]() { return SkipAnyJsonValue(); })); 2282 fieldn++; 2283 return NoError(); 2284 }); 2285 } 2286 case '[': { 2287 size_t count = 0; 2288 return ParseVectorDelimiters(count, [&](size_t &) -> CheckedError { 2289 return Recurse([&]() { return SkipAnyJsonValue(); }); 2290 }); 2291 } 2292 case kTokenStringConstant: 2293 case kTokenIntegerConstant: 2294 case kTokenFloatConstant: NEXT(); break; 2295 default: 2296 if (IsIdent("true") || IsIdent("false") || IsIdent("null")) { 2297 NEXT(); 2298 } else 2299 return TokenError(); 2300 } 2301 return NoError(); 2302 } 2303 2304 CheckedError Parser::ParseFlexBufferValue(flexbuffers::Builder *builder) { 2305 switch (token_) { 2306 case '{': { 2307 auto start = builder->StartMap(); 2308 size_t fieldn_outer = 0; 2309 auto err = 2310 ParseTableDelimiters(fieldn_outer, nullptr, 2311 [&](const std::string &name, size_t &fieldn, 2312 const StructDef *) -> CheckedError { 2313 builder->Key(name); 2314 ECHECK(ParseFlexBufferValue(builder)); 2315 fieldn++; 2316 return NoError(); 2317 }); 2318 ECHECK(err); 2319 builder->EndMap(start); 2320 break; 2321 } 2322 case '[': { 2323 auto start = builder->StartVector(); 2324 size_t count = 0; 2325 ECHECK(ParseVectorDelimiters(count, [&](size_t &) -> CheckedError { 2326 return ParseFlexBufferValue(builder); 2327 })); 2328 builder->EndVector(start, false, false); 2329 break; 2330 } 2331 case kTokenStringConstant: 2332 builder->String(attribute_); 2333 EXPECT(kTokenStringConstant); 2334 break; 2335 case kTokenIntegerConstant: 2336 builder->Int(StringToInt(attribute_.c_str())); 2337 EXPECT(kTokenIntegerConstant); 2338 break; 2339 case kTokenFloatConstant: 2340 builder->Double(strtod(attribute_.c_str(), nullptr)); 2341 EXPECT(kTokenFloatConstant); 2342 break; 2343 default: 2344 if (IsIdent("true")) { 2345 builder->Bool(true); 2346 NEXT(); 2347 } else if (IsIdent("false")) { 2348 builder->Bool(false); 2349 NEXT(); 2350 } else if (IsIdent("null")) { 2351 builder->Null(); 2352 NEXT(); 2353 } else 2354 return TokenError(); 2355 } 2356 return NoError(); 2357 } 2358 2359 bool Parser::ParseFlexBuffer(const char *source, const char *source_filename, 2360 flexbuffers::Builder *builder) { 2361 auto ok = !StartParseFile(source, source_filename).Check() && 2362 !ParseFlexBufferValue(builder).Check(); 2363 if (ok) builder->Finish(); 2364 return ok; 2365 } 2366 2367 bool Parser::Parse(const char *source, const char **include_paths, 2368 const char *source_filename) { 2369 FLATBUFFERS_ASSERT(0 == recurse_protection_counter); 2370 auto r = !ParseRoot(source, include_paths, source_filename).Check(); 2371 FLATBUFFERS_ASSERT(0 == recurse_protection_counter); 2372 return r; 2373 } 2374 2375 CheckedError Parser::StartParseFile(const char *source, 2376 const char *source_filename) { 2377 file_being_parsed_ = source_filename ? source_filename : ""; 2378 source_ = source; 2379 ResetState(source_); 2380 error_.clear(); 2381 ECHECK(SkipByteOrderMark()); 2382 NEXT(); 2383 if (Is(kTokenEof)) return Error("input file is empty"); 2384 return NoError(); 2385 } 2386 2387 CheckedError Parser::ParseRoot(const char *source, const char **include_paths, 2388 const char *source_filename) { 2389 ECHECK(DoParse(source, include_paths, source_filename, nullptr)); 2390 2391 // Check that all types were defined. 2392 for (auto it = structs_.vec.begin(); it != structs_.vec.end();) { 2393 auto &struct_def = **it; 2394 if (struct_def.predecl) { 2395 if (opts.proto_mode) { 2396 // Protos allow enums to be used before declaration, so check if that 2397 // is the case here. 2398 EnumDef *enum_def = nullptr; 2399 for (size_t components = 2400 struct_def.defined_namespace->components.size() + 1; 2401 components && !enum_def; components--) { 2402 auto qualified_name = 2403 struct_def.defined_namespace->GetFullyQualifiedName( 2404 struct_def.name, components - 1); 2405 enum_def = LookupEnum(qualified_name); 2406 } 2407 if (enum_def) { 2408 // This is pretty slow, but a simple solution for now. 2409 auto initial_count = struct_def.refcount; 2410 for (auto struct_it = structs_.vec.begin(); 2411 struct_it != structs_.vec.end(); ++struct_it) { 2412 auto &sd = **struct_it; 2413 for (auto field_it = sd.fields.vec.begin(); 2414 field_it != sd.fields.vec.end(); ++field_it) { 2415 auto &field = **field_it; 2416 if (field.value.type.struct_def == &struct_def) { 2417 field.value.type.struct_def = nullptr; 2418 field.value.type.enum_def = enum_def; 2419 auto &bt = field.value.type.base_type == BASE_TYPE_VECTOR 2420 ? field.value.type.element 2421 : field.value.type.base_type; 2422 FLATBUFFERS_ASSERT(bt == BASE_TYPE_STRUCT); 2423 bt = enum_def->underlying_type.base_type; 2424 struct_def.refcount--; 2425 enum_def->refcount++; 2426 } 2427 } 2428 } 2429 if (struct_def.refcount) 2430 return Error("internal: " + NumToString(struct_def.refcount) + "/" + 2431 NumToString(initial_count) + 2432 " use(s) of pre-declaration enum not accounted for: " + 2433 enum_def->name); 2434 structs_.dict.erase(structs_.dict.find(struct_def.name)); 2435 it = structs_.vec.erase(it); 2436 delete &struct_def; 2437 continue; // Skip error. 2438 } 2439 } 2440 auto err = "type referenced but not defined (check namespace): " + 2441 struct_def.name; 2442 if (struct_def.original_location) 2443 err += ", originally at: " + *struct_def.original_location; 2444 return Error(err); 2445 } 2446 ++it; 2447 } 2448 2449 // This check has to happen here and not earlier, because only now do we 2450 // know for sure what the type of these are. 2451 for (auto it = enums_.vec.begin(); it != enums_.vec.end(); ++it) { 2452 auto &enum_def = **it; 2453 if (enum_def.is_union) { 2454 for (auto val_it = enum_def.vals.vec.begin(); 2455 val_it != enum_def.vals.vec.end(); ++val_it) { 2456 auto &val = **val_it; 2457 if (!SupportsVectorOfUnions() && val.union_type.struct_def && 2458 val.union_type.struct_def->fixed) 2459 return Error( 2460 "only tables can be union elements in the generated language: " + 2461 val.name); 2462 } 2463 } 2464 } 2465 return NoError(); 2466 } 2467 2468 CheckedError Parser::DoParse(const char *source, const char **include_paths, 2469 const char *source_filename, 2470 const char *include_filename) { 2471 if (source_filename) { 2472 if (included_files_.find(source_filename) == included_files_.end()) { 2473 included_files_[source_filename] = 2474 include_filename ? include_filename : ""; 2475 files_included_per_file_[source_filename] = std::set<std::string>(); 2476 } else { 2477 return NoError(); 2478 } 2479 } 2480 if (!include_paths) { 2481 static const char *current_directory[] = { "", nullptr }; 2482 include_paths = current_directory; 2483 } 2484 field_stack_.clear(); 2485 builder_.Clear(); 2486 // Start with a blank namespace just in case this file doesn't have one. 2487 current_namespace_ = empty_namespace_; 2488 2489 ECHECK(StartParseFile(source, source_filename)); 2490 2491 // Includes must come before type declarations: 2492 for (;;) { 2493 // Parse pre-include proto statements if any: 2494 if (opts.proto_mode && (attribute_ == "option" || attribute_ == "syntax" || 2495 attribute_ == "package")) { 2496 ECHECK(ParseProtoDecl()); 2497 } else if (IsIdent("native_include")) { 2498 NEXT(); 2499 vector_emplace_back(&native_included_files_, attribute_); 2500 EXPECT(kTokenStringConstant); 2501 EXPECT(';'); 2502 } else if (IsIdent("include") || (opts.proto_mode && IsIdent("import"))) { 2503 NEXT(); 2504 if (opts.proto_mode && attribute_ == "public") NEXT(); 2505 auto name = flatbuffers::PosixPath(attribute_.c_str()); 2506 EXPECT(kTokenStringConstant); 2507 // Look for the file in include_paths. 2508 std::string filepath; 2509 for (auto paths = include_paths; paths && *paths; paths++) { 2510 filepath = flatbuffers::ConCatPathFileName(*paths, name); 2511 if (FileExists(filepath.c_str())) break; 2512 } 2513 if (filepath.empty()) 2514 return Error("unable to locate include file: " + name); 2515 if (source_filename) 2516 files_included_per_file_[source_filename].insert(filepath); 2517 if (included_files_.find(filepath) == included_files_.end()) { 2518 // We found an include file that we have not parsed yet. 2519 // Load it and parse it. 2520 std::string contents; 2521 if (!LoadFile(filepath.c_str(), true, &contents)) 2522 return Error("unable to load include file: " + name); 2523 ECHECK(DoParse(contents.c_str(), include_paths, filepath.c_str(), 2524 name.c_str())); 2525 // We generally do not want to output code for any included files: 2526 if (!opts.generate_all) MarkGenerated(); 2527 // Reset these just in case the included file had them, and the 2528 // parent doesn't. 2529 root_struct_def_ = nullptr; 2530 file_identifier_.clear(); 2531 file_extension_.clear(); 2532 // This is the easiest way to continue this file after an include: 2533 // instead of saving and restoring all the state, we simply start the 2534 // file anew. This will cause it to encounter the same include 2535 // statement again, but this time it will skip it, because it was 2536 // entered into included_files_. 2537 // This is recursive, but only go as deep as the number of include 2538 // statements. 2539 if (source_filename) { 2540 included_files_.erase(source_filename); 2541 } 2542 return DoParse(source, include_paths, source_filename, 2543 include_filename); 2544 } 2545 EXPECT(';'); 2546 } else { 2547 break; 2548 } 2549 } 2550 // Now parse all other kinds of declarations: 2551 while (token_ != kTokenEof) { 2552 if (opts.proto_mode) { 2553 ECHECK(ParseProtoDecl()); 2554 } else if (IsIdent("namespace")) { 2555 ECHECK(ParseNamespace()); 2556 } else if (token_ == '{') { 2557 if (!root_struct_def_) 2558 return Error("no root type set to parse json with"); 2559 if (builder_.GetSize()) { 2560 return Error("cannot have more than one json object in a file"); 2561 } 2562 uoffset_t toff; 2563 ECHECK(ParseTable(*root_struct_def_, nullptr, &toff)); 2564 if (opts.size_prefixed) { 2565 builder_.FinishSizePrefixed(Offset<Table>(toff), file_identifier_.length() 2566 ? file_identifier_.c_str() 2567 : nullptr); 2568 } else { 2569 builder_.Finish(Offset<Table>(toff), file_identifier_.length() 2570 ? file_identifier_.c_str() 2571 : nullptr); 2572 } 2573 // Check that JSON file doesn't contain more objects or IDL directives. 2574 // Comments after JSON are allowed. 2575 EXPECT(kTokenEof); 2576 } else if (IsIdent("enum")) { 2577 ECHECK(ParseEnum(false, nullptr)); 2578 } else if (IsIdent("union")) { 2579 ECHECK(ParseEnum(true, nullptr)); 2580 } else if (IsIdent("root_type")) { 2581 NEXT(); 2582 auto root_type = attribute_; 2583 EXPECT(kTokenIdentifier); 2584 ECHECK(ParseNamespacing(&root_type, nullptr)); 2585 if (opts.root_type.empty()) { 2586 if (!SetRootType(root_type.c_str())) 2587 return Error("unknown root type: " + root_type); 2588 if (root_struct_def_->fixed) 2589 return Error("root type must be a table"); 2590 } 2591 EXPECT(';'); 2592 } else if (IsIdent("file_identifier")) { 2593 NEXT(); 2594 file_identifier_ = attribute_; 2595 EXPECT(kTokenStringConstant); 2596 if (file_identifier_.length() != FlatBufferBuilder::kFileIdentifierLength) 2597 return Error("file_identifier must be exactly " + 2598 NumToString(FlatBufferBuilder::kFileIdentifierLength) + 2599 " characters"); 2600 EXPECT(';'); 2601 } else if (IsIdent("file_extension")) { 2602 NEXT(); 2603 file_extension_ = attribute_; 2604 EXPECT(kTokenStringConstant); 2605 EXPECT(';'); 2606 } else if (IsIdent("include")) { 2607 return Error("includes must come before declarations"); 2608 } else if (IsIdent("attribute")) { 2609 NEXT(); 2610 auto name = attribute_; 2611 if (Is(kTokenIdentifier)) { 2612 NEXT(); 2613 } else { 2614 EXPECT(kTokenStringConstant); 2615 } 2616 EXPECT(';'); 2617 known_attributes_[name] = false; 2618 } else if (IsIdent("rpc_service")) { 2619 ECHECK(ParseService()); 2620 } else { 2621 ECHECK(ParseDecl()); 2622 } 2623 } 2624 return NoError(); 2625 } 2626 2627 std::set<std::string> Parser::GetIncludedFilesRecursive( 2628 const std::string &file_name) const { 2629 std::set<std::string> included_files; 2630 std::list<std::string> to_process; 2631 2632 if (file_name.empty()) return included_files; 2633 to_process.push_back(file_name); 2634 2635 while (!to_process.empty()) { 2636 std::string current = to_process.front(); 2637 to_process.pop_front(); 2638 included_files.insert(current); 2639 2640 // Workaround the lack of const accessor in C++98 maps. 2641 auto &new_files = 2642 (*const_cast<std::map<std::string, std::set<std::string>> *>( 2643 &files_included_per_file_))[current]; 2644 for (auto it = new_files.begin(); it != new_files.end(); ++it) { 2645 if (included_files.find(*it) == included_files.end()) 2646 to_process.push_back(*it); 2647 } 2648 } 2649 2650 return included_files; 2651 } 2652 2653 // Schema serialization functionality: 2654 2655 template<typename T> bool compareName(const T *a, const T *b) { 2656 return a->defined_namespace->GetFullyQualifiedName(a->name) < 2657 b->defined_namespace->GetFullyQualifiedName(b->name); 2658 } 2659 2660 template<typename T> void AssignIndices(const std::vector<T *> &defvec) { 2661 // Pre-sort these vectors, such that we can set the correct indices for them. 2662 auto vec = defvec; 2663 std::sort(vec.begin(), vec.end(), compareName<T>); 2664 for (int i = 0; i < static_cast<int>(vec.size()); i++) vec[i]->index = i; 2665 } 2666 2667 void Parser::Serialize() { 2668 builder_.Clear(); 2669 AssignIndices(structs_.vec); 2670 AssignIndices(enums_.vec); 2671 std::vector<Offset<reflection::Object>> object_offsets; 2672 for (auto it = structs_.vec.begin(); it != structs_.vec.end(); ++it) { 2673 auto offset = (*it)->Serialize(&builder_, *this); 2674 object_offsets.push_back(offset); 2675 (*it)->serialized_location = offset.o; 2676 } 2677 std::vector<Offset<reflection::Enum>> enum_offsets; 2678 for (auto it = enums_.vec.begin(); it != enums_.vec.end(); ++it) { 2679 auto offset = (*it)->Serialize(&builder_, *this); 2680 enum_offsets.push_back(offset); 2681 (*it)->serialized_location = offset.o; 2682 } 2683 std::vector<Offset<reflection::Service>> service_offsets; 2684 for (auto it = services_.vec.begin(); it != services_.vec.end(); ++it) { 2685 auto offset = (*it)->Serialize(&builder_, *this); 2686 service_offsets.push_back(offset); 2687 (*it)->serialized_location = offset.o; 2688 } 2689 auto objs__ = builder_.CreateVectorOfSortedTables(&object_offsets); 2690 auto enum__ = builder_.CreateVectorOfSortedTables(&enum_offsets); 2691 auto fiid__ = builder_.CreateString(file_identifier_); 2692 auto fext__ = builder_.CreateString(file_extension_); 2693 auto serv__ = builder_.CreateVectorOfSortedTables(&service_offsets); 2694 auto schema_offset = 2695 reflection::CreateSchema(builder_, objs__, enum__, fiid__, fext__, 2696 (root_struct_def_ ? root_struct_def_->serialized_location : 0), 2697 serv__); 2698 if (opts.size_prefixed) { 2699 builder_.FinishSizePrefixed(schema_offset, reflection::SchemaIdentifier()); 2700 } else { 2701 builder_.Finish(schema_offset, reflection::SchemaIdentifier()); 2702 } 2703 } 2704 2705 static Namespace *GetNamespace( 2706 const std::string &qualified_name, std::vector<Namespace *> &namespaces, 2707 std::map<std::string, Namespace *> &namespaces_index) { 2708 size_t dot = qualified_name.find_last_of('.'); 2709 std::string namespace_name = (dot != std::string::npos) 2710 ? std::string(qualified_name.c_str(), dot) 2711 : ""; 2712 Namespace *&ns = namespaces_index[namespace_name]; 2713 2714 if (!ns) { 2715 ns = new Namespace(); 2716 namespaces.push_back(ns); 2717 2718 size_t pos = 0; 2719 2720 for (;;) { 2721 dot = qualified_name.find('.', pos); 2722 if (dot == std::string::npos) { break; } 2723 ns->components.push_back(qualified_name.substr(pos, dot-pos)); 2724 pos = dot + 1; 2725 } 2726 } 2727 2728 return ns; 2729 } 2730 2731 Offset<reflection::Object> StructDef::Serialize(FlatBufferBuilder *builder, 2732 const Parser &parser) const { 2733 std::vector<Offset<reflection::Field>> field_offsets; 2734 for (auto it = fields.vec.begin(); it != fields.vec.end(); ++it) { 2735 field_offsets.push_back((*it)->Serialize( 2736 builder, static_cast<uint16_t>(it - fields.vec.begin()), parser)); 2737 } 2738 auto qualified_name = defined_namespace->GetFullyQualifiedName(name); 2739 auto name__ = builder->CreateString(qualified_name); 2740 auto flds__ = builder->CreateVectorOfSortedTables(&field_offsets); 2741 auto attr__ = SerializeAttributes(builder, parser); 2742 auto docs__ = parser.opts.binary_schema_comments 2743 ? builder->CreateVectorOfStrings(doc_comment) 2744 : 0; 2745 return reflection::CreateObject(*builder, name__, flds__, fixed, 2746 static_cast<int>(minalign), 2747 static_cast<int>(bytesize), 2748 attr__, docs__); 2749 } 2750 2751 bool StructDef::Deserialize(Parser &parser, const reflection::Object *object) { 2752 if (!DeserializeAttributes(parser, object->attributes())) 2753 return false; 2754 DeserializeDoc(doc_comment, object->documentation()); 2755 name = parser.UnqualifiedName(object->name()->str()); 2756 fixed = object->is_struct(); 2757 minalign = object->minalign(); 2758 predecl = false; 2759 sortbysize = attributes.Lookup("original_order") == nullptr && !fixed; 2760 std::vector<uoffset_t> indexes = 2761 std::vector<uoffset_t>(object->fields()->size()); 2762 for (uoffset_t i = 0; i < object->fields()->size(); i++) 2763 indexes[object->fields()->Get(i)->id()] = i; 2764 for (size_t i = 0; i < indexes.size(); i++) { 2765 auto field = object->fields()->Get(indexes[i]); 2766 auto field_def = new FieldDef(); 2767 if (!field_def->Deserialize(parser, field) || 2768 fields.Add(field_def->name, field_def)) { 2769 delete field_def; 2770 return false; 2771 } 2772 if (fixed) { 2773 // Recompute padding since that's currently not serialized. 2774 auto size = InlineSize(field_def->value.type); 2775 auto next_field = 2776 i + 1 < indexes.size() 2777 ? object->fields()->Get(indexes[i+1]) 2778 : nullptr; 2779 bytesize += size; 2780 field_def->padding = 2781 next_field ? (next_field->offset() - field_def->value.offset) - size 2782 : PaddingBytes(bytesize, minalign); 2783 bytesize += field_def->padding; 2784 } 2785 } 2786 FLATBUFFERS_ASSERT(static_cast<int>(bytesize) == object->bytesize()); 2787 return true; 2788 } 2789 2790 Offset<reflection::Field> FieldDef::Serialize(FlatBufferBuilder *builder, 2791 uint16_t id, 2792 const Parser &parser) const { 2793 auto name__ = builder->CreateString(name); 2794 auto type__ = value.type.Serialize(builder); 2795 auto attr__ = SerializeAttributes(builder, parser); 2796 auto docs__ = parser.opts.binary_schema_comments 2797 ? builder->CreateVectorOfStrings(doc_comment) 2798 : 0; 2799 return reflection::CreateField(*builder, name__, type__, id, value.offset, 2800 // Is uint64>max(int64) tested? 2801 IsInteger(value.type.base_type) ? StringToInt(value.constant.c_str()) : 0, 2802 // result may be platform-dependent if underlying is float (not double) 2803 IsFloat(value.type.base_type) ? strtod(value.constant.c_str(), nullptr) 2804 : 0.0, 2805 deprecated, required, key, attr__, docs__); 2806 // TODO: value.constant is almost always "0", we could save quite a bit of 2807 // space by sharing it. Same for common values of value.type. 2808 } 2809 2810 bool FieldDef::Deserialize(Parser &parser, const reflection::Field *field) { 2811 name = parser.UnqualifiedName(field->name()->str()); 2812 defined_namespace = parser.current_namespace_; 2813 if (!value.type.Deserialize(parser, field->type())) 2814 return false; 2815 value.offset = field->offset(); 2816 if (IsInteger(value.type.base_type)) { 2817 value.constant = NumToString(field->default_integer()); 2818 } else if (IsFloat(value.type.base_type)) { 2819 value.constant = FloatToString(field->default_real(), 16); 2820 size_t last_zero = value.constant.find_last_not_of('0'); 2821 if (last_zero != std::string::npos && last_zero != 0) { 2822 value.constant.erase(last_zero, std::string::npos); 2823 } 2824 } 2825 deprecated = field->deprecated(); 2826 required = field->required(); 2827 key = field->key(); 2828 if (!DeserializeAttributes(parser, field->attributes())) 2829 return false; 2830 // TODO: this should probably be handled by a separate attribute 2831 if (attributes.Lookup("flexbuffer")) { 2832 flexbuffer = true; 2833 parser.uses_flexbuffers_ = true; 2834 if (value.type.base_type != BASE_TYPE_VECTOR || 2835 value.type.element != BASE_TYPE_UCHAR) 2836 return false; 2837 } 2838 DeserializeDoc(doc_comment, field->documentation()); 2839 return true; 2840 } 2841 2842 Offset<reflection::RPCCall> RPCCall::Serialize(FlatBufferBuilder *builder, 2843 const Parser &parser) const { 2844 auto name__ = builder->CreateString(name); 2845 auto attr__ = SerializeAttributes(builder, parser); 2846 auto docs__ = parser.opts.binary_schema_comments 2847 ? builder->CreateVectorOfStrings(doc_comment) 2848 : 0; 2849 return reflection::CreateRPCCall(*builder, name__, 2850 request->serialized_location, 2851 response->serialized_location, 2852 attr__, docs__); 2853 } 2854 2855 bool RPCCall::Deserialize(Parser &parser, const reflection::RPCCall *call) { 2856 name = call->name()->str(); 2857 if (!DeserializeAttributes(parser, call->attributes())) 2858 return false; 2859 DeserializeDoc(doc_comment, call->documentation()); 2860 request = parser.structs_.Lookup(call->request()->name()->str()); 2861 response = parser.structs_.Lookup(call->response()->name()->str()); 2862 if (!request || !response) { return false; } 2863 return true; 2864 } 2865 2866 Offset<reflection::Service> ServiceDef::Serialize(FlatBufferBuilder *builder, 2867 const Parser &parser) const { 2868 std::vector<Offset<reflection::RPCCall>> servicecall_offsets; 2869 for (auto it = calls.vec.begin(); it != calls.vec.end(); ++it) { 2870 servicecall_offsets.push_back((*it)->Serialize(builder, parser)); 2871 } 2872 auto qualified_name = defined_namespace->GetFullyQualifiedName(name); 2873 auto name__ = builder->CreateString(qualified_name); 2874 auto call__ = builder->CreateVector(servicecall_offsets); 2875 auto attr__ = SerializeAttributes(builder, parser); 2876 auto docs__ = parser.opts.binary_schema_comments 2877 ? builder->CreateVectorOfStrings(doc_comment) 2878 : 0; 2879 return reflection::CreateService(*builder, name__, call__, attr__, docs__); 2880 } 2881 2882 bool ServiceDef::Deserialize(Parser &parser, 2883 const reflection::Service *service) { 2884 name = parser.UnqualifiedName(service->name()->str()); 2885 if (service->calls()) { 2886 for (uoffset_t i = 0; i < service->calls()->size(); ++i) { 2887 auto call = new RPCCall(); 2888 if (!call->Deserialize(parser, service->calls()->Get(i)) || 2889 calls.Add(call->name, call)) { 2890 delete call; 2891 return false; 2892 } 2893 } 2894 } 2895 if (!DeserializeAttributes(parser, service->attributes())) 2896 return false; 2897 DeserializeDoc(doc_comment, service->documentation()); 2898 return true; 2899 } 2900 2901 Offset<reflection::Enum> EnumDef::Serialize(FlatBufferBuilder *builder, 2902 const Parser &parser) const { 2903 std::vector<Offset<reflection::EnumVal>> enumval_offsets; 2904 for (auto it = vals.vec.begin(); it != vals.vec.end(); ++it) { 2905 enumval_offsets.push_back((*it)->Serialize(builder, parser)); 2906 } 2907 auto qualified_name = defined_namespace->GetFullyQualifiedName(name); 2908 auto name__ = builder->CreateString(qualified_name); 2909 auto vals__ = builder->CreateVector(enumval_offsets); 2910 auto type__ = underlying_type.Serialize(builder); 2911 auto attr__ = SerializeAttributes(builder, parser); 2912 auto docs__ = parser.opts.binary_schema_comments 2913 ? builder->CreateVectorOfStrings(doc_comment) 2914 : 0; 2915 return reflection::CreateEnum(*builder, name__, vals__, is_union, type__, 2916 attr__, docs__); 2917 } 2918 2919 bool EnumDef::Deserialize(Parser &parser, const reflection::Enum *_enum) { 2920 name = parser.UnqualifiedName(_enum->name()->str()); 2921 for (uoffset_t i = 0; i < _enum->values()->size(); ++i) { 2922 auto val = new EnumVal(); 2923 if (!val->Deserialize(parser, _enum->values()->Get(i)) || 2924 vals.Add(val->name, val)) { 2925 delete val; 2926 return false; 2927 } 2928 } 2929 is_union = _enum->is_union(); 2930 if (!underlying_type.Deserialize(parser, _enum->underlying_type())) { 2931 return false; 2932 } 2933 if (!DeserializeAttributes(parser, _enum->attributes())) 2934 return false; 2935 DeserializeDoc(doc_comment, _enum->documentation()); 2936 return true; 2937 } 2938 2939 Offset<reflection::EnumVal> EnumVal::Serialize(FlatBufferBuilder *builder, 2940 const Parser &parser) const { 2941 auto name__ = builder->CreateString(name); 2942 auto type__ = union_type.Serialize(builder); 2943 auto docs__ = parser.opts.binary_schema_comments 2944 ? builder->CreateVectorOfStrings(doc_comment) 2945 : 0; 2946 return reflection::CreateEnumVal(*builder, name__, value, 2947 union_type.struct_def ? union_type.struct_def->serialized_location : 0, 2948 type__, docs__); 2949 } 2950 2951 bool EnumVal::Deserialize(const Parser &parser, 2952 const reflection::EnumVal *val) { 2953 name = val->name()->str(); 2954 value = val->value(); 2955 if (!union_type.Deserialize(parser, val->union_type())) 2956 return false; 2957 DeserializeDoc(doc_comment, val->documentation()); 2958 return true; 2959 } 2960 2961 Offset<reflection::Type> Type::Serialize(FlatBufferBuilder *builder) const { 2962 return reflection::CreateType( 2963 *builder, 2964 static_cast<reflection::BaseType>(base_type), 2965 static_cast<reflection::BaseType>(element), 2966 struct_def ? struct_def->index : (enum_def ? enum_def->index : -1)); 2967 } 2968 2969 bool Type::Deserialize(const Parser &parser, const reflection::Type *type) { 2970 if (type == nullptr) return true; 2971 base_type = static_cast<BaseType>(type->base_type()); 2972 element = static_cast<BaseType>(type->element()); 2973 if (type->index() >= 0) { 2974 if (type->base_type() == reflection::Obj || 2975 (type->base_type() == reflection::Vector && 2976 type->element() == reflection::Obj)) { 2977 if (static_cast<size_t>(type->index()) < parser.structs_.vec.size()) { 2978 struct_def = parser.structs_.vec[type->index()]; 2979 struct_def->refcount++; 2980 } else { 2981 return false; 2982 } 2983 } else { 2984 if (static_cast<size_t>(type->index()) < parser.enums_.vec.size()) { 2985 enum_def = parser.enums_.vec[type->index()]; 2986 } else { 2987 return false; 2988 } 2989 } 2990 } 2991 return true; 2992 } 2993 2994 flatbuffers::Offset< 2995 flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>> 2996 Definition::SerializeAttributes(FlatBufferBuilder *builder, 2997 const Parser &parser) const { 2998 std::vector<flatbuffers::Offset<reflection::KeyValue>> attrs; 2999 for (auto kv = attributes.dict.begin(); kv != attributes.dict.end(); ++kv) { 3000 auto it = parser.known_attributes_.find(kv->first); 3001 FLATBUFFERS_ASSERT(it != parser.known_attributes_.end()); 3002 if (parser.opts.binary_schema_builtins || !it->second) { 3003 auto key = builder->CreateString(kv->first); 3004 auto val = builder->CreateString(kv->second->constant); 3005 attrs.push_back(reflection::CreateKeyValue(*builder, key, val)); 3006 } 3007 } 3008 if (attrs.size()) { 3009 return builder->CreateVectorOfSortedTables(&attrs); 3010 } else { 3011 return 0; 3012 } 3013 } 3014 3015 bool Definition::DeserializeAttributes( 3016 Parser &parser, const Vector<Offset<reflection::KeyValue>> *attrs) { 3017 if (attrs == nullptr) 3018 return true; 3019 for (uoffset_t i = 0; i < attrs->size(); ++i) { 3020 auto kv = attrs->Get(i); 3021 auto value = new Value(); 3022 if (kv->value()) { value->constant = kv->value()->str(); } 3023 if (attributes.Add(kv->key()->str(), value)) { 3024 delete value; 3025 return false; 3026 } 3027 parser.known_attributes_[kv->key()->str()]; 3028 } 3029 return true; 3030 } 3031 3032 /************************************************************************/ 3033 /* DESERIALIZATION */ 3034 /************************************************************************/ 3035 bool Parser::Deserialize(const uint8_t *buf, const size_t size) { 3036 flatbuffers::Verifier verifier(reinterpret_cast<const uint8_t *>(buf), size); 3037 bool size_prefixed = false; 3038 if(!reflection::SchemaBufferHasIdentifier(buf)) { 3039 if (!flatbuffers::BufferHasIdentifier(buf, reflection::SchemaIdentifier(), 3040 true)) 3041 return false; 3042 else 3043 size_prefixed = true; 3044 } 3045 auto verify_fn = size_prefixed ? &reflection::VerifySizePrefixedSchemaBuffer 3046 : &reflection::VerifySchemaBuffer; 3047 if (!verify_fn(verifier)) { 3048 return false; 3049 } 3050 auto schema = size_prefixed ? reflection::GetSizePrefixedSchema(buf) 3051 : reflection::GetSchema(buf); 3052 return Deserialize(schema); 3053 } 3054 3055 bool Parser::Deserialize(const reflection::Schema *schema) { 3056 file_identifier_ = schema->file_ident() ? schema->file_ident()->str() : ""; 3057 file_extension_ = schema->file_ext() ? schema->file_ext()->str() : ""; 3058 std::map<std::string, Namespace *> namespaces_index; 3059 3060 // Create defs without deserializing so references from fields to structs and 3061 // enums can be resolved. 3062 for (auto it = schema->objects()->begin(); it != schema->objects()->end(); 3063 ++it) { 3064 auto struct_def = new StructDef(); 3065 if (structs_.Add(it->name()->str(), struct_def)) { 3066 delete struct_def; 3067 return false; 3068 } 3069 auto type = new Type(BASE_TYPE_STRUCT, struct_def, nullptr); 3070 if (types_.Add(it->name()->str(), type)) { 3071 delete type; 3072 return false; 3073 } 3074 } 3075 for (auto it = schema->enums()->begin(); it != schema->enums()->end(); ++it) { 3076 auto enum_def = new EnumDef(); 3077 if (enums_.Add(it->name()->str(), enum_def)) { 3078 delete enum_def; 3079 return false; 3080 } 3081 auto type = new Type(BASE_TYPE_UNION, nullptr, enum_def); 3082 if (types_.Add(it->name()->str(), type)) { 3083 delete type; 3084 return false; 3085 } 3086 } 3087 3088 // Now fields can refer to structs and enums by index. 3089 for (auto it = schema->objects()->begin(); it != schema->objects()->end(); 3090 ++it) { 3091 std::string qualified_name = it->name()->str(); 3092 auto struct_def = structs_.Lookup(qualified_name); 3093 struct_def->defined_namespace = 3094 GetNamespace(qualified_name, namespaces_, namespaces_index); 3095 if (!struct_def->Deserialize(*this, * it)) { return false; } 3096 if (schema->root_table() == *it) { root_struct_def_ = struct_def; } 3097 } 3098 for (auto it = schema->enums()->begin(); it != schema->enums()->end(); ++it) { 3099 std::string qualified_name = it->name()->str(); 3100 auto enum_def = enums_.Lookup(qualified_name); 3101 enum_def->defined_namespace = 3102 GetNamespace(qualified_name, namespaces_, namespaces_index); 3103 if (!enum_def->Deserialize(*this, *it)) { return false; } 3104 } 3105 3106 if (schema->services()) { 3107 for (auto it = schema->services()->begin(); it != schema->services()->end(); 3108 ++it) { 3109 std::string qualified_name = it->name()->str(); 3110 auto service_def = new ServiceDef(); 3111 service_def->defined_namespace = 3112 GetNamespace(qualified_name, namespaces_, namespaces_index); 3113 if (!service_def->Deserialize(*this, *it) || 3114 services_.Add(qualified_name, service_def)) { 3115 delete service_def; 3116 return false; 3117 } 3118 } 3119 } 3120 3121 return true; 3122 } 3123 3124 std::string Parser::ConformTo(const Parser &base) { 3125 for (auto sit = structs_.vec.begin(); sit != structs_.vec.end(); ++sit) { 3126 auto &struct_def = **sit; 3127 auto qualified_name = 3128 struct_def.defined_namespace->GetFullyQualifiedName(struct_def.name); 3129 auto struct_def_base = base.LookupStruct(qualified_name); 3130 if (!struct_def_base) continue; 3131 for (auto fit = struct_def.fields.vec.begin(); 3132 fit != struct_def.fields.vec.end(); ++fit) { 3133 auto &field = **fit; 3134 auto field_base = struct_def_base->fields.Lookup(field.name); 3135 if (field_base) { 3136 if (field.value.offset != field_base->value.offset) 3137 return "offsets differ for field: " + field.name; 3138 if (field.value.constant != field_base->value.constant) 3139 return "defaults differ for field: " + field.name; 3140 if (!EqualByName(field.value.type, field_base->value.type)) 3141 return "types differ for field: " + field.name; 3142 } else { 3143 // Doesn't have to exist, deleting fields is fine. 3144 // But we should check if there is a field that has the same offset 3145 // but is incompatible (in the case of field renaming). 3146 for (auto fbit = struct_def_base->fields.vec.begin(); 3147 fbit != struct_def_base->fields.vec.end(); ++fbit) { 3148 field_base = *fbit; 3149 if (field.value.offset == field_base->value.offset) { 3150 if (!EqualByName(field.value.type, field_base->value.type)) 3151 return "field renamed to different type: " + field.name; 3152 break; 3153 } 3154 } 3155 } 3156 } 3157 } 3158 for (auto eit = enums_.vec.begin(); eit != enums_.vec.end(); ++eit) { 3159 auto &enum_def = **eit; 3160 auto qualified_name = 3161 enum_def.defined_namespace->GetFullyQualifiedName(enum_def.name); 3162 auto enum_def_base = base.enums_.Lookup(qualified_name); 3163 if (!enum_def_base) continue; 3164 for (auto evit = enum_def.vals.vec.begin(); evit != enum_def.vals.vec.end(); 3165 ++evit) { 3166 auto &enum_val = **evit; 3167 auto enum_val_base = enum_def_base->vals.Lookup(enum_val.name); 3168 if (enum_val_base) { 3169 if (enum_val.value != enum_val_base->value) 3170 return "values differ for enum: " + enum_val.name; 3171 } 3172 } 3173 } 3174 return ""; 3175 } 3176 3177 } // namespace flatbuffers 3178