idl_parser.cpp revision 03e2899985849dbffa3178ae76c00288f7aca79b
126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen/* 226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen * Copyright 2014 Google Inc. All rights reserved. 326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen * 426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen * Licensed under the Apache License, Version 2.0 (the "License"); 526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen * you may not use this file except in compliance with the License. 626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen * You may obtain a copy of the License at 726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen * 826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen * http://www.apache.org/licenses/LICENSE-2.0 926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen * 1026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen * Unless required by applicable law or agreed to in writing, software 1126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen * distributed under the License is distributed on an "AS IS" BASIS, 1226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen * See the License for the specific language governing permissions and 1426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen * limitations under the License. 1526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen */ 1626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 1726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen#include <algorithm> 18df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez#include <list> 1989a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich#include <iostream> 2026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 21d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen#ifdef _WIN32 22d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen#if !defined(_USE_MATH_DEFINES) 23d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen#define _USE_MATH_DEFINES // For M_PI. 24d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen#endif // !defined(_USE_MATH_DEFINES) 25d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen#endif // _WIN32 26d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen 27d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen#include <math.h> 28d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen 2926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen#include "flatbuffers/idl.h" 3026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen#include "flatbuffers/util.h" 3126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 3226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssennamespace flatbuffers { 3326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 3426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenconst char *const kTypeNames[] = { 3503e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen #define FLATBUFFERS_TD(ENUM, IDLTYPE, \ 36f2b3705c2c62c40afdef96f73f0aeaf32b4c8e0eMikkelFJ CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \ 3748dfc69ee613a176f13b04c2310adb7a08fe6737rw IDLTYPE, 3826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) 3926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen #undef FLATBUFFERS_TD 4026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen nullptr 4126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen}; 4226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 4326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenconst char kTypeSizes[] = { 4403e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen #define FLATBUFFERS_TD(ENUM, IDLTYPE, \ 45f2b3705c2c62c40afdef96f73f0aeaf32b4c8e0eMikkelFJ CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \ 46557c88c0396220e79e9a43c07f8393a5c68b739dWouter van Oortmerssen sizeof(CTYPE), 4726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) 4826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen #undef FLATBUFFERS_TD 4926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen}; 5026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 5181312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen// The enums in the reflection schema should match the ones we use internally. 5281312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen// Compare the last element to check if these go out of sync. 5381312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssenstatic_assert(BASE_TYPE_UNION == 54622b8d05cf69cc26babc6a043d1f7a4153755652Wouter van Oortmerssen static_cast<BaseType>(reflection::Union), 5581312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen "enums don't match"); 5681312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen 57451272b61840a3c2b12edeb23b18c9bd0b2aa508Wouter van Oortmerssen// Any parsing calls have to be wrapped in this macro, which automates 58451272b61840a3c2b12edeb23b18c9bd0b2aa508Wouter van Oortmerssen// handling of recursive error checking a bit. It will check the received 59451272b61840a3c2b12edeb23b18c9bd0b2aa508Wouter van Oortmerssen// CheckedError object, and return straight away on error. 6040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen#define ECHECK(call) { auto ce = (call); if (ce.Check()) return ce; } 61451272b61840a3c2b12edeb23b18c9bd0b2aa508Wouter van Oortmerssen 62451272b61840a3c2b12edeb23b18c9bd0b2aa508Wouter van Oortmerssen// These two functions are called hundreds of times below, so define a short 63451272b61840a3c2b12edeb23b18c9bd0b2aa508Wouter van Oortmerssen// form: 6440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen#define NEXT() ECHECK(Next()) 6540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen#define EXPECT(tok) ECHECK(Expect(tok)) 6640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen 67f6416d847186802e03d2fa3c05963ec377c146fcBen Hamiltonstatic bool ValidateUTF8(const std::string &str) { 68f6416d847186802e03d2fa3c05963ec377c146fcBen Hamilton const char *s = &str[0]; 69f6416d847186802e03d2fa3c05963ec377c146fcBen Hamilton const char * const sEnd = s + str.length(); 70f6416d847186802e03d2fa3c05963ec377c146fcBen Hamilton while (s < sEnd) { 71f6416d847186802e03d2fa3c05963ec377c146fcBen Hamilton if (FromUTF8(&s) < 0) { 72f6416d847186802e03d2fa3c05963ec377c146fcBen Hamilton return false; 73f6416d847186802e03d2fa3c05963ec377c146fcBen Hamilton } 74f6416d847186802e03d2fa3c05963ec377c146fcBen Hamilton } 75f6416d847186802e03d2fa3c05963ec377c146fcBen Hamilton return true; 76f6416d847186802e03d2fa3c05963ec377c146fcBen Hamilton} 77f6416d847186802e03d2fa3c05963ec377c146fcBen Hamilton 7840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::Error(const std::string &msg) { 7940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen error_ = file_being_parsed_.length() ? AbsolutePath(file_being_parsed_) : ""; 8040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen #ifdef _WIN32 8140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen error_ += "(" + NumToString(line_) + ")"; // MSVC alike 8240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen #else 8340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (file_being_parsed_.length()) error_ += ":"; 8440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen error_ += NumToString(line_) + ":0"; // gcc alike 8540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen #endif 8640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen error_ += ": error: " + msg; 8740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return CheckedError(true); 8826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 8926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 9040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmersseninline CheckedError NoError() { return CheckedError(false); } 9140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen 92a07f0d428d1175ae52b2f91357f535927c9d6287Jason Stubbsinline std::string OutOfRangeErrorMsg(int64_t val, const std::string &op, 93a07f0d428d1175ae52b2f91357f535927c9d6287Jason Stubbs int64_t limit) { 94a07f0d428d1175ae52b2f91357f535927c9d6287Jason Stubbs const std::string cause = NumToString(val) + op + NumToString(limit); 95a07f0d428d1175ae52b2f91357f535927c9d6287Jason Stubbs return "constant does not fit (" + cause + ")"; 96a07f0d428d1175ae52b2f91357f535927c9d6287Jason Stubbs} 97a07f0d428d1175ae52b2f91357f535927c9d6287Jason Stubbs 9826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen// Ensure that integer values we parse fit inside the declared integer type. 99a07f0d428d1175ae52b2f91357f535927c9d6287Jason StubbsCheckedError Parser::CheckInRange(int64_t val, int64_t min, int64_t max) { 100a07f0d428d1175ae52b2f91357f535927c9d6287Jason Stubbs if (val < min) 101a07f0d428d1175ae52b2f91357f535927c9d6287Jason Stubbs return Error(OutOfRangeErrorMsg(val, " < ", min)); 102a07f0d428d1175ae52b2f91357f535927c9d6287Jason Stubbs else if (val > max) 103a07f0d428d1175ae52b2f91357f535927c9d6287Jason Stubbs return Error(OutOfRangeErrorMsg(val, " > ", max)); 104a07f0d428d1175ae52b2f91357f535927c9d6287Jason Stubbs else 105a07f0d428d1175ae52b2f91357f535927c9d6287Jason Stubbs return NoError(); 10626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 10726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 10826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen// atot: templated version of atoi/atof: convert a string to an instance of T. 10940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssentemplate<typename T> inline CheckedError atot(const char *s, Parser &parser, 11040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen T *val) { 11140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen int64_t i = StringToInt(s); 112a8923222033763f1a74f836c656af19d9f620378Stewart Miles const int64_t min = flatbuffers::numeric_limits<T>::min(); 113a8923222033763f1a74f836c656af19d9f620378Stewart Miles const int64_t max = flatbuffers::numeric_limits<T>::max(); 114a07f0d428d1175ae52b2f91357f535927c9d6287Jason Stubbs ECHECK(parser.CheckInRange(i, min, max)); 11540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen *val = (T)i; 11640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 11726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 11829574282a283ddc7904d096d27b783b794da7e91Wouter van Oortmerssentemplate<> inline CheckedError atot<uint64_t>(const char *s, Parser &parser, 11929574282a283ddc7904d096d27b783b794da7e91Wouter van Oortmerssen uint64_t *val) { 12029574282a283ddc7904d096d27b783b794da7e91Wouter van Oortmerssen (void)parser; 12129574282a283ddc7904d096d27b783b794da7e91Wouter van Oortmerssen *val = StringToUInt(s); 12229574282a283ddc7904d096d27b783b794da7e91Wouter van Oortmerssen return NoError(); 12329574282a283ddc7904d096d27b783b794da7e91Wouter van Oortmerssen} 12440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssentemplate<> inline CheckedError atot<bool>(const char *s, Parser &parser, 12540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen bool *val) { 12640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen (void)parser; 12740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen *val = 0 != atoi(s); 12840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 12926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 13040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssentemplate<> inline CheckedError atot<float>(const char *s, Parser &parser, 13140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen float *val) { 13240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen (void)parser; 13340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen *val = static_cast<float>(strtod(s, nullptr)); 13440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 13526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 13640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssentemplate<> inline CheckedError atot<double>(const char *s, Parser &parser, 13740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen double *val) { 13840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen (void)parser; 13940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen *val = strtod(s, nullptr); 14040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 14126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 14226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 14340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssentemplate<> inline CheckedError atot<Offset<void>>(const char *s, Parser &parser, 14440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen Offset<void> *val) { 14540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen (void)parser; 14640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen *val = Offset<void>(atoi(s)); 14740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 14826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 14926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 15094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssenstd::string Namespace::GetFullyQualifiedName(const std::string &name, 15194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen size_t max_components) const { 15294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Early exit if we don't have a defined namespace. 15394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (components.size() == 0 || !max_components) { 15494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen return name; 15594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 15694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen std::stringstream stream; 15794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen for (size_t i = 0; i < std::min(components.size(), max_components); 15894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen i++) { 15994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (i) { 16094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen stream << "."; 16194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 16294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen stream << components[i]; 16394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 1648c1a723ba55d1574590eba801d64afab9c49e017Wouter van Oortmerssen if (name.length()) stream << "." << name; 16594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen return stream.str(); 16694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen} 16794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen 16826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen// Declare tokens we'll use. Single character tokens are represented by their 16926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen// ascii character code (e.g. '{'), others above 256. 17026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen#define FLATBUFFERS_GEN_TOKENS(TD) \ 17126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen TD(Eof, 256, "end of file") \ 17226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen TD(StringConstant, 257, "string constant") \ 17326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen TD(IntegerConstant, 258, "integer constant") \ 17426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen TD(FloatConstant, 259, "float constant") \ 17503e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen TD(Identifier, 260, "identifier") 1768f80fecc445cb733615ad0186358d4e3789ab377Wouter van Oortmerssen#ifdef __GNUC__ 1778f80fecc445cb733615ad0186358d4e3789ab377Wouter van Oortmerssen__extension__ // Stop GCC complaining about trailing comma with -Wpendantic. 1788f80fecc445cb733615ad0186358d4e3789ab377Wouter van Oortmerssen#endif 17926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenenum { 18075349ae8c39d01e7e2b5779a18ace750c08e2fd9Wouter van Oortmerssen #define FLATBUFFERS_TOKEN(NAME, VALUE, STRING) kToken ## NAME = VALUE, 18126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen FLATBUFFERS_GEN_TOKENS(FLATBUFFERS_TOKEN) 18226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen #undef FLATBUFFERS_TOKEN 18326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen}; 18426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 18526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenstatic std::string TokenToString(int t) { 18626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen static const char *tokens[] = { 18726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen #define FLATBUFFERS_TOKEN(NAME, VALUE, STRING) STRING, 18826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen FLATBUFFERS_GEN_TOKENS(FLATBUFFERS_TOKEN) 18926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen #undef FLATBUFFERS_TOKEN 19003e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen #define FLATBUFFERS_TD(ENUM, IDLTYPE, \ 191f2b3705c2c62c40afdef96f73f0aeaf32b4c8e0eMikkelFJ CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \ 19248dfc69ee613a176f13b04c2310adb7a08fe6737rw IDLTYPE, 19326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) 19426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen #undef FLATBUFFERS_TD 19526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen }; 19626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (t < 256) { // A single ascii char token. 19726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen std::string s; 1988e40902d5284ac479baea5a8ba5eeb31c8edb1a9Wouter van Oortmerssen s.append(1, static_cast<char>(t)); 19926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen return s; 20026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else { // Other tokens. 20126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen return tokens[t - 256]; 20226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 20326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 20426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 20594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssenstd::string Parser::TokenToStringId(int t) { 20603e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen return t == kTokenIdentifier ? attribute_ : TokenToString(t); 20794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen} 20894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen 209ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen// Parses exactly nibbles worth of hex digits into a number, or error. 21029574282a283ddc7904d096d27b783b794da7e91Wouter van OortmerssenCheckedError Parser::ParseHexNum(int nibbles, uint64_t *val) { 211ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen for (int i = 0; i < nibbles; i++) 21230013b4ff80dd7d4fde56e1b2b8b988feed6437fChris Pickett if (!isxdigit(static_cast<const unsigned char>(cursor_[i]))) 21340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("escape code must be followed by " + NumToString(nibbles) + 21440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen " hex digits"); 2157cf74cb8644262f8ca02d69705bbc394d66514ceHiroshi Matsunaga std::string target(cursor_, cursor_ + nibbles); 216b6ba322a0411925757196a1ca6f3a1a87f46831eSahil Jain *val = StringToUInt(target.c_str(), nullptr, 16); 217ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen cursor_ += nibbles; 21840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 219ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen} 220ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen 221cbe8747b59d143ad2bfe73ecc838b711f8102886Oli Wilkinson <OliCheckedError Parser::SkipByteOrderMark() { 22203e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen if (static_cast<unsigned char>(*cursor_) != 0xef) 22303e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen return NoError(); 224cbe8747b59d143ad2bfe73ecc838b711f8102886Oli Wilkinson <Oli cursor_++; 22503e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen if (static_cast<unsigned char>(*cursor_) != 0xbb) 22603e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen return Error("invalid utf-8 byte order mark"); 227f6330ab8f137871f786fc72a7700b54da21f0603Wouter van Oortmerssen cursor_++; 22803e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen if (static_cast<unsigned char>(*cursor_) != 0xbf) 22903e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen return Error("invalid utf-8 byte order mark"); 230f6330ab8f137871f786fc72a7700b54da21f0603Wouter van Oortmerssen cursor_++; 231cbe8747b59d143ad2bfe73ecc838b711f8102886Oli Wilkinson <Oli return NoError(); 232cbe8747b59d143ad2bfe73ecc838b711f8102886Oli Wilkinson <Oli} 233cbe8747b59d143ad2bfe73ecc838b711f8102886Oli Wilkinson <Oli 234fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssenbool IsIdentifierStart(char c) { 235fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen return isalpha(static_cast<unsigned char>(c)) || c == '_'; 236fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen} 237fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen 23840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::Next() { 23926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen doc_comment_.clear(); 24026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen bool seen_newline = false; 24194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen attribute_.clear(); 24226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen for (;;) { 24326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen char c = *cursor_++; 24426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen token_ = c; 24526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen switch (c) { 24640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen case '\0': cursor_--; token_ = kTokenEof; return NoError(); 24726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case ' ': case '\r': case '\t': break; 24826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case '\n': line_++; seen_newline = true; break; 24940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen case '{': case '}': case '(': case ')': case '[': case ']': 25040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen case ',': case ':': case ';': case '=': return NoError(); 25126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case '.': 25230013b4ff80dd7d4fde56e1b2b8b988feed6437fChris Pickett if(!isdigit(static_cast<const unsigned char>(*cursor_))) return NoError(); 25340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("floating point constant can\'t start with \".\""); 25426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case '\"': 2556704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield case '\'': { 2566704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield int unicode_high_surrogate = -1; 2576704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield 25894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen while (*cursor_ != c) { 25926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (*cursor_ < ' ' && *cursor_ >= 0) 26040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("illegal character in string constant"); 26126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (*cursor_ == '\\') { 26226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen cursor_++; 2636704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield if (unicode_high_surrogate != -1 && 2646704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield *cursor_ != 'u') { 2656704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield return Error( 2666704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield "illegal Unicode sequence (unpaired high surrogate)"); 2676704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield } 26826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen switch (*cursor_) { 26926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case 'n': attribute_ += '\n'; cursor_++; break; 27026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case 't': attribute_ += '\t'; cursor_++; break; 27126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case 'r': attribute_ += '\r'; cursor_++; break; 272ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen case 'b': attribute_ += '\b'; cursor_++; break; 273ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen case 'f': attribute_ += '\f'; cursor_++; break; 27426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case '\"': attribute_ += '\"'; cursor_++; break; 27594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen case '\'': attribute_ += '\''; cursor_++; break; 27626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case '\\': attribute_ += '\\'; cursor_++; break; 277ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen case '/': attribute_ += '/'; cursor_++; break; 278ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen case 'x': { // Not in the JSON standard 279ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen cursor_++; 28029574282a283ddc7904d096d27b783b794da7e91Wouter van Oortmerssen uint64_t val; 28140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseHexNum(2, &val)); 28240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen attribute_ += static_cast<char>(val); 283ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen break; 284ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen } 285ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen case 'u': { 286ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen cursor_++; 28729574282a283ddc7904d096d27b783b794da7e91Wouter van Oortmerssen uint64_t val; 28840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseHexNum(4, &val)); 2896704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield if (val >= 0xD800 && val <= 0xDBFF) { 2906704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield if (unicode_high_surrogate != -1) { 2916704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield return Error( 2926704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield "illegal Unicode sequence (multiple high surrogates)"); 2936704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield } else { 294e92ae5199d52fd59540a800bec7eef46cd778257Wouter van Oortmerssen unicode_high_surrogate = static_cast<int>(val); 2956704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield } 2966704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield } else if (val >= 0xDC00 && val <= 0xDFFF) { 2976704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield if (unicode_high_surrogate == -1) { 2986704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield return Error( 2996704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield "illegal Unicode sequence (unpaired low surrogate)"); 3006704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield } else { 3016704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield int code_point = 0x10000 + 3026704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield ((unicode_high_surrogate & 0x03FF) << 10) + 3036704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield (val & 0x03FF); 3046704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield ToUTF8(code_point, &attribute_); 3056704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield unicode_high_surrogate = -1; 3066704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield } 3076704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield } else { 3086704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield if (unicode_high_surrogate != -1) { 3096704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield return Error( 3106704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield "illegal Unicode sequence (unpaired high surrogate)"); 3116704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield } 3126704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield ToUTF8(static_cast<int>(val), &attribute_); 3136704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield } 314ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen break; 315ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen } 31640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen default: return Error("unknown escape code in string constant"); 31726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 31826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else { // printable chars + UTF-8 bytes 3196704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield if (unicode_high_surrogate != -1) { 3206704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield return Error( 3216704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield "illegal Unicode sequence (unpaired high surrogate)"); 3226704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield } 32326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen attribute_ += *cursor_++; 32426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 32526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 3266704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield if (unicode_high_surrogate != -1) { 3276704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield return Error( 3286704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield "illegal Unicode sequence (unpaired high surrogate)"); 3296704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield } 33026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen cursor_++; 331f6416d847186802e03d2fa3c05963ec377c146fcBen Hamilton if (!opts.allow_non_utf8 && !ValidateUTF8(attribute_)) { 332f6416d847186802e03d2fa3c05963ec377c146fcBen Hamilton return Error("illegal UTF-8 sequence"); 333f6416d847186802e03d2fa3c05963ec377c146fcBen Hamilton } 33426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen token_ = kTokenStringConstant; 33540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 3366704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield } 33726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case '/': 33826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (*cursor_ == '/') { 33926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen const char *start = ++cursor_; 340a8d6962ac2fbf5075ee5f58877d488eb74ed32dfMormegil while (*cursor_ && *cursor_ != '\n' && *cursor_ != '\r') cursor_++; 34126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (*start == '/') { // documentation comment 34207d5965c812fa5e82dc4d3eb32b37540b7c91598Zbigniew Mandziejewicz if (cursor_ != source_ && !seen_newline) 34340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error( 34440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen "a documentation comment should be on a line on its own"); 345730c0cadde2302efa1487d672a1e2f53680ce2eaGabriel Martinez doc_comment_.push_back(std::string(start + 1, cursor_)); 34626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 34726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen break; 34894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else if (*cursor_ == '*') { 34994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen cursor_++; 35094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // TODO: make nested. 35194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen while (*cursor_ != '*' || cursor_[1] != '/') { 352ab51b030939e02e55cac6f9e779d8696013819a9Wouter van Oortmerssen if (*cursor_ == '\n') line_++; 35340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!*cursor_) return Error("end of file in comment"); 35494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen cursor_++; 35594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 35694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen cursor_ += 2; 35794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen break; 35826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 35926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // fall thru 36026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen default: 361fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen if (IsIdentifierStart(c)) { 36226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // Collect all chars of an identifier: 36326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen const char *start = cursor_ - 1; 36426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen while (isalnum(static_cast<unsigned char>(*cursor_)) || 36526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen *cursor_ == '_') 36626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen cursor_++; 36726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen attribute_.append(start, cursor_); 36826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen token_ = kTokenIdentifier; 36940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 37026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else if (isdigit(static_cast<unsigned char>(c)) || c == '-') { 37126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen const char *start = cursor_ - 1; 37229574282a283ddc7904d096d27b783b794da7e91Wouter van Oortmerssen if (c == '-' && *cursor_ == '0' && 37329574282a283ddc7904d096d27b783b794da7e91Wouter van Oortmerssen (cursor_[1] == 'x' || cursor_[1] == 'X')) { 374f6f88e567ef7f2d282991c761ad2c8d106f6b183Raman ++start; 375f6f88e567ef7f2d282991c761ad2c8d106f6b183Raman ++cursor_; 376f6f88e567ef7f2d282991c761ad2c8d106f6b183Raman attribute_.append(&c, &c + 1); 377f6f88e567ef7f2d282991c761ad2c8d106f6b183Raman c = '0'; 378f6f88e567ef7f2d282991c761ad2c8d106f6b183Raman } 37994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (c == '0' && (*cursor_ == 'x' || *cursor_ == 'X')) { 38094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen cursor_++; 38194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen while (isxdigit(static_cast<unsigned char>(*cursor_))) cursor_++; 38294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen attribute_.append(start + 2, cursor_); 38329574282a283ddc7904d096d27b783b794da7e91Wouter van Oortmerssen attribute_ = NumToString(static_cast<int64_t>( 38429574282a283ddc7904d096d27b783b794da7e91Wouter van Oortmerssen StringToUInt(attribute_.c_str(), nullptr, 16))); 38594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen token_ = kTokenIntegerConstant; 38640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 38794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 38826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen while (isdigit(static_cast<unsigned char>(*cursor_))) cursor_++; 38994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (*cursor_ == '.' || *cursor_ == 'e' || *cursor_ == 'E') { 39094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (*cursor_ == '.') { 39194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen cursor_++; 39294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen while (isdigit(static_cast<unsigned char>(*cursor_))) cursor_++; 39394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 39493df5697a04e406929d7a3fa1f17904d2859e36dWouter van Oortmerssen // See if this float has a scientific notation suffix. Both JSON 39593df5697a04e406929d7a3fa1f17904d2859e36dWouter van Oortmerssen // and C++ (through strtod() we use) have the same format: 39693df5697a04e406929d7a3fa1f17904d2859e36dWouter van Oortmerssen if (*cursor_ == 'e' || *cursor_ == 'E') { 39793df5697a04e406929d7a3fa1f17904d2859e36dWouter van Oortmerssen cursor_++; 39893df5697a04e406929d7a3fa1f17904d2859e36dWouter van Oortmerssen if (*cursor_ == '+' || *cursor_ == '-') cursor_++; 39993df5697a04e406929d7a3fa1f17904d2859e36dWouter van Oortmerssen while (isdigit(static_cast<unsigned char>(*cursor_))) cursor_++; 40093df5697a04e406929d7a3fa1f17904d2859e36dWouter van Oortmerssen } 40126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen token_ = kTokenFloatConstant; 40226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else { 40326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen token_ = kTokenIntegerConstant; 40426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 40526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen attribute_.append(start, cursor_); 40640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 40726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 40826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen std::string ch; 40926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen ch = c; 41026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (c < ' ' || c > '~') ch = "code: " + NumToString(c); 41140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("illegal character: " + ch); 41226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 41326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 41426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 41526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 41640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen// Check if a given token is next. 41740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssenbool Parser::Is(int t) { 41840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return t == token_; 41926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 42026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 42103e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssenbool Parser::IsIdent(const char *id) { 42203e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen return token_ == kTokenIdentifier && attribute_ == id; 42303e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen} 42403e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen 42526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen// Expect a given token to be next, consume it, or error if not present. 42640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::Expect(int t) { 42726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (t != token_) { 42840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("expecting: " + TokenToString(t) + " instead got: " + 42940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen TokenToStringId(token_)); 43026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 43140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 43240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 43326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 43426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 43540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseNamespacing(std::string *id, std::string *last) { 43640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen while (Is('.')) { 43740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 43839833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van Oortmerssen *id += "."; 43939833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van Oortmerssen *id += attribute_; 44039833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van Oortmerssen if (last) *last = attribute_; 44140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 44239833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van Oortmerssen } 44340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 44439833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van Oortmerssen} 44539833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van Oortmerssen 44639833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van OortmerssenEnumDef *Parser::LookupEnum(const std::string &id) { 44794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Search thru parent namespaces. 448321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen for (int components = static_cast<int>(current_namespace_->components.size()); 44994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen components >= 0; components--) { 45040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen auto ed = enums_.Lookup( 451321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen current_namespace_->GetFullyQualifiedName(id, components)); 45294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (ed) return ed; 45394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 45494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen return nullptr; 45539833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van Oortmerssen} 45639833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van Oortmerssen 45740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseTypeIdent(Type &type) { 45839833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van Oortmerssen std::string id = attribute_; 45940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 46040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseNamespacing(&id, nullptr)); 46139833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van Oortmerssen auto enum_def = LookupEnum(id); 462d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen if (enum_def) { 463d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen type = enum_def->underlying_type; 464d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen if (enum_def->is_union) type.base_type = BASE_TYPE_UNION; 465d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen } else { 466d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen type.base_type = BASE_TYPE_STRUCT; 46739833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van Oortmerssen type.struct_def = LookupCreateStruct(id); 468d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen } 46940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 470d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen} 471d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen 47226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen// Parse any IDL type. 47340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseType(Type &type) { 47403e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen if (token_ == kTokenIdentifier) { 47503e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen if (IsIdent("bool")) { 47603e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen type.base_type = BASE_TYPE_BOOL; 47703e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen NEXT(); 47803e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if (IsIdent("byte") || IsIdent("int8")) { 47903e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen type.base_type = BASE_TYPE_CHAR; 48003e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen NEXT(); 48103e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if (IsIdent("ubyte") || IsIdent("uint8")) { 48203e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen type.base_type = BASE_TYPE_UCHAR; 48303e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen NEXT(); 48403e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if (IsIdent("short") || IsIdent("int16")) { 48503e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen type.base_type = BASE_TYPE_SHORT; 48603e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen NEXT(); 48703e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if (IsIdent("ushort") || IsIdent("uint16")) { 48803e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen type.base_type = BASE_TYPE_USHORT; 48903e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen NEXT(); 49003e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if (IsIdent("int") || IsIdent("int32")) { 49103e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen type.base_type = BASE_TYPE_INT; 49203e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen NEXT(); 49303e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if (IsIdent("uint") || IsIdent("uint32")) { 49403e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen type.base_type = BASE_TYPE_UINT; 49503e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen NEXT(); 49603e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if (IsIdent("long") || IsIdent("int64")) { 49703e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen type.base_type = BASE_TYPE_LONG; 49803e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen NEXT(); 49903e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if (IsIdent("ulong") || IsIdent("uint64")) { 50003e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen type.base_type = BASE_TYPE_ULONG; 50103e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen NEXT(); 50203e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if (IsIdent("float") || IsIdent("float32")) { 50303e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen type.base_type = BASE_TYPE_FLOAT; 50403e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen NEXT(); 50503e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if (IsIdent("double") || IsIdent("float64")) { 50603e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen type.base_type = BASE_TYPE_DOUBLE; 50703e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen NEXT(); 50803e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if (IsIdent("string")) { 50903e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen type.base_type = BASE_TYPE_STRING; 51040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 51126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else { 51203e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen ECHECK(ParseTypeIdent(type)); 51303e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } 51403e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if (token_ == '[') { 51503e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen NEXT(); 51603e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen Type subtype; 51703e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen ECHECK(ParseType(subtype)); 51803e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen if (subtype.base_type == BASE_TYPE_VECTOR) { 51903e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen // We could support this, but it will complicate things, and it's 52003e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen // easier to work around with a struct around the inner vector. 52103e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen return Error( 52203e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen "nested vector types not supported (wrap in table first)."); 52326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 52403e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen type = Type(BASE_TYPE_VECTOR, subtype.struct_def, subtype.enum_def); 52503e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen type.element = subtype.base_type; 52603e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen EXPECT(']'); 52703e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else { 52803e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen return Error("illegal type syntax"); 52926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 53040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 53126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 53226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 53340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::AddField(StructDef &struct_def, const std::string &name, 53440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen const Type &type, FieldDef **dest) { 53526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto &field = *new FieldDef(); 53626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen field.value.offset = 53726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen FieldIndexToOffset(static_cast<voffset_t>(struct_def.fields.vec.size())); 53826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen field.name = name; 539df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez field.file = struct_def.file; 54026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen field.value.type = type; 54126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (struct_def.fixed) { // statically compute the field offset 54226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto size = InlineSize(type); 54326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto alignment = InlineAlignment(type); 54426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // structs_ need to have a predictable format, so we need to align to 54526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // the largest scalar 54626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen struct_def.minalign = std::max(struct_def.minalign, alignment); 54726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen struct_def.PadLastField(alignment); 5481256307a388f05917b112253ef79e9b79ff76e1dWouter van Oortmerssen field.value.offset = static_cast<voffset_t>(struct_def.bytesize); 54926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen struct_def.bytesize += size; 55026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 55126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (struct_def.fields.Add(name, &field)) 55240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("field already exists: " + name); 55340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen *dest = &field; 55440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 55526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 55626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 55740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseField(StructDef &struct_def) { 55826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen std::string name = attribute_; 559e9f1f4d9b7fb41f9f66a24ef03ccbea1780d2674Wouter van Oortmerssen 5608a58aafda12bd1b9f7f228dc5f0583cf4f4afe87Wouter van Oortmerssen if (structs_.Lookup(name)) 561e9f1f4d9b7fb41f9f66a24ef03ccbea1780d2674Wouter van Oortmerssen return Error("field name can not be the same as table/struct name"); 562e9f1f4d9b7fb41f9f66a24ef03ccbea1780d2674Wouter van Oortmerssen 563730c0cadde2302efa1487d672a1e2f53680ce2eaGabriel Martinez std::vector<std::string> dc = doc_comment_; 56440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 56540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(':'); 56626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Type type; 56740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseType(type)); 56826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 56926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (struct_def.fixed && !IsScalar(type.base_type) && !IsStruct(type)) 57040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("structs_ may contain only scalar or struct fields"); 57126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 5729140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen FieldDef *typefield = nullptr; 57326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (type.base_type == BASE_TYPE_UNION) { 57426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // For union fields, add a second auto-generated field to hold the type, 5759e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen // with a special suffix. 5769e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen ECHECK(AddField(struct_def, name + UnionTypeFieldSuffix(), 5779e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen type.enum_def->underlying_type, &typefield)); 57868bbe983e9819bcbcd214cf84d73a440863ed6caBei Li } else if (type.base_type == BASE_TYPE_VECTOR && 57968bbe983e9819bcbcd214cf84d73a440863ed6caBei Li type.element == BASE_TYPE_UNION) { 58046bb05d95226c72cc85242eee386465860786333Kamil Rojewski // Only cpp, js and ts supports the union vector feature so far. 58146bb05d95226c72cc85242eee386465860786333Kamil Rojewski if (!SupportsVectorOfUnions()) { 58268bbe983e9819bcbcd214cf84d73a440863ed6caBei Li return Error("Vectors of unions are not yet supported in all " 58368bbe983e9819bcbcd214cf84d73a440863ed6caBei Li "the specified programming languages."); 58468bbe983e9819bcbcd214cf84d73a440863ed6caBei Li } 58568bbe983e9819bcbcd214cf84d73a440863ed6caBei Li // For vector of union fields, add a second auto-generated vector field to 58668bbe983e9819bcbcd214cf84d73a440863ed6caBei Li // hold the types, with a special suffix. 58768bbe983e9819bcbcd214cf84d73a440863ed6caBei Li Type union_vector(BASE_TYPE_VECTOR, nullptr, type.enum_def); 58868bbe983e9819bcbcd214cf84d73a440863ed6caBei Li union_vector.element = BASE_TYPE_UTYPE; 58968bbe983e9819bcbcd214cf84d73a440863ed6caBei Li ECHECK(AddField(struct_def, name + UnionTypeFieldSuffix(), 59068bbe983e9819bcbcd214cf84d73a440863ed6caBei Li union_vector, &typefield)); 59126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 59226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 59340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen FieldDef *field; 59440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(AddField(struct_def, name, type, &field)); 59526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 59626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (token_ == '=') { 59740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 59815dc1a86cd9e1fd22a46fde1a3632418eb8d9466Wouter van Oortmerssen if (!IsScalar(type.base_type)) 59940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("default values currently only supported for scalars"); 60040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseSingleValue(field->value)); 601fd542c71e35774f640073cb6fb3fa939d2f19f87Wouter van Oortmerssen } 602fd542c71e35774f640073cb6fb3fa939d2f19f87Wouter van Oortmerssen if (IsFloat(field->value.type.base_type)) { 603fd542c71e35774f640073cb6fb3fa939d2f19f87Wouter van Oortmerssen if (!strpbrk(field->value.constant.c_str(), ".eE")) 604fd542c71e35774f640073cb6fb3fa939d2f19f87Wouter van Oortmerssen field->value.constant += ".0"; 60526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 60626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 6077b8053570e4407cedfde8d32f6a3c59e5585ef7bWouter van Oortmerssen if (type.enum_def && 6087b8053570e4407cedfde8d32f6a3c59e5585ef7bWouter van Oortmerssen IsScalar(type.base_type) && 6097b8053570e4407cedfde8d32f6a3c59e5585ef7bWouter van Oortmerssen !struct_def.fixed && 6107b8053570e4407cedfde8d32f6a3c59e5585ef7bWouter van Oortmerssen !type.enum_def->attributes.Lookup("bit_flags") && 611d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen !type.enum_def->ReverseLookup(static_cast<int>( 61240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen StringToInt(field->value.constant.c_str())))) 61340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("enum " + type.enum_def->name + 6147b8053570e4407cedfde8d32f6a3c59e5585ef7bWouter van Oortmerssen " does not have a declaration for this field\'s default of " + 61540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen field->value.constant); 6167b8053570e4407cedfde8d32f6a3c59e5585ef7bWouter van Oortmerssen 61740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen field->doc_comment = dc; 618e6b79f00022aee3108427977c9823ff57154e1c6Wouter van Oortmerssen ECHECK(ParseMetaData(&field->attributes)); 61940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen field->deprecated = field->attributes.Lookup("deprecated") != nullptr; 62040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen auto hash_name = field->attributes.Lookup("hash"); 621d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames if (hash_name) { 622d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames switch (type.base_type) { 623d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames case BASE_TYPE_INT: 624d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames case BASE_TYPE_UINT: { 625d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames if (FindHashFunction32(hash_name->constant.c_str()) == nullptr) 62640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("Unknown hashing algorithm for 32 bit types: " + 627d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames hash_name->constant); 628d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames break; 629d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames } 630d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames case BASE_TYPE_LONG: 631d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames case BASE_TYPE_ULONG: { 632d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames if (FindHashFunction64(hash_name->constant.c_str()) == nullptr) 63340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("Unknown hashing algorithm for 64 bit types: " + 634d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames hash_name->constant); 635d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames break; 636d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames } 637d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames default: 63840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error( 63940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen "only int, uint, long and ulong data types support hashing."); 640d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames } 641d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames } 642dc2fa215b854b31aa9a7f8c959ce08297ec79e23Wouter van Oortmerssen auto cpp_type = field->attributes.Lookup("cpp_type"); 643dc2fa215b854b31aa9a7f8c959ce08297ec79e23Wouter van Oortmerssen if (cpp_type) { 644dc2fa215b854b31aa9a7f8c959ce08297ec79e23Wouter van Oortmerssen if (!hash_name) 645dc2fa215b854b31aa9a7f8c959ce08297ec79e23Wouter van Oortmerssen return Error("cpp_type can only be used with a hashed field"); 646dc2fa215b854b31aa9a7f8c959ce08297ec79e23Wouter van Oortmerssen } 64740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (field->deprecated && struct_def.fixed) 64840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("can't deprecate fields in a struct"); 64940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen field->required = field->attributes.Lookup("required") != nullptr; 65040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (field->required && (struct_def.fixed || 65140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen IsScalar(field->value.type.base_type))) 65240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("only non-scalar fields in tables may be 'required'"); 65340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen field->key = field->attributes.Lookup("key") != nullptr; 65440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (field->key) { 6553550899987f9590357dec34d302380874bb2311cWouter van Oortmerssen if (struct_def.has_key) 65640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("only one field may be set as 'key'"); 6573550899987f9590357dec34d302380874bb2311cWouter van Oortmerssen struct_def.has_key = true; 65840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!IsScalar(field->value.type.base_type)) { 65940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen field->required = true; 66040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (field->value.type.base_type != BASE_TYPE_STRING) 66140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("'key' field must be string or scalar type"); 6623550899987f9590357dec34d302380874bb2311cWouter van Oortmerssen } 6633550899987f9590357dec34d302380874bb2311cWouter van Oortmerssen } 664641b397f8b79701b44184a52b5b9c6da98eb7580Wouter van Oortmerssen 665641b397f8b79701b44184a52b5b9c6da98eb7580Wouter van Oortmerssen field->native_inline = field->attributes.Lookup("native_inline") != nullptr; 666641b397f8b79701b44184a52b5b9c6da98eb7580Wouter van Oortmerssen if (field->native_inline && !IsStruct(field->value.type)) 667641b397f8b79701b44184a52b5b9c6da98eb7580Wouter van Oortmerssen return Error("native_inline can only be defined on structs'"); 668641b397f8b79701b44184a52b5b9c6da98eb7580Wouter van Oortmerssen 66940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen auto nested = field->attributes.Lookup("nested_flatbuffer"); 6703e201a99b2f23c8c8475e43803d122b105db9a68Wouter van Oortmerssen if (nested) { 6713e201a99b2f23c8c8475e43803d122b105db9a68Wouter van Oortmerssen if (nested->type.base_type != BASE_TYPE_STRING) 67240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error( 67340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen "nested_flatbuffer attribute must be a string (the root type)"); 67440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (field->value.type.base_type != BASE_TYPE_VECTOR || 67540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen field->value.type.element != BASE_TYPE_UCHAR) 67640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error( 67740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen "nested_flatbuffer attribute may only apply to a vector of ubyte"); 6783e201a99b2f23c8c8475e43803d122b105db9a68Wouter van Oortmerssen // This will cause an error if the root type of the nested flatbuffer 6793e201a99b2f23c8c8475e43803d122b105db9a68Wouter van Oortmerssen // wasn't defined elsewhere. 6803e201a99b2f23c8c8475e43803d122b105db9a68Wouter van Oortmerssen LookupCreateStruct(nested->constant); 68189a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich 68289a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich // Keep a pointer to StructDef in FieldDef to simplify re-use later 683321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen auto nested_qualified_name = 684321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen current_namespace_->GetFullyQualifiedName(nested->constant); 68589a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich field->nested_flatbuffer = structs_.Lookup(nested_qualified_name); 6863e201a99b2f23c8c8475e43803d122b105db9a68Wouter van Oortmerssen } 68726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 688dddd0865cb161a081afbdfa11919622a49f4141aWouter van Oortmerssen if (field->attributes.Lookup("flexbuffer")) { 6898f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen field->flexbuffer = true; 690dddd0865cb161a081afbdfa11919622a49f4141aWouter van Oortmerssen uses_flexbuffers_ = true; 691dddd0865cb161a081afbdfa11919622a49f4141aWouter van Oortmerssen if (field->value.type.base_type != BASE_TYPE_VECTOR || 692dddd0865cb161a081afbdfa11919622a49f4141aWouter van Oortmerssen field->value.type.element != BASE_TYPE_UCHAR) 693dddd0865cb161a081afbdfa11919622a49f4141aWouter van Oortmerssen return Error( 694dddd0865cb161a081afbdfa11919622a49f4141aWouter van Oortmerssen "flexbuffer attribute may only apply to a vector of ubyte"); 695dddd0865cb161a081afbdfa11919622a49f4141aWouter van Oortmerssen } 696dddd0865cb161a081afbdfa11919622a49f4141aWouter van Oortmerssen 6979140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen if (typefield) { 6987cc72e4b11df064391a909ee7fa0ee5dd7630f9bKamil Rojewski if (!IsScalar(typefield->value.type.base_type)) { 6997cc72e4b11df064391a909ee7fa0ee5dd7630f9bKamil Rojewski // this is a union vector field 7007cc72e4b11df064391a909ee7fa0ee5dd7630f9bKamil Rojewski typefield->required = field->required; 7017cc72e4b11df064391a909ee7fa0ee5dd7630f9bKamil Rojewski } 7029140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen // If this field is a union, and it has a manually assigned id, 7039140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen // the automatically added type field should have an id as well (of N - 1). 70440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen auto attr = field->attributes.Lookup("id"); 7059140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen if (attr) { 7069140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen auto id = atoi(attr->constant.c_str()); 7079140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen auto val = new Value(); 7089140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen val->type = attr->type; 7099140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen val->constant = NumToString(id - 1); 7109140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen typefield->attributes.Add("id", val); 7119140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen } 7129140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen } 7139140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen 71440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(';'); 71540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 71626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 71726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 718b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van OortmerssenCheckedError Parser::ParseString(Value &val) { 719b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen auto s = attribute_; 720b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen EXPECT(kTokenStringConstant); 721b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen val.constant = NumToString(builder_.CreateString(s).o); 722b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen return NoError(); 723b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen} 724b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen 725f325cce6fdfc0c85e081fe90c7267fb0e8c79878Wouter van OortmerssenCheckedError Parser::ParseComma() { 726f325cce6fdfc0c85e081fe90c7267fb0e8c79878Wouter van Oortmerssen if (!opts.protobuf_ascii_alike) EXPECT(','); 727f325cce6fdfc0c85e081fe90c7267fb0e8c79878Wouter van Oortmerssen return NoError(); 728f325cce6fdfc0c85e081fe90c7267fb0e8c79878Wouter van Oortmerssen} 729f325cce6fdfc0c85e081fe90c7267fb0e8c79878Wouter van Oortmerssen 73040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseAnyValue(Value &val, FieldDef *field, 7319e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen size_t parent_fieldn, 7329e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen const StructDef *parent_struct_def) { 73326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen switch (val.type.base_type) { 73426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case BASE_TYPE_UNION: { 73526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen assert(field); 7369e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen std::string constant; 737eac2905568ec764f2d6fb0864ff95acec419d163Wouter van Oortmerssen // Find corresponding type field we may have already parsed. 738eac2905568ec764f2d6fb0864ff95acec419d163Wouter van Oortmerssen for (auto elem = field_stack_.rbegin(); 739eac2905568ec764f2d6fb0864ff95acec419d163Wouter van Oortmerssen elem != field_stack_.rbegin() + parent_fieldn; ++elem) { 740eac2905568ec764f2d6fb0864ff95acec419d163Wouter van Oortmerssen auto &type = elem->second->value.type; 741eac2905568ec764f2d6fb0864ff95acec419d163Wouter van Oortmerssen if (type.base_type == BASE_TYPE_UTYPE && 742eac2905568ec764f2d6fb0864ff95acec419d163Wouter van Oortmerssen type.enum_def == val.type.enum_def) { 743eac2905568ec764f2d6fb0864ff95acec419d163Wouter van Oortmerssen constant = elem->first.constant; 744eac2905568ec764f2d6fb0864ff95acec419d163Wouter van Oortmerssen break; 745eac2905568ec764f2d6fb0864ff95acec419d163Wouter van Oortmerssen } 746eac2905568ec764f2d6fb0864ff95acec419d163Wouter van Oortmerssen } 747eac2905568ec764f2d6fb0864ff95acec419d163Wouter van Oortmerssen if (constant.empty()) { 7489e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen // We haven't seen the type field yet. Sadly a lot of JSON writers 7499e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen // output these in alphabetical order, meaning it comes after this 7509e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen // value. So we scan past the value to find it, then come back here. 7519e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen auto type_name = field->name + UnionTypeFieldSuffix(); 7529e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen assert(parent_struct_def); 7539e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen auto type_field = parent_struct_def->fields.Lookup(type_name); 7549e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen assert(type_field); // Guaranteed by ParseField(). 7559e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen // Remember where we are in the source file, so we can come back here. 7569e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen auto backup = *static_cast<ParserState *>(this); 7579e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen ECHECK(SkipAnyJsonValue()); // The table. 758f325cce6fdfc0c85e081fe90c7267fb0e8c79878Wouter van Oortmerssen ECHECK(ParseComma()); 7599e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen auto next_name = attribute_; 7609e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen if (Is(kTokenStringConstant)) { 7619e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen NEXT(); 7629e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen } else { 7639e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen EXPECT(kTokenIdentifier); 7649e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen } 7659e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen if (next_name != type_name) 7669e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen return Error("missing type field after this union value: " + 7679e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen type_name); 7689e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen EXPECT(':'); 7699e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen Value type_val = type_field->value; 7709e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen ECHECK(ParseAnyValue(type_val, type_field, 0, nullptr)); 7719e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen constant = type_val.constant; 7729e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen // Got the information we needed, now rewind: 7739e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen *static_cast<ParserState *>(this) = backup; 7749e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen } 77540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen uint8_t enum_idx; 7769e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen ECHECK(atot(constant.c_str(), *this, &enum_idx)); 7773fb6a86d020f7423553a4e2dbba637b56d7760f6Wouter van Oortmerssen auto enum_val = val.type.enum_def->ReverseLookup(enum_idx); 77840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!enum_val) return Error("illegal type id for: " + field->name); 779b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen if (enum_val->union_type.base_type == BASE_TYPE_STRUCT) { 780b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen ECHECK(ParseTable(*enum_val->union_type.struct_def, &val.constant, 781b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen nullptr)); 782b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen if (enum_val->union_type.struct_def->fixed) { 783b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen // All BASE_TYPE_UNION values are offsets, so turn this into one. 784b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen SerializeStruct(*enum_val->union_type.struct_def, val); 785b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen builder_.ClearOffsets(); 786b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen val.constant = NumToString(builder_.GetSize()); 787b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen } 788b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen } else if (enum_val->union_type.base_type == BASE_TYPE_STRING) { 789b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen ECHECK(ParseString(val)); 790b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen } else { 791b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen assert(false); 792b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen } 79326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen break; 79426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 79526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case BASE_TYPE_STRUCT: 79640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseTable(*val.type.struct_def, &val.constant, nullptr)); 79726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen break; 79826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case BASE_TYPE_STRING: { 799b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen ECHECK(ParseString(val)); 80026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen break; 80126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 80226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case BASE_TYPE_VECTOR: { 80340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen uoffset_t off; 80440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseVector(val.type.VectorType(), &off)); 80540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen val.constant = NumToString(off); 80626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen break; 80726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 808d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames case BASE_TYPE_INT: 809d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames case BASE_TYPE_UINT: 810d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames case BASE_TYPE_LONG: 811d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames case BASE_TYPE_ULONG: { 812d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames if (field && field->attributes.Lookup("hash") && 813d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames (token_ == kTokenIdentifier || token_ == kTokenStringConstant)) { 81440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseHash(val, field)); 815d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames } else { 81640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseSingleValue(val)); 817d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames } 818d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames break; 819d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames } 82026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen default: 82140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseSingleValue(val)); 82226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen break; 82326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 82440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 82526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 82626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 82726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenvoid Parser::SerializeStruct(const StructDef &struct_def, const Value &val) { 8284d7810424c8f964dbcb8dd3179d8c46cd896c4dcWouter van Oortmerssen assert(val.constant.length() == struct_def.bytesize); 82926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen builder_.Align(struct_def.minalign); 8304d7810424c8f964dbcb8dd3179d8c46cd896c4dcWouter van Oortmerssen builder_.PushBytes(reinterpret_cast<const uint8_t *>(val.constant.c_str()), 8314d7810424c8f964dbcb8dd3179d8c46cd896c4dcWouter van Oortmerssen struct_def.bytesize); 83226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen builder_.AddStructOffset(val.offset, builder_.GetSize()); 83326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 83426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 8358f864aad7b875d645236be59ab1037051b12ba10Wouter van OortmerssenCheckedError Parser::ParseTableDelimiters(size_t &fieldn, 8368f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen const StructDef *struct_def, 837a8923222033763f1a74f836c656af19d9f620378Stewart Miles ParseTableDelimitersBody body, 838a8923222033763f1a74f836c656af19d9f620378Stewart Miles void *state) { 8398f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen // We allow tables both as JSON object{ .. } with field names 840b1740688bfbebc0d7fa2d8106d5c0eaa8c6e27d8Guillaume Giraud // or vector[..] with all fields in order 8418f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen char terminator = '}'; 8428f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen bool is_nested_vector = struct_def && Is('['); 8438f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen if (is_nested_vector) { 844b1740688bfbebc0d7fa2d8106d5c0eaa8c6e27d8Guillaume Giraud NEXT(); 8458f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen terminator = ']'; 846b1740688bfbebc0d7fa2d8106d5c0eaa8c6e27d8Guillaume Giraud } else { 847b1740688bfbebc0d7fa2d8106d5c0eaa8c6e27d8Guillaume Giraud EXPECT('{'); 848b1740688bfbebc0d7fa2d8106d5c0eaa8c6e27d8Guillaume Giraud } 8496c2dc41e0df3d6edc8cd8f452dd7a8ad7ff840c0Wouter van Oortmerssen for (;;) { 8508f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen if ((!opts.strict_json || !fieldn) && Is(terminator)) break; 851b1740688bfbebc0d7fa2d8106d5c0eaa8c6e27d8Guillaume Giraud std::string name; 8528f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen if (is_nested_vector) { 8538f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen if (fieldn > struct_def->fields.vec.size()) { 854b1740688bfbebc0d7fa2d8106d5c0eaa8c6e27d8Guillaume Giraud return Error("too many unnamed fields in nested array"); 855b1740688bfbebc0d7fa2d8106d5c0eaa8c6e27d8Guillaume Giraud } 8568f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen name = struct_def->fields.vec[fieldn]->name; 85740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } else { 858b1740688bfbebc0d7fa2d8106d5c0eaa8c6e27d8Guillaume Giraud name = attribute_; 859b1740688bfbebc0d7fa2d8106d5c0eaa8c6e27d8Guillaume Giraud if (Is(kTokenStringConstant)) { 860b1740688bfbebc0d7fa2d8106d5c0eaa8c6e27d8Guillaume Giraud NEXT(); 861b1740688bfbebc0d7fa2d8106d5c0eaa8c6e27d8Guillaume Giraud } else { 862b1740688bfbebc0d7fa2d8106d5c0eaa8c6e27d8Guillaume Giraud EXPECT(opts.strict_json ? kTokenStringConstant : kTokenIdentifier); 863b1740688bfbebc0d7fa2d8106d5c0eaa8c6e27d8Guillaume Giraud } 864f325cce6fdfc0c85e081fe90c7267fb0e8c79878Wouter van Oortmerssen if (!opts.protobuf_ascii_alike || !(Is('{') || Is('['))) EXPECT(':'); 86540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } 866a8923222033763f1a74f836c656af19d9f620378Stewart Miles ECHECK(body(name, fieldn, struct_def, state)); 8678f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen if (Is(terminator)) break; 868f325cce6fdfc0c85e081fe90c7267fb0e8c79878Wouter van Oortmerssen ECHECK(ParseComma()); 8698f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen } 8708f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen NEXT(); 8718f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen if (is_nested_vector && fieldn != struct_def->fields.vec.size()) { 8728f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen return Error("wrong number of unnamed fields in table vector"); 8738f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen } 8748f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen return NoError(); 8758f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen} 8768f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen 8778f864aad7b875d645236be59ab1037051b12ba10Wouter van OortmerssenCheckedError Parser::ParseTable(const StructDef &struct_def, std::string *value, 8788f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen uoffset_t *ovalue) { 879a8923222033763f1a74f836c656af19d9f620378Stewart Miles size_t fieldn_outer = 0; 880a8923222033763f1a74f836c656af19d9f620378Stewart Miles auto err = ParseTableDelimiters(fieldn_outer, &struct_def, 881a8923222033763f1a74f836c656af19d9f620378Stewart Miles [](const std::string &name, size_t &fieldn, 882a8923222033763f1a74f836c656af19d9f620378Stewart Miles const StructDef *struct_def_inner, 883a8923222033763f1a74f836c656af19d9f620378Stewart Miles void *state) -> CheckedError { 884a8923222033763f1a74f836c656af19d9f620378Stewart Miles Parser *parser = static_cast<Parser *>(state); 8852e2063cbeb6ea95c804796c443153f71797c3629schoetbi if (name == "$schema") { 886a8923222033763f1a74f836c656af19d9f620378Stewart Miles ECHECK(parser->Expect(kTokenStringConstant)); 8872e2063cbeb6ea95c804796c443153f71797c3629schoetbi return NoError(); 8882e2063cbeb6ea95c804796c443153f71797c3629schoetbi } 889a8923222033763f1a74f836c656af19d9f620378Stewart Miles auto field = struct_def_inner->fields.Lookup(name); 89013d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke if (!field) { 891a8923222033763f1a74f836c656af19d9f620378Stewart Miles if (!parser->opts.skip_unexpected_fields_in_json) { 892a8923222033763f1a74f836c656af19d9f620378Stewart Miles return parser->Error("unknown field: " + name); 89313d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke } else { 894a8923222033763f1a74f836c656af19d9f620378Stewart Miles ECHECK(parser->SkipAnyJsonValue()); 89513d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke } 89613d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke } else { 89703e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen if (parser->IsIdent("null")) { 898a8923222033763f1a74f836c656af19d9f620378Stewart Miles ECHECK(parser->Next()); // Ignore this field. 899049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen } else { 900049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen Value val = field->value; 9018f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen if (field->flexbuffer) { 9028f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen flexbuffers::Builder builder(1024, 9038f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen flexbuffers::BUILDER_FLAG_SHARE_ALL); 904a8923222033763f1a74f836c656af19d9f620378Stewart Miles ECHECK(parser->ParseFlexBufferValue(&builder)); 9058f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen builder.Finish(); 906a8923222033763f1a74f836c656af19d9f620378Stewart Miles auto off = parser->builder_.CreateVector(builder.GetBuffer()); 9078f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen val.constant = NumToString(off.o); 90889a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich } else if (field->nested_flatbuffer) { 90989a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich ECHECK(parser->ParseNestedFlatbuffer(val, field, fieldn, struct_def_inner)); 9108f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen } else { 911a8923222033763f1a74f836c656af19d9f620378Stewart Miles ECHECK(parser->ParseAnyValue(val, field, fieldn, struct_def_inner)); 9128f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen } 913049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen // Hardcoded insertion-sort with error-check. 914049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen // If fields are specified in order, then this loop exits immediately. 915a8923222033763f1a74f836c656af19d9f620378Stewart Miles auto elem = parser->field_stack_.rbegin(); 916a8923222033763f1a74f836c656af19d9f620378Stewart Miles for (; elem != parser->field_stack_.rbegin() + fieldn; ++elem) { 917eac2905568ec764f2d6fb0864ff95acec419d163Wouter van Oortmerssen auto existing_field = elem->second; 918049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen if (existing_field == field) 919a8923222033763f1a74f836c656af19d9f620378Stewart Miles return parser->Error("field set more than once: " + field->name); 920049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen if (existing_field->value.offset < field->value.offset) break; 921049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen } 922eac2905568ec764f2d6fb0864ff95acec419d163Wouter van Oortmerssen // Note: elem points to before the insertion point, thus .base() points 923eac2905568ec764f2d6fb0864ff95acec419d163Wouter van Oortmerssen // to the correct spot. 924a8923222033763f1a74f836c656af19d9f620378Stewart Miles parser->field_stack_.insert(elem.base(), 925a8923222033763f1a74f836c656af19d9f620378Stewart Miles std::make_pair(val, field)); 926049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen fieldn++; 92713d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke } 9284d7810424c8f964dbcb8dd3179d8c46cd896c4dcWouter van Oortmerssen } 9298f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen return NoError(); 930a8923222033763f1a74f836c656af19d9f620378Stewart Miles }, this); 9318f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen ECHECK(err); 93255dec4d2f8817ede5a98d302d0b947c759f97098sfariv 93355dec4d2f8817ede5a98d302d0b947c759f97098sfariv // Check if all required fields are parsed. 93455dec4d2f8817ede5a98d302d0b947c759f97098sfariv for (auto field_it = struct_def.fields.vec.begin(); 93555dec4d2f8817ede5a98d302d0b947c759f97098sfariv field_it != struct_def.fields.vec.end(); 93655dec4d2f8817ede5a98d302d0b947c759f97098sfariv ++field_it) { 93755dec4d2f8817ede5a98d302d0b947c759f97098sfariv auto required_field = *field_it; 93855dec4d2f8817ede5a98d302d0b947c759f97098sfariv if (!required_field->required) { 93955dec4d2f8817ede5a98d302d0b947c759f97098sfariv continue; 94055dec4d2f8817ede5a98d302d0b947c759f97098sfariv } 94155dec4d2f8817ede5a98d302d0b947c759f97098sfariv bool found = false; 942a8923222033763f1a74f836c656af19d9f620378Stewart Miles for (auto pf_it = field_stack_.end() - fieldn_outer; 94355dec4d2f8817ede5a98d302d0b947c759f97098sfariv pf_it != field_stack_.end(); 94455dec4d2f8817ede5a98d302d0b947c759f97098sfariv ++pf_it) { 94555dec4d2f8817ede5a98d302d0b947c759f97098sfariv auto parsed_field = pf_it->second; 94655dec4d2f8817ede5a98d302d0b947c759f97098sfariv if (parsed_field == required_field) { 94755dec4d2f8817ede5a98d302d0b947c759f97098sfariv found = true; 94855dec4d2f8817ede5a98d302d0b947c759f97098sfariv break; 94955dec4d2f8817ede5a98d302d0b947c759f97098sfariv } 95055dec4d2f8817ede5a98d302d0b947c759f97098sfariv } 95155dec4d2f8817ede5a98d302d0b947c759f97098sfariv if (!found) { 95255dec4d2f8817ede5a98d302d0b947c759f97098sfariv return Error("required field is missing: " + required_field->name + " in " + struct_def.name); 95355dec4d2f8817ede5a98d302d0b947c759f97098sfariv } 95426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 95513d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke 956a8923222033763f1a74f836c656af19d9f620378Stewart Miles if (struct_def.fixed && fieldn_outer != struct_def.fields.vec.size()) 95740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("struct: wrong number of initializers: " + struct_def.name); 9584d7810424c8f964dbcb8dd3179d8c46cd896c4dcWouter van Oortmerssen 95926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto start = struct_def.fixed 96026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen ? builder_.StartStruct(struct_def.minalign) 96126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen : builder_.StartTable(); 96226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 96326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen for (size_t size = struct_def.sortbysize ? sizeof(largest_scalar_t) : 1; 96426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen size; 96526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen size /= 2) { 96626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // Go through elements in reverse, since we're building the data backwards. 967a8923222033763f1a74f836c656af19d9f620378Stewart Miles for (auto it = field_stack_.rbegin(); it != field_stack_.rbegin() + 968a8923222033763f1a74f836c656af19d9f620378Stewart Miles fieldn_outer; 969a8923222033763f1a74f836c656af19d9f620378Stewart Miles ++it) { 970721d21923efe8fabd2e1df0f94891a47f8eb9000Shuhei Tanuma auto &field_value = it->first; 97126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto field = it->second; 97240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!struct_def.sortbysize || 97340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen size == SizeOf(field_value.type.base_type)) { 974721d21923efe8fabd2e1df0f94891a47f8eb9000Shuhei Tanuma switch (field_value.type.base_type) { 97503e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen #define FLATBUFFERS_TD(ENUM, IDLTYPE, \ 976f2b3705c2c62c40afdef96f73f0aeaf32b4c8e0eMikkelFJ CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \ 97726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case BASE_TYPE_ ## ENUM: \ 97826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen builder_.Pad(field->padding); \ 979be3c8742585326447a6f9e776ad90a6b0fceb953Wouter van Oortmerssen if (struct_def.fixed) { \ 98040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen CTYPE val; \ 98140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(atot(field_value.constant.c_str(), *this, &val)); \ 98240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen builder_.PushElement(val); \ 983be3c8742585326447a6f9e776ad90a6b0fceb953Wouter van Oortmerssen } else { \ 98440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen CTYPE val, valdef; \ 98540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(atot(field_value.constant.c_str(), *this, &val)); \ 98640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(atot(field->value.constant.c_str(), *this, &valdef)); \ 98740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen builder_.AddElement(field_value.offset, val, valdef); \ 988be3c8742585326447a6f9e776ad90a6b0fceb953Wouter van Oortmerssen } \ 98926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen break; 99026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen FLATBUFFERS_GEN_TYPES_SCALAR(FLATBUFFERS_TD); 99126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen #undef FLATBUFFERS_TD 99203e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen #define FLATBUFFERS_TD(ENUM, IDLTYPE, \ 993f2b3705c2c62c40afdef96f73f0aeaf32b4c8e0eMikkelFJ CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \ 99426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case BASE_TYPE_ ## ENUM: \ 99526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen builder_.Pad(field->padding); \ 99626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (IsStruct(field->value.type)) { \ 997721d21923efe8fabd2e1df0f94891a47f8eb9000Shuhei Tanuma SerializeStruct(*field->value.type.struct_def, field_value); \ 99826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else { \ 99940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen CTYPE val; \ 100040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(atot(field_value.constant.c_str(), *this, &val)); \ 100140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen builder_.AddOffset(field_value.offset, val); \ 100226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } \ 100326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen break; 100426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen FLATBUFFERS_GEN_TYPES_POINTER(FLATBUFFERS_TD); 100526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen #undef FLATBUFFERS_TD 100626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 100726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 100826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 100926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 1010a8923222033763f1a74f836c656af19d9f620378Stewart Miles for (size_t i = 0; i < fieldn_outer; i++) field_stack_.pop_back(); 101126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 101226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (struct_def.fixed) { 101326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen builder_.ClearOffsets(); 101426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen builder_.EndStruct(); 10154d7810424c8f964dbcb8dd3179d8c46cd896c4dcWouter van Oortmerssen assert(value); 10164d7810424c8f964dbcb8dd3179d8c46cd896c4dcWouter van Oortmerssen // Temporarily store this struct in the value string, since it is to 10174d7810424c8f964dbcb8dd3179d8c46cd896c4dcWouter van Oortmerssen // be serialized in-place elsewhere. 10184d7810424c8f964dbcb8dd3179d8c46cd896c4dcWouter van Oortmerssen value->assign( 10194d7810424c8f964dbcb8dd3179d8c46cd896c4dcWouter van Oortmerssen reinterpret_cast<const char *>(builder_.GetCurrentBufferPointer()), 10204d7810424c8f964dbcb8dd3179d8c46cd896c4dcWouter van Oortmerssen struct_def.bytesize); 102126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen builder_.PopBytes(struct_def.bytesize); 102240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen assert(!ovalue); 102326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else { 1024ac1015e3c417ecb18d8f449a4e6aaaff3c4f53b9Wouter van Oortmerssen auto val = builder_.EndTable(start); 102540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (ovalue) *ovalue = val; 102640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (value) *value = NumToString(val); 102726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 102840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 102926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 103026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 10318f864aad7b875d645236be59ab1037051b12ba10Wouter van OortmerssenCheckedError Parser::ParseVectorDelimiters(size_t &count, 1032a8923222033763f1a74f836c656af19d9f620378Stewart Miles ParseVectorDelimitersBody body, 1033a8923222033763f1a74f836c656af19d9f620378Stewart Miles void *state) { 10348f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen EXPECT('['); 10356c2dc41e0df3d6edc8cd8f452dd7a8ad7ff840c0Wouter van Oortmerssen for (;;) { 10368f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen if ((!opts.strict_json || !count) && Is(']')) break; 1037a8923222033763f1a74f836c656af19d9f620378Stewart Miles ECHECK(body(count, state)); 10388f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen count++; 10398f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen if (Is(']')) break; 1040f325cce6fdfc0c85e081fe90c7267fb0e8c79878Wouter van Oortmerssen ECHECK(ParseComma()); 10418f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen } 10428f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen NEXT(); 10438f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen return NoError(); 10448f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen} 10458f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen 10468f864aad7b875d645236be59ab1037051b12ba10Wouter van OortmerssenCheckedError Parser::ParseVector(const Type &type, uoffset_t *ovalue) { 10478f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen size_t count = 0; 1048a8923222033763f1a74f836c656af19d9f620378Stewart Miles std::pair<Parser *, const Type &> parser_and_type_state(this, type); 1049a8923222033763f1a74f836c656af19d9f620378Stewart Miles auto err = ParseVectorDelimiters(count, 1050a8923222033763f1a74f836c656af19d9f620378Stewart Miles [](size_t &, void *state) -> CheckedError { 1051a8923222033763f1a74f836c656af19d9f620378Stewart Miles auto *parser_and_type = 1052a8923222033763f1a74f836c656af19d9f620378Stewart Miles static_cast<std::pair<Parser *, const Type &> *>(state); 1053a8923222033763f1a74f836c656af19d9f620378Stewart Miles auto *parser = parser_and_type->first; 105426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Value val; 1055a8923222033763f1a74f836c656af19d9f620378Stewart Miles val.type = parser_and_type->second; 1056a8923222033763f1a74f836c656af19d9f620378Stewart Miles ECHECK(parser->ParseAnyValue(val, nullptr, 0, nullptr)); 1057a8923222033763f1a74f836c656af19d9f620378Stewart Miles parser->field_stack_.push_back(std::make_pair(val, nullptr)); 10588f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen return NoError(); 1059a8923222033763f1a74f836c656af19d9f620378Stewart Miles }, &parser_and_type_state); 10608f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen ECHECK(err); 106126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 1062be3c8742585326447a6f9e776ad90a6b0fceb953Wouter van Oortmerssen builder_.StartVector(count * InlineSize(type) / InlineAlignment(type), 1063be3c8742585326447a6f9e776ad90a6b0fceb953Wouter van Oortmerssen InlineAlignment(type)); 10648f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen for (size_t i = 0; i < count; i++) { 106526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // start at the back, since we're building the data backwards. 106626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto &val = field_stack_.back().first; 106726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen switch (val.type.base_type) { 106803e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen #define FLATBUFFERS_TD(ENUM, IDLTYPE, \ 1069f2b3705c2c62c40afdef96f73f0aeaf32b4c8e0eMikkelFJ CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \ 107026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case BASE_TYPE_ ## ENUM: \ 107126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (IsStruct(val.type)) SerializeStruct(*val.type.struct_def, val); \ 107240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen else { \ 107340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen CTYPE elem; \ 107440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(atot(val.constant.c_str(), *this, &elem)); \ 107540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen builder_.PushElement(elem); \ 107640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } \ 107726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen break; 107826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) 107926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen #undef FLATBUFFERS_TD 108026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 108126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen field_stack_.pop_back(); 108226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 108326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 108426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen builder_.ClearOffsets(); 108540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen *ovalue = builder_.EndVector(count); 108640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 108726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 108826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 108989a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian HelmichCheckedError Parser::ParseNestedFlatbuffer(Value &val, FieldDef *field, 109089a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich size_t fieldn, 109189a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich const StructDef *parent_struct_def) { 109289a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich if (token_ == '[') {// backwards compat for 'legacy' ubyte buffers 109389a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich ECHECK(ParseAnyValue(val, field, fieldn, parent_struct_def)); 109489a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich } else { 109589a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich auto cursor_at_value_begin = cursor_; 109689a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich ECHECK(SkipAnyJsonValue()); 109789a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich std::string substring(cursor_at_value_begin -1 , cursor_ -1); 109889a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich 109989a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich // Create and initialize new parser 110089a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich Parser nested_parser; 110189a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich assert(field->nested_flatbuffer); 110289a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich nested_parser.root_struct_def_ = field->nested_flatbuffer; 110389a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich nested_parser.enums_ = enums_; 110489a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich nested_parser.opts = opts; 110589a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich nested_parser.uses_flexbuffers_ = uses_flexbuffers_; 110689a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich 110789a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich // Parse JSON substring into new flatbuffer builder using nested_parser 110889a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich if (!nested_parser.Parse(substring.c_str(), nullptr, nullptr)) { 110989a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich ECHECK(Error(nested_parser.error_)); 111089a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich } 111189a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich auto off = builder_.CreateVector(nested_parser.builder_.GetBufferPointer(), nested_parser.builder_.GetSize()); 111289a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich val.constant = NumToString(off.o); 111389a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich 111489a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich // Clean nested_parser before destruction to avoid deleting the elements in the SymbolTables 111589a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich nested_parser.enums_.dict.clear(); 111689a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich nested_parser.enums_.vec.clear(); 111789a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich } 111889a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich return NoError(); 111989a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich} 112089a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich 1121e6b79f00022aee3108427977c9823ff57154e1c6Wouter van OortmerssenCheckedError Parser::ParseMetaData(SymbolTable<Value> *attributes) { 112240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is('(')) { 112340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 112426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen for (;;) { 112526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto name = attribute_; 112640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 11270952143971bdbb5ef20dae8a865e811a0e31b4b3Wouter van Oortmerssen if (known_attributes_.find(name) == known_attributes_.end()) 112840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("user define attributes must be declared before use: " + 112940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen name); 113026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto e = new Value(); 1131e6b79f00022aee3108427977c9823ff57154e1c6Wouter van Oortmerssen attributes->Add(name, e); 113240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is(':')) { 113340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 113440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseSingleValue(*e)); 113526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 113640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is(')')) { NEXT(); break; } 113740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(','); 113826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 113926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 114040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 114126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 114226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 114340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::TryTypedValue(int dtoken, bool check, Value &e, 114440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen BaseType req, bool *destmatch) { 114526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen bool match = dtoken == token_; 114626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (match) { 114740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen *destmatch = true; 114826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen e.constant = attribute_; 114926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (!check) { 115026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (e.type.base_type == BASE_TYPE_NONE) { 115126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen e.type.base_type = req; 115226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else { 115340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error(std::string("type mismatch: expecting: ") + 115440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen kTypeNames[e.type.base_type] + 115540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ", found: " + 115640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen kTypeNames[req]); 115726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 115826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 115940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 116026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 116140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 116226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 116326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 1164fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van OortmerssenCheckedError Parser::ParseEnumFromString(Type &type, int64_t *result) { 116540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen *result = 0; 11669c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen // Parse one or more enum identifiers, separated by spaces. 11679c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen const char *next = attribute_.c_str(); 11689c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen do { 11699c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen const char *divider = strchr(next, ' '); 11709c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen std::string word; 11719c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen if (divider) { 11729c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen word = std::string(next, divider); 11739c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen next = divider + strspn(divider, " "); 11749c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen } else { 11759c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen word = next; 11769c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen next += word.length(); 11779c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen } 11789c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen if (type.enum_def) { // The field has an enum type 11799c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen auto enum_val = type.enum_def->vals.Lookup(word); 11809c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen if (!enum_val) 118140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("unknown enum value: " + word + 11829c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen ", for enum: " + type.enum_def->name); 118340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen *result |= enum_val->value; 11849c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen } else { // No enum type, probably integral field. 11859c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen if (!IsInteger(type.base_type)) 118640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("not a valid value for this field: " + word); 11879c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen // TODO: could check if its a valid number constant here. 118839833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van Oortmerssen const char *dot = strrchr(word.c_str(), '.'); 118940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!dot) 119040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("enum values need to be qualified by an enum type"); 11919c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen std::string enum_def_str(word.c_str(), dot); 11929c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen std::string enum_val_str(dot + 1, word.c_str() + word.length()); 119339833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van Oortmerssen auto enum_def = LookupEnum(enum_def_str); 119440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!enum_def) return Error("unknown enum: " + enum_def_str); 11959c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen auto enum_val = enum_def->vals.Lookup(enum_val_str); 119640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!enum_val) return Error("unknown enum value: " + enum_val_str); 119740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen *result |= enum_val->value; 11989c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen } 11999c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen } while(*next); 120040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 12019c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen} 12029c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen 1203d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames 120440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseHash(Value &e, FieldDef* field) { 1205d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames assert(field); 1206d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames Value *hash_name = field->attributes.Lookup("hash"); 1207d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames switch (e.type.base_type) { 120846497e4f9ad2f8193dc12cad02d525f93c8f4fd0Wouter van Oortmerssen case BASE_TYPE_INT: { 120946497e4f9ad2f8193dc12cad02d525f93c8f4fd0Wouter van Oortmerssen auto hash = FindHashFunction32(hash_name->constant.c_str()); 121046497e4f9ad2f8193dc12cad02d525f93c8f4fd0Wouter van Oortmerssen int32_t hashed_value = static_cast<int32_t>(hash(attribute_.c_str())); 121146497e4f9ad2f8193dc12cad02d525f93c8f4fd0Wouter van Oortmerssen e.constant = NumToString(hashed_value); 121246497e4f9ad2f8193dc12cad02d525f93c8f4fd0Wouter van Oortmerssen break; 121346497e4f9ad2f8193dc12cad02d525f93c8f4fd0Wouter van Oortmerssen } 1214d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames case BASE_TYPE_UINT: { 1215d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames auto hash = FindHashFunction32(hash_name->constant.c_str()); 1216d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames uint32_t hashed_value = hash(attribute_.c_str()); 1217d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames e.constant = NumToString(hashed_value); 1218d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames break; 1219d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames } 122046497e4f9ad2f8193dc12cad02d525f93c8f4fd0Wouter van Oortmerssen case BASE_TYPE_LONG: { 122146497e4f9ad2f8193dc12cad02d525f93c8f4fd0Wouter van Oortmerssen auto hash = FindHashFunction64(hash_name->constant.c_str()); 122246497e4f9ad2f8193dc12cad02d525f93c8f4fd0Wouter van Oortmerssen int64_t hashed_value = static_cast<int64_t>(hash(attribute_.c_str())); 122346497e4f9ad2f8193dc12cad02d525f93c8f4fd0Wouter van Oortmerssen e.constant = NumToString(hashed_value); 122446497e4f9ad2f8193dc12cad02d525f93c8f4fd0Wouter van Oortmerssen break; 122546497e4f9ad2f8193dc12cad02d525f93c8f4fd0Wouter van Oortmerssen } 1226d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames case BASE_TYPE_ULONG: { 1227d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames auto hash = FindHashFunction64(hash_name->constant.c_str()); 1228d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames uint64_t hashed_value = hash(attribute_.c_str()); 1229d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames e.constant = NumToString(hashed_value); 1230d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames break; 1231d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames } 1232d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames default: 1233d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames assert(0); 1234d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames } 123540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 123640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 1237d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames} 1238d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames 12398f864aad7b875d645236be59ab1037051b12ba10Wouter van OortmerssenCheckedError Parser::TokenError() { 12408f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen return Error("cannot parse value starting with: " + 12418f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen TokenToStringId(token_)); 12428f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen} 12438f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen 124440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseSingleValue(Value &e) { 1245d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen // First see if this could be a conversion function: 1246d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen if (token_ == kTokenIdentifier && *cursor_ == '(') { 1247d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen auto functionname = attribute_; 1248d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen NEXT(); 1249d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen EXPECT('('); 1250d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen ECHECK(ParseSingleValue(e)); 1251d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen EXPECT(')'); 1252d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen #define FLATBUFFERS_FN_DOUBLE(name, op) \ 1253d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen if (functionname == name) { \ 1254d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen auto x = strtod(e.constant.c_str(), nullptr); \ 1255d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen e.constant = NumToString(op); \ 1256d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen } 1257d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen FLATBUFFERS_FN_DOUBLE("deg", x / M_PI * 180); 1258d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen FLATBUFFERS_FN_DOUBLE("rad", x * M_PI / 180); 1259d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen FLATBUFFERS_FN_DOUBLE("sin", sin(x)); 1260d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen FLATBUFFERS_FN_DOUBLE("cos", cos(x)); 1261d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen FLATBUFFERS_FN_DOUBLE("tan", tan(x)); 1262d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen FLATBUFFERS_FN_DOUBLE("asin", asin(x)); 1263d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen FLATBUFFERS_FN_DOUBLE("acos", acos(x)); 1264d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen FLATBUFFERS_FN_DOUBLE("atan", atan(x)); 1265d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen // TODO(wvo): add more useful conversion functions here. 1266d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen #undef FLATBUFFERS_FN_DOUBLE 1267d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen // Then check if this could be a string/identifier enum value: 1268d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen } else if (e.type.base_type != BASE_TYPE_STRING && 126903e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen e.type.base_type != BASE_TYPE_BOOL && 12709c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen e.type.base_type != BASE_TYPE_NONE && 12719c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen (token_ == kTokenIdentifier || token_ == kTokenStringConstant)) { 1272fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen if (IsIdentifierStart(attribute_[0])) { // Enum value. 1273fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen int64_t val; 1274fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen ECHECK(ParseEnumFromString(e.type, &val)); 1275fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen e.constant = NumToString(val); 1276fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen NEXT(); 1277fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen } else { // Numeric constant in string. 1278fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen if (IsInteger(e.type.base_type)) { 1279b6ba322a0411925757196a1ca6f3a1a87f46831eSahil Jain char *end; 1280b6ba322a0411925757196a1ca6f3a1a87f46831eSahil Jain e.constant = NumToString(StringToInt(attribute_.c_str(), &end)); 1281b6ba322a0411925757196a1ca6f3a1a87f46831eSahil Jain if (*end) 1282b6ba322a0411925757196a1ca6f3a1a87f46831eSahil Jain return Error("invalid integer: " + attribute_); 1283fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen } else if (IsFloat(e.type.base_type)) { 1284b6ba322a0411925757196a1ca6f3a1a87f46831eSahil Jain char *end; 1285b6ba322a0411925757196a1ca6f3a1a87f46831eSahil Jain e.constant = NumToString(strtod(attribute_.c_str(), &end)); 1286b6ba322a0411925757196a1ca6f3a1a87f46831eSahil Jain if (*end) 1287b6ba322a0411925757196a1ca6f3a1a87f46831eSahil Jain return Error("invalid float: " + attribute_); 1288fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen } else { 1289fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen assert(0); // Shouldn't happen, we covered all types. 1290fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen e.constant = "0"; 1291fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen } 129283dc5ed4a7267c78fb3f00e972de4db30762166dWouter van Oortmerssen NEXT(); 1293fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen } 129426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else { 129540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen bool match = false; 129640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(TryTypedValue(kTokenIntegerConstant, 129740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen IsScalar(e.type.base_type), 129840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen e, 129940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen BASE_TYPE_INT, 130040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen &match)); 130140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(TryTypedValue(kTokenFloatConstant, 130240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen IsFloat(e.type.base_type), 130340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen e, 130440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen BASE_TYPE_FLOAT, 130540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen &match)); 130640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(TryTypedValue(kTokenStringConstant, 130740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen e.type.base_type == BASE_TYPE_STRING, 130840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen e, 130940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen BASE_TYPE_STRING, 131040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen &match)); 131103e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen auto istrue = IsIdent("true"); 131203e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen if (istrue || IsIdent("false")) { 131303e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen attribute_ = NumToString(istrue); 131403e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen ECHECK(TryTypedValue(kTokenIdentifier, 131503e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen IsBool(e.type.base_type), 131603e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen e, 131703e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen BASE_TYPE_BOOL, 131803e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen &match)); 131903e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } 13208f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen if (!match) return TokenError(); 132126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 132240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 132326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 132426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 132594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van OortmerssenStructDef *Parser::LookupCreateStruct(const std::string &name, 132694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen bool create_if_new, bool definition) { 1327321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen std::string qualified_name = current_namespace_->GetFullyQualifiedName(name); 132820c0082ee5bfeeecaa443c001a89934e9448ffa4Wouter van Oortmerssen // See if it exists pre-declared by an unqualified use. 132994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen auto struct_def = structs_.Lookup(name); 133094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (struct_def && struct_def->predecl) { 133194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (definition) { 133220c0082ee5bfeeecaa443c001a89934e9448ffa4Wouter van Oortmerssen // Make sure it has the current namespace, and is registered under its 133320c0082ee5bfeeecaa443c001a89934e9448ffa4Wouter van Oortmerssen // qualified name. 1334321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen struct_def->defined_namespace = current_namespace_; 133594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen structs_.Move(name, qualified_name); 133694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 133794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen return struct_def; 133894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 133920c0082ee5bfeeecaa443c001a89934e9448ffa4Wouter van Oortmerssen // See if it exists pre-declared by an qualified use. 134094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen struct_def = structs_.Lookup(qualified_name); 134120c0082ee5bfeeecaa443c001a89934e9448ffa4Wouter van Oortmerssen if (struct_def && struct_def->predecl) { 134220c0082ee5bfeeecaa443c001a89934e9448ffa4Wouter van Oortmerssen if (definition) { 134320c0082ee5bfeeecaa443c001a89934e9448ffa4Wouter van Oortmerssen // Make sure it has the current namespace. 1344321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen struct_def->defined_namespace = current_namespace_; 134520c0082ee5bfeeecaa443c001a89934e9448ffa4Wouter van Oortmerssen } 134620c0082ee5bfeeecaa443c001a89934e9448ffa4Wouter van Oortmerssen return struct_def; 134720c0082ee5bfeeecaa443c001a89934e9448ffa4Wouter van Oortmerssen } 134894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (!definition) { 134994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Search thru parent namespaces. 1350321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen for (size_t components = current_namespace_->components.size(); 135194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen components && !struct_def; components--) { 135294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen struct_def = structs_.Lookup( 1353321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen current_namespace_->GetFullyQualifiedName(name, components - 1)); 135494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 135594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 135694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (!struct_def && create_if_new) { 135726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen struct_def = new StructDef(); 135894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (definition) { 135994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen structs_.Add(qualified_name, struct_def); 136094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen struct_def->name = name; 1361321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen struct_def->defined_namespace = current_namespace_; 136294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else { 136394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Not a definition. 136494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Rather than failing, we create a "pre declared" StructDef, due to 136594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // circular references, and check for errors at the end of parsing. 136694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // It is defined in the root namespace, since we don't know what the 136794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // final namespace will be. 136894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // TODO: maybe safer to use special namespace? 136994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen structs_.Add(name, struct_def); 137094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen struct_def->name = name; 1371321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen struct_def->defined_namespace = empty_namespace_; 137294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 137326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 137426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen return struct_def; 137526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 137626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 137740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseEnum(bool is_union, EnumDef **dest) { 1378c3807fa39dda5445924ef77253efb446459f6e56Max Galkin std::vector<std::string> enum_comment = doc_comment_; 137940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 1380c3807fa39dda5445924ef77253efb446459f6e56Max Galkin std::string enum_name = attribute_; 138140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 138226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto &enum_def = *new EnumDef(); 1383c3807fa39dda5445924ef77253efb446459f6e56Max Galkin enum_def.name = enum_name; 138440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen enum_def.file = file_being_parsed_; 1385c3807fa39dda5445924ef77253efb446459f6e56Max Galkin enum_def.doc_comment = enum_comment; 138626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen enum_def.is_union = is_union; 1387321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen enum_def.defined_namespace = current_namespace_; 1388321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen if (enums_.Add(current_namespace_->GetFullyQualifiedName(enum_name), 138994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen &enum_def)) 139040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("enum already exists: " + enum_name); 139126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (is_union) { 139226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen enum_def.underlying_type.base_type = BASE_TYPE_UTYPE; 139326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen enum_def.underlying_type.enum_def = &enum_def; 1394a5f50019bc979c352bb7e0c08b8bbfd8ab06af4dWouter van Oortmerssen } else { 139545bda6e08de1436e8a25e791b776e0bcc38f232bWouter van Oortmerssen if (opts.proto_mode) { 139694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen enum_def.underlying_type.base_type = BASE_TYPE_INT; 1397d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen } else { 1398d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen // Give specialized error message, since this type spec used to 1399d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen // be optional in the first FlatBuffers release. 140040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!Is(':')) { 140140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("must specify the underlying integer type for this" 140240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen " enum (e.g. \': short\', which was the default)."); 140340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } else { 140440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 140540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } 1406d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen // Specify the integer type underlying this enum. 140740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseType(enum_def.underlying_type)); 1408d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen if (!IsInteger(enum_def.underlying_type.base_type)) 140940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("underlying enum type must be integral"); 1410d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen } 14113fb6a86d020f7423553a4e2dbba637b56d7760f6Wouter van Oortmerssen // Make this type refer back to the enum it was derived from. 14123fb6a86d020f7423553a4e2dbba637b56d7760f6Wouter van Oortmerssen enum_def.underlying_type.enum_def = &enum_def; 141326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 1414e6b79f00022aee3108427977c9823ff57154e1c6Wouter van Oortmerssen ECHECK(ParseMetaData(&enum_def.attributes)); 141540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT('{'); 141626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (is_union) enum_def.vals.Add("NONE", new EnumVal("NONE", 0)); 141740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen for (;;) { 141845bda6e08de1436e8a25e791b776e0bcc38f232bWouter van Oortmerssen if (opts.proto_mode && attribute_ == "option") { 141940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseProtoOption()); 142094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else { 142194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen auto value_name = attribute_; 142294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen auto full_name = value_name; 142394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen std::vector<std::string> value_comment = doc_comment_; 142440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 14253639032d1e2224663202f79ca33c5039eed95f29Wouter van Oortmerssen if (is_union) { 14263639032d1e2224663202f79ca33c5039eed95f29Wouter van Oortmerssen ECHECK(ParseNamespacing(&full_name, &value_name)); 1427d70f5ac6b02f250dca8e2c6e8f59a4223d1f66f6Wouter van Oortmerssen if (opts.union_value_namespacing) { 1428d70f5ac6b02f250dca8e2c6e8f59a4223d1f66f6Wouter van Oortmerssen // Since we can't namespace the actual enum identifiers, turn 1429d70f5ac6b02f250dca8e2c6e8f59a4223d1f66f6Wouter van Oortmerssen // namespace parts into part of the identifier. 1430d70f5ac6b02f250dca8e2c6e8f59a4223d1f66f6Wouter van Oortmerssen value_name = full_name; 1431d70f5ac6b02f250dca8e2c6e8f59a4223d1f66f6Wouter van Oortmerssen std::replace(value_name.begin(), value_name.end(), '.', '_'); 1432d70f5ac6b02f250dca8e2c6e8f59a4223d1f66f6Wouter van Oortmerssen } 14333639032d1e2224663202f79ca33c5039eed95f29Wouter van Oortmerssen } 143494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen auto prevsize = enum_def.vals.vec.size(); 143594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen auto value = enum_def.vals.vec.size() 143694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen ? enum_def.vals.vec.back()->value + 1 143794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen : 0; 143894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen auto &ev = *new EnumVal(value_name, value); 143994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (enum_def.vals.Add(value_name, &ev)) 144040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("enum value already exists: " + value_name); 144194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen ev.doc_comment = value_comment; 144294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (is_union) { 1443b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen if (Is(':')) { 1444b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen NEXT(); 1445b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen ECHECK(ParseType(ev.union_type)); 1446b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen if (ev.union_type.base_type != BASE_TYPE_STRUCT && 1447b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen ev.union_type.base_type != BASE_TYPE_STRING) 1448b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen return Error("union value type may only be table/struct/string"); 1449b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen enum_def.uses_type_aliases = true; 1450b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen } else { 1451b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen ev.union_type = Type(BASE_TYPE_STRUCT, LookupCreateStruct(full_name)); 1452b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen } 145394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 145440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is('=')) { 145540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 1456d779308b3e48124dae91896700bf3cc12b5251e3Wouter van Oortmerssen ev.value = StringToInt(attribute_.c_str()); 145740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIntegerConstant); 145845bda6e08de1436e8a25e791b776e0bcc38f232bWouter van Oortmerssen if (!opts.proto_mode && prevsize && 145994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen enum_def.vals.vec[prevsize - 1]->value >= ev.value) 146040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("enum values must be specified in ascending order"); 146194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 14629d01bfaea3befaa0e12b0b310cadc1ed036ecfe3Wouter van Oortmerssen if (is_union) { 14639d01bfaea3befaa0e12b0b310cadc1ed036ecfe3Wouter van Oortmerssen if (ev.value < 0 || ev.value >= 256) 14649d01bfaea3befaa0e12b0b310cadc1ed036ecfe3Wouter van Oortmerssen return Error("union enum value must fit in a ubyte"); 14659d01bfaea3befaa0e12b0b310cadc1ed036ecfe3Wouter van Oortmerssen } 146640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (opts.proto_mode && Is('[')) { 146740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 146894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // ignore attributes on enums. 146940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen while (token_ != ']') NEXT(); 147040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 147194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 147226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 147340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!Is(opts.proto_mode ? ';' : ',')) break; 147440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 147540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is('}')) break; 147640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } 147740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT('}'); 1478127d35085a22cb33034f608ee21d65a655d1582cWouter van Oortmerssen if (enum_def.attributes.Lookup("bit_flags")) { 1479127d35085a22cb33034f608ee21d65a655d1582cWouter van Oortmerssen for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end(); 1480127d35085a22cb33034f608ee21d65a655d1582cWouter van Oortmerssen ++it) { 1481127d35085a22cb33034f608ee21d65a655d1582cWouter van Oortmerssen if (static_cast<size_t>((*it)->value) >= 1482127d35085a22cb33034f608ee21d65a655d1582cWouter van Oortmerssen SizeOf(enum_def.underlying_type.base_type) * 8) 148340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("bit flag out of range of underlying integral type"); 14849c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen (*it)->value = 1LL << (*it)->value; 1485127d35085a22cb33034f608ee21d65a655d1582cWouter van Oortmerssen } 1486127d35085a22cb33034f608ee21d65a655d1582cWouter van Oortmerssen } 148740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (dest) *dest = &enum_def; 1488321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen types_.Add(current_namespace_->GetFullyQualifiedName(enum_def.name), 14899b3d8b318a3bc9d71d08b50d723996f556557c86Wouter van Oortmerssen new Type(BASE_TYPE_UNION, nullptr, &enum_def)); 149040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 149126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 149226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 149340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::StartStruct(const std::string &name, StructDef **dest) { 149494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen auto &struct_def = *LookupCreateStruct(name, true, true); 149540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!struct_def.predecl) return Error("datatype already exists: " + name); 149626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen struct_def.predecl = false; 149726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen struct_def.name = name; 149840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen struct_def.file = file_being_parsed_; 149926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // Move this struct to the back of the vector just in case it was predeclared, 1500d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen // to preserve declaration order. 1501370693a200cf2a6eb58be5d17fe6482f3e05c067Dmitry Ermolov *std::remove(structs_.vec.begin(), structs_.vec.end(), &struct_def) = &struct_def; 150240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen *dest = &struct_def; 150340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 1504d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen} 1505d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen 1506b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra PenkeCheckedError Parser::CheckClash(std::vector<FieldDef*> &fields, 1507b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke StructDef *struct_def, 1508b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke const char *suffix, 1509b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke BaseType basetype) { 1510b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke auto len = strlen(suffix); 1511b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke for (auto it = fields.begin(); it != fields.end(); ++it) { 1512b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke auto &fname = (*it)->name; 1513b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke if (fname.length() > len && 1514b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke fname.compare(fname.length() - len, len, suffix) == 0 && 1515b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke (*it)->value.type.base_type != BASE_TYPE_UTYPE) { 1516b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke auto field = struct_def->fields.Lookup( 1517b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke fname.substr(0, fname.length() - len)); 1518b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke if (field && field->value.type.base_type == basetype) 1519b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke return Error("Field " + fname + 1520b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke " would clash with generated functions for field " + 1521b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke field->name); 1522b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke } 1523b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke } 1524b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke return NoError(); 1525b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke} 1526d779308b3e48124dae91896700bf3cc12b5251e3Wouter van Oortmerssen 152746bb05d95226c72cc85242eee386465860786333Kamil Rojewskibool Parser::SupportsVectorOfUnions() const { 152846bb05d95226c72cc85242eee386465860786333Kamil Rojewski return opts.lang_to_generate != 0 && (opts.lang_to_generate & 152946bb05d95226c72cc85242eee386465860786333Kamil Rojewski ~(IDLOptions::kCpp | IDLOptions::kJs | IDLOptions::kTs | IDLOptions::kPhp)) == 0; 153046bb05d95226c72cc85242eee386465860786333Kamil Rojewski} 153146bb05d95226c72cc85242eee386465860786333Kamil Rojewski 1532321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van OortmerssenNamespace *Parser::UniqueNamespace(Namespace *ns) { 1533321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen for (auto it = namespaces_.begin(); it != namespaces_.end(); ++it) { 1534321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen if (ns->components == (*it)->components) { 1535321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen delete ns; 1536321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen return *it; 1537321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen } 1538321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen } 1539321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen namespaces_.push_back(ns); 1540321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen return ns; 1541321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen} 1542321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen 1543b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penkestatic bool compareFieldDefs(const FieldDef *a, const FieldDef *b) { 1544b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke auto a_id = atoi(a->attributes.Lookup("id")->constant.c_str()); 1545b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke auto b_id = atoi(b->attributes.Lookup("id")->constant.c_str()); 1546b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke return a_id < b_id; 1547b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke} 1548b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke 154940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseDecl() { 1550d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen std::vector<std::string> dc = doc_comment_; 155103e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen bool fixed = IsIdent("struct"); 155203e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen if (!fixed && !IsIdent("table")) return Error("declaration expected"); 155303e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen NEXT(); 155494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen std::string name = attribute_; 155540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 155640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen StructDef *struct_def; 155740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(StartStruct(name, &struct_def)); 155840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen struct_def->doc_comment = dc; 155940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen struct_def->fixed = fixed; 1560e6b79f00022aee3108427977c9823ff57154e1c6Wouter van Oortmerssen ECHECK(ParseMetaData(&struct_def->attributes)); 156140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen struct_def->sortbysize = 156240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen struct_def->attributes.Lookup("original_order") == nullptr && !fixed; 156340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT('{'); 156440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen while (token_ != '}') ECHECK(ParseField(*struct_def)); 156540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen auto force_align = struct_def->attributes.Lookup("force_align"); 156626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (fixed && force_align) { 156726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto align = static_cast<size_t>(atoi(force_align->constant.c_str())); 156826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (force_align->type.base_type != BASE_TYPE_INT || 156940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen align < struct_def->minalign || 15706862b2ff08021c7ba474334a6e2a3f3b1fc0dee5Wouter van Oortmerssen align > FLATBUFFERS_MAX_ALIGNMENT || 157126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen align & (align - 1)) 157240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("force_align must be a power of two integer ranging from the" 15736862b2ff08021c7ba474334a6e2a3f3b1fc0dee5Wouter van Oortmerssen "struct\'s natural alignment to " + 15746862b2ff08021c7ba474334a6e2a3f3b1fc0dee5Wouter van Oortmerssen NumToString(FLATBUFFERS_MAX_ALIGNMENT)); 157540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen struct_def->minalign = align; 157626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 157740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen struct_def->PadLastField(struct_def->minalign); 15789140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen // Check if this is a table that has manual id assignments 157940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen auto &fields = struct_def->fields.vec; 158040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!struct_def->fixed && fields.size()) { 15817fcbe723fc821785abfec0348023d9ebf5b4db96Wouter van Oortmerssen size_t num_id_fields = 0; 15829140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen for (auto it = fields.begin(); it != fields.end(); ++it) { 15839140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen if ((*it)->attributes.Lookup("id")) num_id_fields++; 15849140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen } 15859140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen // If any fields have ids.. 15869140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen if (num_id_fields) { 15879140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen // Then all fields must have them. 15889140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen if (num_id_fields != fields.size()) 158940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error( 159040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen "either all fields or no fields must have an 'id' attribute"); 15919140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen // Simply sort by id, then the fields are the same as if no ids had 15929140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen // been specified. 1593b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke std::sort(fields.begin(), fields.end(), compareFieldDefs); 15949140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen // Verify we have a contiguous set, and reassign vtable offsets. 15959140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen for (int i = 0; i < static_cast<int>(fields.size()); i++) { 15969140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen if (i != atoi(fields[i]->attributes.Lookup("id")->constant.c_str())) 159740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("field id\'s must be consecutive from 0, id " + 15989140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen NumToString(i) + " missing or set twice"); 15999140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen fields[i]->value.offset = FieldIndexToOffset(static_cast<voffset_t>(i)); 16009140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen } 16019140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen } 16029140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen } 1603b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke 16049e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen ECHECK(CheckClash(fields, struct_def, UnionTypeFieldSuffix(), 16059e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen BASE_TYPE_UNION)); 1606b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke ECHECK(CheckClash(fields, struct_def, "Type", BASE_TYPE_UNION)); 1607b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke ECHECK(CheckClash(fields, struct_def, "_length", BASE_TYPE_VECTOR)); 1608b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke ECHECK(CheckClash(fields, struct_def, "Length", BASE_TYPE_VECTOR)); 1609b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke ECHECK(CheckClash(fields, struct_def, "_byte_vector", BASE_TYPE_STRING)); 1610b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke ECHECK(CheckClash(fields, struct_def, "ByteVector", BASE_TYPE_STRING)); 161140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT('}'); 1612321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen types_.Add(current_namespace_->GetFullyQualifiedName(struct_def->name), 16139b3d8b318a3bc9d71d08b50d723996f556557c86Wouter van Oortmerssen new Type(BASE_TYPE_STRUCT, struct_def, nullptr)); 161440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 161526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 161626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 16171a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van OortmerssenCheckedError Parser::ParseService() { 16181a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen std::vector<std::string> service_comment = doc_comment_; 16191a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen NEXT(); 16201a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen auto service_name = attribute_; 16211a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen EXPECT(kTokenIdentifier); 16221a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen auto &service_def = *new ServiceDef(); 16231a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen service_def.name = service_name; 16241a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen service_def.file = file_being_parsed_; 16251a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen service_def.doc_comment = service_comment; 1626321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen service_def.defined_namespace = current_namespace_; 1627321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen if (services_.Add(current_namespace_->GetFullyQualifiedName(service_name), 16281a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen &service_def)) 16291a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen return Error("service already exists: " + service_name); 1630e6b79f00022aee3108427977c9823ff57154e1c6Wouter van Oortmerssen ECHECK(ParseMetaData(&service_def.attributes)); 16311a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen EXPECT('{'); 16321a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen do { 16331a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen auto rpc_name = attribute_; 16341a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen EXPECT(kTokenIdentifier); 16351a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen EXPECT('('); 16361a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen Type reqtype, resptype; 16371a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen ECHECK(ParseTypeIdent(reqtype)); 16381a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen EXPECT(')'); 16391a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen EXPECT(':'); 16401a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen ECHECK(ParseTypeIdent(resptype)); 16411a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen if (reqtype.base_type != BASE_TYPE_STRUCT || reqtype.struct_def->fixed || 16421a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen resptype.base_type != BASE_TYPE_STRUCT || resptype.struct_def->fixed) 16431a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen return Error("rpc request and response types must be tables"); 16441a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen auto &rpc = *new RPCCall(); 16451a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen rpc.name = rpc_name; 16461a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen rpc.request = reqtype.struct_def; 16471a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen rpc.response = resptype.struct_def; 16481a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen if (service_def.calls.Add(rpc_name, &rpc)) 16491a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen return Error("rpc already exists: " + rpc_name); 1650e6b79f00022aee3108427977c9823ff57154e1c6Wouter van Oortmerssen ECHECK(ParseMetaData(&rpc.attributes)); 16511a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen EXPECT(';'); 16521a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen } while (token_ != '}'); 16531a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen NEXT(); 16541a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen return NoError(); 16551a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen} 16561a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen 165726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenbool Parser::SetRootType(const char *name) { 16584dcaec7938e0a9fe9f0451fe296b6151e3554275Wouter van Oortmerssen root_struct_def_ = structs_.Lookup(name); 16594dcaec7938e0a9fe9f0451fe296b6151e3554275Wouter van Oortmerssen if (!root_struct_def_) 16604dcaec7938e0a9fe9f0451fe296b6151e3554275Wouter van Oortmerssen root_struct_def_ = structs_.Lookup( 1661321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen current_namespace_->GetFullyQualifiedName(name)); 166281312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen return root_struct_def_ != nullptr; 166326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 166426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 1665be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssenvoid Parser::MarkGenerated() { 16663881bbd6517f97deb239f32ff5ebec8db86e902fWouter van Oortmerssen // This function marks all existing definitions as having already 16673881bbd6517f97deb239f32ff5ebec8db86e902fWouter van Oortmerssen // been generated, which signals no code for included files should be 16683881bbd6517f97deb239f32ff5ebec8db86e902fWouter van Oortmerssen // generated. 1669be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen for (auto it = enums_.vec.begin(); 1670be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen it != enums_.vec.end(); ++it) { 1671be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen (*it)->generated = true; 1672be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen } 1673be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen for (auto it = structs_.vec.begin(); 1674be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen it != structs_.vec.end(); ++it) { 16750e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath if (!(*it)->predecl) { 16760e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath (*it)->generated = true; 16770e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath } 1678be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen } 167948f37f9e0a04f2b60046dda7fef20a8b0ebc1a70Wouter van Oortmerssen for (auto it = services_.vec.begin(); 168048f37f9e0a04f2b60046dda7fef20a8b0ebc1a70Wouter van Oortmerssen it != services_.vec.end(); ++it) { 168148f37f9e0a04f2b60046dda7fef20a8b0ebc1a70Wouter van Oortmerssen (*it)->generated = true; 168248f37f9e0a04f2b60046dda7fef20a8b0ebc1a70Wouter van Oortmerssen } 1683be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen} 1684be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen 168540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseNamespace() { 168640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 1687d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen auto ns = new Namespace(); 1688321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen namespaces_.push_back(ns); // Store it here to not leak upon error. 168994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (token_ != ';') { 169094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen for (;;) { 169194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen ns->components.push_back(attribute_); 169240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 169340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is('.')) NEXT() else break; 169494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 1695d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen } 1696321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen namespaces_.pop_back(); 1697321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen current_namespace_ = UniqueNamespace(ns); 169840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(';'); 169940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 1700d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen} 1701d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen 1702b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penkestatic bool compareEnumVals(const EnumVal *a, const EnumVal* b) { 1703b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke return a->value < b->value; 1704b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke} 1705b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke 1706d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen// Best effort parsing of .proto declarations, with the aim to turn them 1707d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen// in the closest corresponding FlatBuffer equivalent. 1708d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen// We parse everything as identifiers instead of keywords, since we don't 1709d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen// want protobuf keywords to become invalid identifiers in FlatBuffers. 171040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseProtoDecl() { 171103e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen bool isextend = IsIdent("extend"); 171203e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen if (IsIdent("package")) { 1713d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen // These are identical in syntax to FlatBuffer's namespace decl. 171440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseNamespace()); 171503e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if (IsIdent("message") || isextend) { 17163ad853630c6bf76a9c8fc2a15e3fc40cd52de691Advay Mengle std::vector<std::string> struct_comment = doc_comment_; 171740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 171894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen StructDef *struct_def = nullptr; 1719321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen Namespace *parent_namespace = nullptr; 172094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (isextend) { 172140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is('.')) NEXT(); // qualified names may start with a . ? 172294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen auto id = attribute_; 172340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 172440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseNamespacing(&id, nullptr)); 172594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen struct_def = LookupCreateStruct(id, false); 172640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!struct_def) 172740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("cannot extend unknown message type: " + id); 172894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else { 172994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen std::string name = attribute_; 173040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 173140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(StartStruct(name, &struct_def)); 173294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Since message definitions can be nested, we create a new namespace. 173394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen auto ns = new Namespace(); 173494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Copy of current namespace. 1735321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen *ns = *current_namespace_; 173694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // But with current message name. 173794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen ns->components.push_back(name); 1738321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen parent_namespace = current_namespace_; 1739321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen current_namespace_ = UniqueNamespace(ns); 174094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 174194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen struct_def->doc_comment = struct_comment; 174240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseProtoFields(struct_def, isextend, false)); 174394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (!isextend) { 1744321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen current_namespace_ = parent_namespace; 174594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 174640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is(';')) NEXT(); 174703e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if (IsIdent("enum")) { 174894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // These are almost the same, just with different terminator: 174940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EnumDef *enum_def; 175040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseEnum(false, &enum_def)); 175140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is(';')) NEXT(); 175294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Protobuf allows them to be specified in any order, so sort afterwards. 175340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen auto &v = enum_def->vals.vec; 1754d779308b3e48124dae91896700bf3cc12b5251e3Wouter van Oortmerssen std::sort(v.begin(), v.end(), compareEnumVals); 1755b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke 175694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Temp: remove any duplicates, as .fbs files can't handle them. 175794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen for (auto it = v.begin(); it != v.end(); ) { 175894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (it != v.begin() && it[0]->value == it[-1]->value) it = v.erase(it); 175994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen else ++it; 176094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 176103e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if (IsIdent("syntax")) { // Skip these. 176240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 176340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT('='); 176440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenStringConstant); 176540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(';'); 176603e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if (IsIdent("option")) { // Skip these. 176740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseProtoOption()); 176840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(';'); 176903e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if (IsIdent("service")) { // Skip these. 177040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 177140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 177240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseProtoCurliesOrIdent()); 177394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else { 177440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("don\'t know how to parse .proto declaration starting with " + 177594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen TokenToStringId(token_)); 177694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 177740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 177894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen} 177994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen 178040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseProtoFields(StructDef *struct_def, bool isextend, 178140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen bool inside_oneof) { 178240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT('{'); 178394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen while (token_ != '}') { 178403e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen if (IsIdent("message") || IsIdent("extend") || IsIdent("enum")) { 178594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Nested declarations. 178640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseProtoDecl()); 178703e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if (IsIdent("extensions")) { // Skip these. 178840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 178940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIntegerConstant); 179040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is(kTokenIdentifier)) { 179140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); // to 179240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); // num 179394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 179440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(';'); 179503e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if (IsIdent("option")) { // Skip these. 179640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseProtoOption()); 179740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(';'); 179803e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if (IsIdent("reserved")) { // Skip these. 179940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 180040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIntegerConstant); 180140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen while (Is(',')) { NEXT(); EXPECT(kTokenIntegerConstant); } 180240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(';'); 180394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else { 180494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen std::vector<std::string> field_comment = doc_comment_; 180594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Parse the qualifier. 180694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen bool required = false; 180794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen bool repeated = false; 180894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen bool oneof = false; 180994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (!inside_oneof) { 181003e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen if (IsIdent("optional")) { 18112abe24b9ddd22fd095d96f002fb8c16b4edc36d2Wouter van Oortmerssen // This is the default. 181203e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen NEXT(); 181303e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if (IsIdent("required")) { 18142abe24b9ddd22fd095d96f002fb8c16b4edc36d2Wouter van Oortmerssen required = true; 181503e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen NEXT(); 181603e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if (IsIdent("repeated")) { 18172abe24b9ddd22fd095d96f002fb8c16b4edc36d2Wouter van Oortmerssen repeated = true; 181803e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen NEXT(); 181903e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if (IsIdent("oneof")) { 182094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen oneof = true; 182103e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen NEXT(); 18222abe24b9ddd22fd095d96f002fb8c16b4edc36d2Wouter van Oortmerssen } else { 182394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // can't error, proto3 allows decls without any of the above. 18242abe24b9ddd22fd095d96f002fb8c16b4edc36d2Wouter van Oortmerssen } 182594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 182694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen StructDef *anonymous_struct = nullptr; 182794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen Type type; 182803e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen if (IsIdent("group") || oneof) { 182903e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen if (!oneof) NEXT(); 183094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen auto name = "Anonymous" + NumToString(anonymous_counter++); 183140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(StartStruct(name, &anonymous_struct)); 183294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen type = Type(BASE_TYPE_STRUCT, anonymous_struct); 183394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else { 183440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseTypeFromProtoType(&type)); 183594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 183694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Repeated elements get mapped to a vector. 183794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (repeated) { 183894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen type.element = type.base_type; 183994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen type.base_type = BASE_TYPE_VECTOR; 184094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 184194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen std::string name = attribute_; 184203e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen EXPECT(kTokenIdentifier); 184394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (!oneof) { 18442abe24b9ddd22fd095d96f002fb8c16b4edc36d2Wouter van Oortmerssen // Parse the field id. Since we're just translating schemas, not 18452abe24b9ddd22fd095d96f002fb8c16b4edc36d2Wouter van Oortmerssen // any kind of binary compatibility, we can safely ignore these, and 18462abe24b9ddd22fd095d96f002fb8c16b4edc36d2Wouter van Oortmerssen // assign our own. 184740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT('='); 184840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIntegerConstant); 184994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 185040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen FieldDef *field = nullptr; 185194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (isextend) { 185294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // We allow a field to be re-defined when extending. 185394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // TODO: are there situations where that is problematic? 185440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen field = struct_def->fields.Lookup(name); 185594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 185640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!field) ECHECK(AddField(*struct_def, name, type, &field)); 185740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen field->doc_comment = field_comment; 185840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!IsScalar(type.base_type)) field->required = required; 185994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // See if there's a default specified. 186040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is('[')) { 186140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 186240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen for (;;) { 186394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen auto key = attribute_; 186440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseProtoKey()); 186540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT('='); 186694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen auto val = attribute_; 186740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseProtoCurliesOrIdent()); 186894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (key == "default") { 186994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Temp: skip non-numeric defaults (enums). 187094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen auto numeric = strpbrk(val.c_str(), "0123456789-+."); 187194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (IsScalar(type.base_type) && numeric == val.c_str()) 187240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen field->value.constant = val; 187394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else if (key == "deprecated") { 187440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen field->deprecated = val == "true"; 187594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 187640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!Is(',')) break; 187740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 187840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } 187940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(']'); 188094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 188194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (anonymous_struct) { 188240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseProtoFields(anonymous_struct, false, oneof)); 188340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is(';')) NEXT(); 188494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else { 188540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(';'); 1886d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen } 1887d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen } 188894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 188940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 189040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 189194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen} 189294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen 189340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseProtoKey() { 189494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (token_ == '(') { 189540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 189694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Skip "(a.b)" style custom attributes. 189740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen while (token_ == '.' || token_ == kTokenIdentifier) NEXT(); 189840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(')'); 189940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen while (Is('.')) { NEXT(); EXPECT(kTokenIdentifier); } 190094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else { 190140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 190294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 190340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 190494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen} 190594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen 190640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseProtoCurliesOrIdent() { 190740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is('{')) { 190840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 190994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen for (int nesting = 1; nesting; ) { 191094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (token_ == '{') nesting++; 191194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen else if (token_ == '}') nesting--; 191240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 191394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 1914d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen } else { 191540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); // Any single token. 1916d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen } 191740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 1918d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen} 1919d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen 192040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseProtoOption() { 192140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 192240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseProtoKey()); 192340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT('='); 192440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseProtoCurliesOrIdent()); 192540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 192694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen} 192794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen 1928d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen// Parse a protobuf type, and map it to the corresponding FlatBuffer one. 192940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseTypeFromProtoType(Type *type) { 193069776b9e7eddd7aa9388f67d06f668e257f02704Wouter van Oortmerssen struct type_lookup { const char *proto_type; BaseType fb_type, element; }; 1931d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen static type_lookup lookup[] = { 193269776b9e7eddd7aa9388f67d06f668e257f02704Wouter van Oortmerssen { "float", BASE_TYPE_FLOAT, BASE_TYPE_NONE }, 193369776b9e7eddd7aa9388f67d06f668e257f02704Wouter van Oortmerssen { "double", BASE_TYPE_DOUBLE, BASE_TYPE_NONE }, 193469776b9e7eddd7aa9388f67d06f668e257f02704Wouter van Oortmerssen { "int32", BASE_TYPE_INT, BASE_TYPE_NONE }, 193569776b9e7eddd7aa9388f67d06f668e257f02704Wouter van Oortmerssen { "int64", BASE_TYPE_LONG, BASE_TYPE_NONE }, 193669776b9e7eddd7aa9388f67d06f668e257f02704Wouter van Oortmerssen { "uint32", BASE_TYPE_UINT, BASE_TYPE_NONE }, 193769776b9e7eddd7aa9388f67d06f668e257f02704Wouter van Oortmerssen { "uint64", BASE_TYPE_ULONG, BASE_TYPE_NONE }, 193869776b9e7eddd7aa9388f67d06f668e257f02704Wouter van Oortmerssen { "sint32", BASE_TYPE_INT, BASE_TYPE_NONE }, 193969776b9e7eddd7aa9388f67d06f668e257f02704Wouter van Oortmerssen { "sint64", BASE_TYPE_LONG, BASE_TYPE_NONE }, 194069776b9e7eddd7aa9388f67d06f668e257f02704Wouter van Oortmerssen { "fixed32", BASE_TYPE_UINT, BASE_TYPE_NONE }, 194169776b9e7eddd7aa9388f67d06f668e257f02704Wouter van Oortmerssen { "fixed64", BASE_TYPE_ULONG, BASE_TYPE_NONE }, 194269776b9e7eddd7aa9388f67d06f668e257f02704Wouter van Oortmerssen { "sfixed32", BASE_TYPE_INT, BASE_TYPE_NONE }, 194369776b9e7eddd7aa9388f67d06f668e257f02704Wouter van Oortmerssen { "sfixed64", BASE_TYPE_LONG, BASE_TYPE_NONE }, 194469776b9e7eddd7aa9388f67d06f668e257f02704Wouter van Oortmerssen { "bool", BASE_TYPE_BOOL, BASE_TYPE_NONE }, 194569776b9e7eddd7aa9388f67d06f668e257f02704Wouter van Oortmerssen { "string", BASE_TYPE_STRING, BASE_TYPE_NONE }, 194669776b9e7eddd7aa9388f67d06f668e257f02704Wouter van Oortmerssen { "bytes", BASE_TYPE_VECTOR, BASE_TYPE_UCHAR }, 194769776b9e7eddd7aa9388f67d06f668e257f02704Wouter van Oortmerssen { nullptr, BASE_TYPE_NONE, BASE_TYPE_NONE } 1948d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen }; 1949d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen for (auto tl = lookup; tl->proto_type; tl++) { 1950d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen if (attribute_ == tl->proto_type) { 195140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen type->base_type = tl->fb_type; 195269776b9e7eddd7aa9388f67d06f668e257f02704Wouter van Oortmerssen type->element = tl->element; 195340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 195440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 1955d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen } 1956d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen } 195740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is('.')) NEXT(); // qualified names may start with a . ? 195840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseTypeIdent(*type)); 195940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 1960d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen} 1961d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen 196213d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra PenkeCheckedError Parser::SkipAnyJsonValue() { 196313d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke switch (token_) { 19648f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen case '{': { 1965a8923222033763f1a74f836c656af19d9f620378Stewart Miles size_t fieldn_outer = 0; 1966a8923222033763f1a74f836c656af19d9f620378Stewart Miles return ParseTableDelimiters(fieldn_outer, nullptr, 1967a8923222033763f1a74f836c656af19d9f620378Stewart Miles [](const std::string &, 1968a8923222033763f1a74f836c656af19d9f620378Stewart Miles size_t &fieldn, const StructDef *, 1969a8923222033763f1a74f836c656af19d9f620378Stewart Miles void *state) -> CheckedError { 1970a8923222033763f1a74f836c656af19d9f620378Stewart Miles auto *parser = static_cast<Parser *>(state); 1971a8923222033763f1a74f836c656af19d9f620378Stewart Miles ECHECK(parser->SkipAnyJsonValue()); 1972a8923222033763f1a74f836c656af19d9f620378Stewart Miles fieldn++; 1973a8923222033763f1a74f836c656af19d9f620378Stewart Miles return NoError(); 1974a8923222033763f1a74f836c656af19d9f620378Stewart Miles }, 1975a8923222033763f1a74f836c656af19d9f620378Stewart Miles this); 19768f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen } 19778f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen case '[': { 19788f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen size_t count = 0; 1979a8923222033763f1a74f836c656af19d9f620378Stewart Miles return ParseVectorDelimiters(count, [](size_t &, 1980a8923222033763f1a74f836c656af19d9f620378Stewart Miles void *state) -> CheckedError { 1981a8923222033763f1a74f836c656af19d9f620378Stewart Miles return static_cast<Parser *>(state)->SkipAnyJsonValue(); 1982a8923222033763f1a74f836c656af19d9f620378Stewart Miles }, 1983a8923222033763f1a74f836c656af19d9f620378Stewart Miles this); 19848f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen } 198513d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke case kTokenStringConstant: 198613d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke case kTokenIntegerConstant: 198713d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke case kTokenFloatConstant: 198803e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen NEXT(); 1989a2b1bfc1075e8e5ae7b347a04cbb796524f2c5c9rouzier break; 199013d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke default: 199103e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen if (IsIdent("true") || IsIdent("false") || IsIdent("null")) { NEXT(); } 199203e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen else return TokenError(); 199313d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke } 199413d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke return NoError(); 199513d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke} 199613d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke 19978f864aad7b875d645236be59ab1037051b12ba10Wouter van OortmerssenCheckedError Parser::ParseFlexBufferValue(flexbuffers::Builder *builder) { 19988f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen switch (token_) { 19998f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen case '{': { 2000a8923222033763f1a74f836c656af19d9f620378Stewart Miles std::pair<Parser *, flexbuffers::Builder *> parser_and_builder_state( 2001a8923222033763f1a74f836c656af19d9f620378Stewart Miles this, builder); 20028f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen auto start = builder->StartMap(); 2003a8923222033763f1a74f836c656af19d9f620378Stewart Miles size_t fieldn_outer = 0; 2004a8923222033763f1a74f836c656af19d9f620378Stewart Miles auto err = ParseTableDelimiters(fieldn_outer, nullptr, 2005a8923222033763f1a74f836c656af19d9f620378Stewart Miles [](const std::string &name, 2006a8923222033763f1a74f836c656af19d9f620378Stewart Miles size_t &fieldn, const StructDef *, 2007a8923222033763f1a74f836c656af19d9f620378Stewart Miles void *state) -> CheckedError { 2008a8923222033763f1a74f836c656af19d9f620378Stewart Miles auto *parser_and_builder = 2009a8923222033763f1a74f836c656af19d9f620378Stewart Miles static_cast<std::pair<Parser *, flexbuffers::Builder *> *>( 2010a8923222033763f1a74f836c656af19d9f620378Stewart Miles state); 2011a8923222033763f1a74f836c656af19d9f620378Stewart Miles auto *parser = parser_and_builder->first; 2012a8923222033763f1a74f836c656af19d9f620378Stewart Miles auto *current_builder = parser_and_builder->second; 2013a8923222033763f1a74f836c656af19d9f620378Stewart Miles current_builder->Key(name); 2014a8923222033763f1a74f836c656af19d9f620378Stewart Miles ECHECK(parser->ParseFlexBufferValue(current_builder)); 2015a8923222033763f1a74f836c656af19d9f620378Stewart Miles fieldn++; 2016a8923222033763f1a74f836c656af19d9f620378Stewart Miles return NoError(); 2017a8923222033763f1a74f836c656af19d9f620378Stewart Miles }, 2018a8923222033763f1a74f836c656af19d9f620378Stewart Miles &parser_and_builder_state); 20198f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen ECHECK(err); 20208f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen builder->EndMap(start); 20218f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen break; 2022cbab26673b99b0a5dff9907fbe08e1efc211f1ffNalinichandra Penke } 20238f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen case '[':{ 20248f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen auto start = builder->StartVector(); 20258f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen size_t count = 0; 2026a8923222033763f1a74f836c656af19d9f620378Stewart Miles std::pair<Parser *, flexbuffers::Builder *> parser_and_builder_state( 2027a8923222033763f1a74f836c656af19d9f620378Stewart Miles this, builder); 2028a8923222033763f1a74f836c656af19d9f620378Stewart Miles ECHECK(ParseVectorDelimiters(count, [](size_t &, 2029a8923222033763f1a74f836c656af19d9f620378Stewart Miles void *state) -> CheckedError { 2030a8923222033763f1a74f836c656af19d9f620378Stewart Miles auto *parser_and_builder = 2031a8923222033763f1a74f836c656af19d9f620378Stewart Miles static_cast<std::pair<Parser *, flexbuffers::Builder *> *>( 2032a8923222033763f1a74f836c656af19d9f620378Stewart Miles state); 2033a8923222033763f1a74f836c656af19d9f620378Stewart Miles return parser_and_builder->first->ParseFlexBufferValue( 2034a8923222033763f1a74f836c656af19d9f620378Stewart Miles parser_and_builder->second); 2035a8923222033763f1a74f836c656af19d9f620378Stewart Miles }, 2036a8923222033763f1a74f836c656af19d9f620378Stewart Miles &parser_and_builder_state)); 20378f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen builder->EndVector(start, false, false); 20388f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen break; 2039cbab26673b99b0a5dff9907fbe08e1efc211f1ffNalinichandra Penke } 20408f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen case kTokenStringConstant: 20418f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen builder->String(attribute_); 20428f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen EXPECT(kTokenStringConstant); 20438f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen break; 20448f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen case kTokenIntegerConstant: 20458f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen builder->Int(StringToInt(attribute_.c_str())); 20468f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen EXPECT(kTokenIntegerConstant); 20478f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen break; 20488f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen case kTokenFloatConstant: 20498f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen builder->Double(strtod(attribute_.c_str(), nullptr)); 20508f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen EXPECT(kTokenFloatConstant); 20518f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen break; 20528f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen default: 205303e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen if (IsIdent("true")) { builder->Bool(true); NEXT(); } 205403e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen else if (IsIdent("false")) { builder->Bool(false); NEXT(); } 205503e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen else if (IsIdent("null")) { builder->Null(); NEXT(); } 205603e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen else return TokenError(); 205713d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke } 205813d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke return NoError(); 205913d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke} 206013d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke 20618f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssenbool Parser::ParseFlexBuffer(const char *source, const char *source_filename, 20628f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen flexbuffers::Builder *builder) { 20638f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen auto ok = !StartParseFile(source, source_filename).Check() && 20648f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen !ParseFlexBufferValue(builder).Check(); 20658f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen if (ok) builder->Finish(); 20668f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen return ok; 206713d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke} 206813d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke 206930642c5a6f0fe2728d5b05cd272880d325c18cf6Wouter van Oortmerssenbool Parser::Parse(const char *source, const char **include_paths, 207030642c5a6f0fe2728d5b05cd272880d325c18cf6Wouter van Oortmerssen const char *source_filename) { 20710e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath return !ParseRoot(source, include_paths, source_filename).Check(); 207240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen} 207340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen 20748f864aad7b875d645236be59ab1037051b12ba10Wouter van OortmerssenCheckedError Parser::StartParseFile(const char *source, const char *source_filename) { 20758f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen file_being_parsed_ = source_filename ? source_filename : ""; 20768f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen source_ = cursor_ = source; 20778f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen line_ = 1; 20788f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen error_.clear(); 20798f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen ECHECK(SkipByteOrderMark()); 20808f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen NEXT(); 20818f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen if (Is(kTokenEof)) 20828f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen return Error("input file is empty"); 20838f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen return NoError(); 20848f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen} 20858f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen 20860e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrathCheckedError Parser::ParseRoot(const char *source, const char **include_paths, 20870e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath const char *source_filename) { 20880e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath ECHECK(DoParse(source, include_paths, source_filename, nullptr)); 20890e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath 20900e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath // Check that all types were defined. 20910e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath for (auto it = structs_.vec.begin(); it != structs_.vec.end(); ++it) { 20920e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath if ((*it)->predecl) { 2093321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen return Error("type referenced but not defined (check namespace): " + 2094321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen (*it)->name); 20950e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath } 20960e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath } 20970e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath 20980e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath // This check has to happen here and not earlier, because only now do we 20990e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath // know for sure what the type of these are. 21000e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath for (auto it = enums_.vec.begin(); it != enums_.vec.end(); ++it) { 21010e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath auto &enum_def = **it; 21020e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath if (enum_def.is_union) { 21030e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath for (auto val_it = enum_def.vals.vec.begin(); 21040e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath val_it != enum_def.vals.vec.end(); 21050e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath ++val_it) { 21060e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath auto &val = **val_it; 210746bb05d95226c72cc85242eee386465860786333Kamil Rojewski if (!SupportsVectorOfUnions() && 21080e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath val.union_type.struct_def && val.union_type.struct_def->fixed) 21090e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath return Error( 21100e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath "only tables can be union elements in the generated language: " 21110e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath + val.name); 21120e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath } 21130e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath } 21140e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath } 21150e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath return NoError(); 21160e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath} 21170e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath 21180e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrathCheckedError Parser::DoParse(const char *source, 21190e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath const char **include_paths, 21200e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath const char *source_filename, 21210e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath const char *include_filename) { 2122df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez if (source_filename && 2123642254bee60e7c7cd793f8f636a9351f883ea97aPavel Kalinnikov included_files_.find(source_filename) == included_files_.end()) { 2124642254bee60e7c7cd793f8f636a9351f883ea97aPavel Kalinnikov included_files_[source_filename] = include_filename ? include_filename : ""; 2125df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez files_included_per_file_[source_filename] = std::set<std::string>(); 2126df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez } 2127df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez if (!include_paths) { 21281e6f8f5b8c4d0407d7db750858e7863e07091958Wouter van Oortmerssen static const char *current_directory[] = { "", nullptr }; 2129df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez include_paths = current_directory; 2130df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez } 2131fea6b525ee57bf61d307abc16ade8d9041a3a01dYonggang Li field_stack_.clear(); 213226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen builder_.Clear(); 213394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Start with a blank namespace just in case this file doesn't have one. 2134321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen current_namespace_ = empty_namespace_; 2135e7e4dc755d98ea33ef8e0dedb86f6cc466a89074Louis-Paul CORDIER 21368f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen ECHECK(StartParseFile(source, source_filename)); 2137e7e4dc755d98ea33ef8e0dedb86f6cc466a89074Louis-Paul CORDIER 213840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // Includes must come before type declarations: 213940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen for (;;) { 214040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // Parse pre-include proto statements if any: 214140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (opts.proto_mode && 214240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen (attribute_ == "option" || attribute_ == "syntax" || 214340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen attribute_ == "package")) { 214440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseProtoDecl()); 214503e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if (IsIdent("native_include")) { 21463f936c5655d2e802db101c73c42ebaab4ed476aaWouter van Oortmerssen NEXT(); 2147a8923222033763f1a74f836c656af19d9f620378Stewart Miles vector_emplace_back(&native_included_files_, attribute_); 21483f936c5655d2e802db101c73c42ebaab4ed476aaWouter van Oortmerssen EXPECT(kTokenStringConstant); 214903e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if (IsIdent("include") || (opts.proto_mode && IsIdent("import"))) { 215040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 215140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (opts.proto_mode && attribute_ == "public") NEXT(); 2152aaf5598a032314767721fead8a0acf9ca37c5e09Wouter van Oortmerssen auto name = flatbuffers::PosixPath(attribute_.c_str()); 215340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenStringConstant); 215440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // Look for the file in include_paths. 215540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen std::string filepath; 215640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen for (auto paths = include_paths; paths && *paths; paths++) { 215740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen filepath = flatbuffers::ConCatPathFileName(*paths, name); 215840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if(FileExists(filepath.c_str())) break; 2159be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen } 216040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (filepath.empty()) 216140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("unable to locate include file: " + name); 216240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (source_filename) 216340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen files_included_per_file_[source_filename].insert(filepath); 2164642254bee60e7c7cd793f8f636a9351f883ea97aPavel Kalinnikov if (included_files_.find(filepath) == included_files_.end()) { 216540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // We found an include file that we have not parsed yet. 216640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // Load it and parse it. 216740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen std::string contents; 216840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!LoadFile(filepath.c_str(), true, &contents)) 216940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("unable to load include file: " + name); 217022743ca45a3f835df423eb608837022a4a57dcc0Wouter van Oortmerssen ECHECK(DoParse(contents.c_str(), include_paths, filepath.c_str(), 217122743ca45a3f835df423eb608837022a4a57dcc0Wouter van Oortmerssen name.c_str())); 217240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // We generally do not want to output code for any included files: 217340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!opts.generate_all) MarkGenerated(); 2174432e7582c65aeb65b582724f601fc3202ecf9017Wouter van Oortmerssen // Reset these just in case the included file had them, and the 2175dca33ddb75a035344cb6ea3e38b9123dcce9b5fdWouter van Oortmerssen // parent doesn't. 2176dca33ddb75a035344cb6ea3e38b9123dcce9b5fdWouter van Oortmerssen root_struct_def_ = nullptr; 2177432e7582c65aeb65b582724f601fc3202ecf9017Wouter van Oortmerssen file_identifier_.clear(); 2178432e7582c65aeb65b582724f601fc3202ecf9017Wouter van Oortmerssen file_extension_.clear(); 217940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // This is the easiest way to continue this file after an include: 218040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // instead of saving and restoring all the state, we simply start the 218140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // file anew. This will cause it to encounter the same include 218240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // statement again, but this time it will skip it, because it was 218340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // entered into included_files_. 218440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // This is recursive, but only go as deep as the number of include 218540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // statements. 218622743ca45a3f835df423eb608837022a4a57dcc0Wouter van Oortmerssen return DoParse(source, include_paths, source_filename, include_filename); 218726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 218840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(';'); 218940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } else { 219040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen break; 219126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 219240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } 219340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // Now parse all other kinds of declarations: 219440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen while (token_ != kTokenEof) { 219540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (opts.proto_mode) { 219640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseProtoDecl()); 219703e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if (IsIdent("namespace")) { 219840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseNamespace()); 219940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } else if (token_ == '{') { 220040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!root_struct_def_) 220140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("no root type set to parse json with"); 220240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (builder_.GetSize()) { 220340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("cannot have more than one json object in a file"); 220494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 220540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen uoffset_t toff; 220640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseTable(*root_struct_def_, nullptr, &toff)); 220740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen builder_.Finish(Offset<Table>(toff), 220840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen file_identifier_.length() ? file_identifier_.c_str() : nullptr); 220903e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if (IsIdent("enum")) { 221040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseEnum(false, nullptr)); 221103e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if (IsIdent("union")) { 221240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseEnum(true, nullptr)); 221303e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if (IsIdent("root_type")) { 221440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 221540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen auto root_type = attribute_; 221640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 221740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseNamespacing(&root_type, nullptr)); 221840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!SetRootType(root_type.c_str())) 221940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("unknown root type: " + root_type); 222040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (root_struct_def_->fixed) 222140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("root type must be a table"); 222240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(';'); 222303e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if (IsIdent("file_identifier")) { 222440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 222540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen file_identifier_ = attribute_; 222640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenStringConstant); 222740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (file_identifier_.length() != 222840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen FlatBufferBuilder::kFileIdentifierLength) 222940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("file_identifier must be exactly " + 223040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NumToString(FlatBufferBuilder::kFileIdentifierLength) + 223140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen " characters"); 223240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(';'); 223303e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if (IsIdent("file_extension")) { 223440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 223540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen file_extension_ = attribute_; 223640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenStringConstant); 223740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(';'); 223803e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if(IsIdent("include")) { 223940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("includes must come before declarations"); 224003e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if(IsIdent("attribute")) { 224140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 224240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen auto name = attribute_; 224340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenStringConstant); 224440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(';'); 224572fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen known_attributes_[name] = false; 224603e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if (IsIdent("rpc_service")) { 22471a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen ECHECK(ParseService()); 224840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } else { 224940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseDecl()); 225026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 225140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } 225240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 225326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 225426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 2255df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinezstd::set<std::string> Parser::GetIncludedFilesRecursive( 2256df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez const std::string &file_name) const { 2257df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez std::set<std::string> included_files; 2258df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez std::list<std::string> to_process; 2259df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez 2260df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez if (file_name.empty()) return included_files; 2261df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez to_process.push_back(file_name); 2262df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez 2263df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez while (!to_process.empty()) { 2264df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez std::string current = to_process.front(); 2265df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez to_process.pop_front(); 2266df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez included_files.insert(current); 2267df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez 2268a8923222033763f1a74f836c656af19d9f620378Stewart Miles // Workaround the lack of const accessor in C++98 maps. 2269a8923222033763f1a74f836c656af19d9f620378Stewart Miles auto &new_files = 2270a8923222033763f1a74f836c656af19d9f620378Stewart Miles (*const_cast<std::map<std::string, std::set<std::string>> *>( 2271a8923222033763f1a74f836c656af19d9f620378Stewart Miles &files_included_per_file_))[current]; 2272df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez for (auto it = new_files.begin(); it != new_files.end(); ++it) { 2273df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez if (included_files.find(*it) == included_files.end()) 2274df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez to_process.push_back(*it); 2275df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez } 2276df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez } 2277df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez 2278df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez return included_files; 2279df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez} 2280df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez 228181312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen// Schema serialization functionality: 228281312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen 2283b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penketemplate<typename T> bool compareName(const T* a, const T* b) { 2284df0991b7ded0533554d3665e782273b6c8736376Xun Liu return a->defined_namespace->GetFullyQualifiedName(a->name) 2285df0991b7ded0533554d3665e782273b6c8736376Xun Liu < b->defined_namespace->GetFullyQualifiedName(b->name); 2286b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke} 2287b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke 228881312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssentemplate<typename T> void AssignIndices(const std::vector<T *> &defvec) { 228981312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen // Pre-sort these vectors, such that we can set the correct indices for them. 229081312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen auto vec = defvec; 2291b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke std::sort(vec.begin(), vec.end(), compareName<T>); 229281312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen for (int i = 0; i < static_cast<int>(vec.size()); i++) vec[i]->index = i; 229381312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen} 229481312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen 229581312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssenvoid Parser::Serialize() { 229681312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen builder_.Clear(); 229781312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen AssignIndices(structs_.vec); 229881312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen AssignIndices(enums_.vec); 229981312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen std::vector<Offset<reflection::Object>> object_offsets; 230081312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen for (auto it = structs_.vec.begin(); it != structs_.vec.end(); ++it) { 230172fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen auto offset = (*it)->Serialize(&builder_, *this); 230281312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen object_offsets.push_back(offset); 230381312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen (*it)->serialized_location = offset.o; 230481312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen } 230581312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen std::vector<Offset<reflection::Enum>> enum_offsets; 230681312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen for (auto it = enums_.vec.begin(); it != enums_.vec.end(); ++it) { 230772fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen auto offset = (*it)->Serialize(&builder_, *this); 230881312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen enum_offsets.push_back(offset); 230981312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen (*it)->serialized_location = offset.o; 231081312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen } 231181312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen auto schema_offset = reflection::CreateSchema( 231281312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen builder_, 231381312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen builder_.CreateVectorOfSortedTables(&object_offsets), 231481312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen builder_.CreateVectorOfSortedTables(&enum_offsets), 231581312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen builder_.CreateString(file_identifier_), 231681312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen builder_.CreateString(file_extension_), 231736c7e9a9625b65332e16615897f1ef9c1b99e203Wouter van Oortmerssen root_struct_def_ 231836c7e9a9625b65332e16615897f1ef9c1b99e203Wouter van Oortmerssen ? root_struct_def_->serialized_location 231936c7e9a9625b65332e16615897f1ef9c1b99e203Wouter van Oortmerssen : 0); 232081312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen builder_.Finish(schema_offset, reflection::SchemaIdentifier()); 232181312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen} 232281312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen 232372fc45aa6acbc11052c6baa462fac26c5075392aWouter van OortmerssenOffset<reflection::Object> StructDef::Serialize(FlatBufferBuilder *builder, 232472fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen const Parser &parser) const { 232581312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen std::vector<Offset<reflection::Field>> field_offsets; 232681312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen for (auto it = fields.vec.begin(); it != fields.vec.end(); ++it) { 2327622b8d05cf69cc26babc6a043d1f7a4153755652Wouter van Oortmerssen field_offsets.push_back( 2328622b8d05cf69cc26babc6a043d1f7a4153755652Wouter van Oortmerssen (*it)->Serialize(builder, 232972fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen static_cast<uint16_t>(it - fields.vec.begin()), parser)); 233081312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen } 2331df0991b7ded0533554d3665e782273b6c8736376Xun Liu auto qualified_name = defined_namespace->GetFullyQualifiedName(name); 233281312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen return reflection::CreateObject(*builder, 2333df0991b7ded0533554d3665e782273b6c8736376Xun Liu builder->CreateString(qualified_name), 233481312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen builder->CreateVectorOfSortedTables( 233581312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen &field_offsets), 2336cb2b2be54eb52fb009f30f5ca300165a95fa5df6Wouter van Oortmerssen fixed, 2337cb2b2be54eb52fb009f30f5ca300165a95fa5df6Wouter van Oortmerssen static_cast<int>(minalign), 233872fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen static_cast<int>(bytesize), 23391fb6b9ee6f817befae08f39549d5bd80de3931ccWouter van Oortmerssen SerializeAttributes(builder, parser), 23401fb6b9ee6f817befae08f39549d5bd80de3931ccWouter van Oortmerssen parser.opts.binary_schema_comments 23411fb6b9ee6f817befae08f39549d5bd80de3931ccWouter van Oortmerssen ? builder->CreateVectorOfStrings( 23421fb6b9ee6f817befae08f39549d5bd80de3931ccWouter van Oortmerssen doc_comment) 23431fb6b9ee6f817befae08f39549d5bd80de3931ccWouter van Oortmerssen : 0); 234481312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen} 234581312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen 234681312c21281430449aef20f7a71ad9e0962791d3Wouter van OortmerssenOffset<reflection::Field> FieldDef::Serialize(FlatBufferBuilder *builder, 234772fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen uint16_t id, 234872fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen const Parser &parser) const { 234981312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen return reflection::CreateField(*builder, 235081312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen builder->CreateString(name), 235181312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen value.type.Serialize(builder), 235281312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen id, 235381312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen value.offset, 235481312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen IsInteger(value.type.base_type) 235581312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen ? StringToInt(value.constant.c_str()) 235681312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen : 0, 235781312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen IsFloat(value.type.base_type) 235881312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen ? strtod(value.constant.c_str(), nullptr) 235981312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen : 0.0, 236081312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen deprecated, 236181312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen required, 236272fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen key, 23631fb6b9ee6f817befae08f39549d5bd80de3931ccWouter van Oortmerssen SerializeAttributes(builder, parser), 23641fb6b9ee6f817befae08f39549d5bd80de3931ccWouter van Oortmerssen parser.opts.binary_schema_comments 23651fb6b9ee6f817befae08f39549d5bd80de3931ccWouter van Oortmerssen ? builder->CreateVectorOfStrings(doc_comment) 23661fb6b9ee6f817befae08f39549d5bd80de3931ccWouter van Oortmerssen : 0); 236781312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen // TODO: value.constant is almost always "0", we could save quite a bit of 236881312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen // space by sharing it. Same for common values of value.type. 236981312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen} 237081312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen 237172fc45aa6acbc11052c6baa462fac26c5075392aWouter van OortmerssenOffset<reflection::Enum> EnumDef::Serialize(FlatBufferBuilder *builder, 237272fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen const Parser &parser) const { 237381312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen std::vector<Offset<reflection::EnumVal>> enumval_offsets; 237481312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen for (auto it = vals.vec.begin(); it != vals.vec.end(); ++it) { 237581312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen enumval_offsets.push_back((*it)->Serialize(builder)); 237681312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen } 2377df0991b7ded0533554d3665e782273b6c8736376Xun Liu auto qualified_name = defined_namespace->GetFullyQualifiedName(name); 237881312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen return reflection::CreateEnum(*builder, 2379df0991b7ded0533554d3665e782273b6c8736376Xun Liu builder->CreateString(qualified_name), 238081312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen builder->CreateVector(enumval_offsets), 238181312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen is_union, 238272fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen underlying_type.Serialize(builder), 23831fb6b9ee6f817befae08f39549d5bd80de3931ccWouter van Oortmerssen SerializeAttributes(builder, parser), 23841fb6b9ee6f817befae08f39549d5bd80de3931ccWouter van Oortmerssen parser.opts.binary_schema_comments 23851fb6b9ee6f817befae08f39549d5bd80de3931ccWouter van Oortmerssen ? builder->CreateVectorOfStrings(doc_comment) 23861fb6b9ee6f817befae08f39549d5bd80de3931ccWouter van Oortmerssen : 0); 238781312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen} 238881312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen 238981312c21281430449aef20f7a71ad9e0962791d3Wouter van OortmerssenOffset<reflection::EnumVal> EnumVal::Serialize(FlatBufferBuilder *builder) const 239081312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen { 239181312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen return reflection::CreateEnumVal(*builder, 239281312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen builder->CreateString(name), 239381312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen value, 2394b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen union_type.struct_def 2395b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen ? union_type.struct_def-> 2396b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen serialized_location 2397b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen : 0, 2398b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen union_type.Serialize(builder)); 239981312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen} 240081312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen 240181312c21281430449aef20f7a71ad9e0962791d3Wouter van OortmerssenOffset<reflection::Type> Type::Serialize(FlatBufferBuilder *builder) const { 240281312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen return reflection::CreateType(*builder, 240381312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen static_cast<reflection::BaseType>(base_type), 240481312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen static_cast<reflection::BaseType>(element), 240581312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen struct_def ? struct_def->index : 240681312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen (enum_def ? enum_def->index : -1)); 240781312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen} 240881312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen 240972fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssenflatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset< 241072fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen reflection::KeyValue>>> 241172fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen Definition::SerializeAttributes(FlatBufferBuilder *builder, 241272fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen const Parser &parser) const { 241372fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen std::vector<flatbuffers::Offset<reflection::KeyValue>> attrs; 2414e92ae5199d52fd59540a800bec7eef46cd778257Wouter van Oortmerssen for (auto kv = attributes.dict.begin(); kv != attributes.dict.end(); ++kv) { 2415e92ae5199d52fd59540a800bec7eef46cd778257Wouter van Oortmerssen auto it = parser.known_attributes_.find(kv->first); 241672fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen assert(it != parser.known_attributes_.end()); 241772fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen if (!it->second) { // Custom attribute. 241872fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen attrs.push_back( 2419e92ae5199d52fd59540a800bec7eef46cd778257Wouter van Oortmerssen reflection::CreateKeyValue(*builder, builder->CreateString(kv->first), 242072fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen builder->CreateString( 2421e92ae5199d52fd59540a800bec7eef46cd778257Wouter van Oortmerssen kv->second->constant))); 242272fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen } 242372fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen } 242472fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen if (attrs.size()) { 242572fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen return builder->CreateVectorOfSortedTables(&attrs); 242672fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen } else { 242772fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen return 0; 242872fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen } 242972fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen} 243072fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen 243105b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssenstd::string Parser::ConformTo(const Parser &base) { 243205b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen for (auto sit = structs_.vec.begin(); sit != structs_.vec.end(); ++sit) { 243305b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen auto &struct_def = **sit; 243405b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen auto qualified_name = 243505b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen struct_def.defined_namespace->GetFullyQualifiedName(struct_def.name); 243605b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen auto struct_def_base = base.structs_.Lookup(qualified_name); 243705b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen if (!struct_def_base) continue; 243805b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen for (auto fit = struct_def.fields.vec.begin(); 243905b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen fit != struct_def.fields.vec.end(); ++fit) { 244005b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen auto &field = **fit; 244105b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen auto field_base = struct_def_base->fields.Lookup(field.name); 244205b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen if (field_base) { 244305b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen if (field.value.offset != field_base->value.offset) 244405b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen return "offsets differ for field: " + field.name; 244505b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen if (field.value.constant != field_base->value.constant) 244605b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen return "defaults differ for field: " + field.name; 244705b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen if (!EqualByName(field.value.type, field_base->value.type)) 244805b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen return "types differ for field: " + field.name; 244905b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen } else { 245005b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen // Doesn't have to exist, deleting fields is fine. 245105b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen // But we should check if there is a field that has the same offset 245205b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen // but is incompatible (in the case of field renaming). 245305b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen for (auto fbit = struct_def_base->fields.vec.begin(); 245405b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen fbit != struct_def_base->fields.vec.end(); ++fbit) { 245505b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen field_base = *fbit; 245605b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen if (field.value.offset == field_base->value.offset) { 245705b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen if (!EqualByName(field.value.type, field_base->value.type)) 245805b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen return "field renamed to different type: " + field.name; 245905b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen break; 246005b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen } 246105b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen } 246205b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen } 246305b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen } 246405b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen } 246505b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen for (auto eit = enums_.vec.begin(); eit != enums_.vec.end(); ++eit) { 246605b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen auto &enum_def = **eit; 246705b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen auto qualified_name = 246805b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen enum_def.defined_namespace->GetFullyQualifiedName(enum_def.name); 246905b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen auto enum_def_base = base.enums_.Lookup(qualified_name); 247005b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen if (!enum_def_base) continue; 247105b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen for (auto evit = enum_def.vals.vec.begin(); 247205b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen evit != enum_def.vals.vec.end(); ++evit) { 247305b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen auto &enum_val = **evit; 247405b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen auto enum_val_base = enum_def_base->vals.Lookup(enum_val.name); 247505b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen if (enum_val_base) { 247605b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen if (enum_val.value != enum_val_base->value) 247705b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen return "values differ for enum: " + enum_val.name; 247805b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen } 247905b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen } 248005b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen } 248105b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen return ""; 248205b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen} 248305b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen 248426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} // namespace flatbuffers 2485