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#include <math.h> 22d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen 2326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen#include "flatbuffers/idl.h" 2426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen#include "flatbuffers/util.h" 2526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 2626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssennamespace flatbuffers { 2726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 2885b131a719b3ca554a6cf4840f8ec27feb60ec07Bastien Brunnensteinconst double kPi = 3.14159265358979323846; 2985b131a719b3ca554a6cf4840f8ec27feb60ec07Bastien Brunnenstein 3026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenconst char *const kTypeNames[] = { 3103e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen #define FLATBUFFERS_TD(ENUM, IDLTYPE, \ 32f2b3705c2c62c40afdef96f73f0aeaf32b4c8e0eMikkelFJ CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \ 3348dfc69ee613a176f13b04c2310adb7a08fe6737rw IDLTYPE, 3426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) 3526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen #undef FLATBUFFERS_TD 3626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen nullptr 3726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen}; 3826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 3926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenconst char kTypeSizes[] = { 4003e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen #define FLATBUFFERS_TD(ENUM, IDLTYPE, \ 41f2b3705c2c62c40afdef96f73f0aeaf32b4c8e0eMikkelFJ CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \ 42557c88c0396220e79e9a43c07f8393a5c68b739dWouter van Oortmerssen sizeof(CTYPE), 4326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) 4426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen #undef FLATBUFFERS_TD 4526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen}; 4626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 4781312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen// The enums in the reflection schema should match the ones we use internally. 4881312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen// Compare the last element to check if these go out of sync. 4981312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssenstatic_assert(BASE_TYPE_UNION == 50622b8d05cf69cc26babc6a043d1f7a4153755652Wouter van Oortmerssen static_cast<BaseType>(reflection::Union), 5181312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen "enums don't match"); 5281312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen 53451272b61840a3c2b12edeb23b18c9bd0b2aa508Wouter van Oortmerssen// Any parsing calls have to be wrapped in this macro, which automates 54451272b61840a3c2b12edeb23b18c9bd0b2aa508Wouter van Oortmerssen// handling of recursive error checking a bit. It will check the received 55451272b61840a3c2b12edeb23b18c9bd0b2aa508Wouter van Oortmerssen// CheckedError object, and return straight away on error. 5640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen#define ECHECK(call) { auto ce = (call); if (ce.Check()) return ce; } 57451272b61840a3c2b12edeb23b18c9bd0b2aa508Wouter van Oortmerssen 58451272b61840a3c2b12edeb23b18c9bd0b2aa508Wouter van Oortmerssen// These two functions are called hundreds of times below, so define a short 59451272b61840a3c2b12edeb23b18c9bd0b2aa508Wouter van Oortmerssen// form: 6040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen#define NEXT() ECHECK(Next()) 6140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen#define EXPECT(tok) ECHECK(Expect(tok)) 6240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen 63f6416d847186802e03d2fa3c05963ec377c146fcBen Hamiltonstatic bool ValidateUTF8(const std::string &str) { 64f6416d847186802e03d2fa3c05963ec377c146fcBen Hamilton const char *s = &str[0]; 65f6416d847186802e03d2fa3c05963ec377c146fcBen Hamilton const char * const sEnd = s + str.length(); 66f6416d847186802e03d2fa3c05963ec377c146fcBen Hamilton while (s < sEnd) { 67f6416d847186802e03d2fa3c05963ec377c146fcBen Hamilton if (FromUTF8(&s) < 0) { 68f6416d847186802e03d2fa3c05963ec377c146fcBen Hamilton return false; 69f6416d847186802e03d2fa3c05963ec377c146fcBen Hamilton } 70f6416d847186802e03d2fa3c05963ec377c146fcBen Hamilton } 71f6416d847186802e03d2fa3c05963ec377c146fcBen Hamilton return true; 72f6416d847186802e03d2fa3c05963ec377c146fcBen Hamilton} 73f6416d847186802e03d2fa3c05963ec377c146fcBen Hamilton 749c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssenvoid Parser::Message(const std::string &msg) { 7540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen error_ = file_being_parsed_.length() ? AbsolutePath(file_being_parsed_) : ""; 7640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen #ifdef _WIN32 7740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen error_ += "(" + NumToString(line_) + ")"; // MSVC alike 7840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen #else 7940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (file_being_parsed_.length()) error_ += ":"; 8040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen error_ += NumToString(line_) + ":0"; // gcc alike 8140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen #endif 829c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen error_ += ": " + msg; 839c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen} 849c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen 859c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssenvoid Parser::Warning(const std::string &msg) { 869c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen Message("warning: " + msg); 879c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen} 889c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen 899c3920d0ab90e9442759c6b41c28af577759a692Wouter van OortmerssenCheckedError Parser::Error(const std::string &msg) { 909c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen Message("error: " + msg); 9140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return CheckedError(true); 9226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 9326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 9440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmersseninline CheckedError NoError() { return CheckedError(false); } 9540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen 96a07f0d428d1175ae52b2f91357f535927c9d6287Jason Stubbsinline std::string OutOfRangeErrorMsg(int64_t val, const std::string &op, 97a07f0d428d1175ae52b2f91357f535927c9d6287Jason Stubbs int64_t limit) { 98a07f0d428d1175ae52b2f91357f535927c9d6287Jason Stubbs const std::string cause = NumToString(val) + op + NumToString(limit); 99a07f0d428d1175ae52b2f91357f535927c9d6287Jason Stubbs return "constant does not fit (" + cause + ")"; 100a07f0d428d1175ae52b2f91357f535927c9d6287Jason Stubbs} 101a07f0d428d1175ae52b2f91357f535927c9d6287Jason Stubbs 10226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen// Ensure that integer values we parse fit inside the declared integer type. 103a07f0d428d1175ae52b2f91357f535927c9d6287Jason StubbsCheckedError Parser::CheckInRange(int64_t val, int64_t min, int64_t max) { 104a07f0d428d1175ae52b2f91357f535927c9d6287Jason Stubbs if (val < min) 105a07f0d428d1175ae52b2f91357f535927c9d6287Jason Stubbs return Error(OutOfRangeErrorMsg(val, " < ", min)); 106a07f0d428d1175ae52b2f91357f535927c9d6287Jason Stubbs else if (val > max) 107a07f0d428d1175ae52b2f91357f535927c9d6287Jason Stubbs return Error(OutOfRangeErrorMsg(val, " > ", max)); 108a07f0d428d1175ae52b2f91357f535927c9d6287Jason Stubbs else 109a07f0d428d1175ae52b2f91357f535927c9d6287Jason Stubbs return NoError(); 11026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 11126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 11226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen// atot: templated version of atoi/atof: convert a string to an instance of T. 11340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssentemplate<typename T> inline CheckedError atot(const char *s, Parser &parser, 11440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen T *val) { 11540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen int64_t i = StringToInt(s); 116a8923222033763f1a74f836c656af19d9f620378Stewart Miles const int64_t min = flatbuffers::numeric_limits<T>::min(); 117a8923222033763f1a74f836c656af19d9f620378Stewart Miles const int64_t max = flatbuffers::numeric_limits<T>::max(); 118a07f0d428d1175ae52b2f91357f535927c9d6287Jason Stubbs ECHECK(parser.CheckInRange(i, min, max)); 11940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen *val = (T)i; 12040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 12126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 12229574282a283ddc7904d096d27b783b794da7e91Wouter van Oortmerssentemplate<> inline CheckedError atot<uint64_t>(const char *s, Parser &parser, 12329574282a283ddc7904d096d27b783b794da7e91Wouter van Oortmerssen uint64_t *val) { 12429574282a283ddc7904d096d27b783b794da7e91Wouter van Oortmerssen (void)parser; 12529574282a283ddc7904d096d27b783b794da7e91Wouter van Oortmerssen *val = StringToUInt(s); 12629574282a283ddc7904d096d27b783b794da7e91Wouter van Oortmerssen return NoError(); 12729574282a283ddc7904d096d27b783b794da7e91Wouter van Oortmerssen} 12840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssentemplate<> inline CheckedError atot<bool>(const char *s, Parser &parser, 12940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen bool *val) { 13040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen (void)parser; 13140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen *val = 0 != atoi(s); 13240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 13326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 13440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssentemplate<> inline CheckedError atot<float>(const char *s, Parser &parser, 13540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen float *val) { 13640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen (void)parser; 13740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen *val = static_cast<float>(strtod(s, nullptr)); 13840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 13926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 14040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssentemplate<> inline CheckedError atot<double>(const char *s, Parser &parser, 14140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen double *val) { 14240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen (void)parser; 14340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen *val = strtod(s, nullptr); 14440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 14526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 14626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 14740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssentemplate<> inline CheckedError atot<Offset<void>>(const char *s, Parser &parser, 14840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen Offset<void> *val) { 14940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen (void)parser; 15040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen *val = Offset<void>(atoi(s)); 15140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 15226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 15326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 15494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssenstd::string Namespace::GetFullyQualifiedName(const std::string &name, 15594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen size_t max_components) const { 15694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Early exit if we don't have a defined namespace. 15794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (components.size() == 0 || !max_components) { 15894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen return name; 15994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 16094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen std::stringstream stream; 16194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen for (size_t i = 0; i < std::min(components.size(), max_components); 16294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen i++) { 16394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (i) { 16494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen stream << "."; 16594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 16694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen stream << components[i]; 16794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 1688c1a723ba55d1574590eba801d64afab9c49e017Wouter van Oortmerssen if (name.length()) stream << "." << name; 16994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen return stream.str(); 17094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen} 17194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen 17226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen// Declare tokens we'll use. Single character tokens are represented by their 17326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen// ascii character code (e.g. '{'), others above 256. 17426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen#define FLATBUFFERS_GEN_TOKENS(TD) \ 17526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen TD(Eof, 256, "end of file") \ 17626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen TD(StringConstant, 257, "string constant") \ 17726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen TD(IntegerConstant, 258, "integer constant") \ 17826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen TD(FloatConstant, 259, "float constant") \ 17903e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen TD(Identifier, 260, "identifier") 1808f80fecc445cb733615ad0186358d4e3789ab377Wouter van Oortmerssen#ifdef __GNUC__ 1818f80fecc445cb733615ad0186358d4e3789ab377Wouter van Oortmerssen__extension__ // Stop GCC complaining about trailing comma with -Wpendantic. 1828f80fecc445cb733615ad0186358d4e3789ab377Wouter van Oortmerssen#endif 18326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenenum { 18475349ae8c39d01e7e2b5779a18ace750c08e2fd9Wouter van Oortmerssen #define FLATBUFFERS_TOKEN(NAME, VALUE, STRING) kToken ## NAME = VALUE, 18526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen FLATBUFFERS_GEN_TOKENS(FLATBUFFERS_TOKEN) 18626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen #undef FLATBUFFERS_TOKEN 18726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen}; 18826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 18926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenstatic std::string TokenToString(int t) { 19026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen static const char *tokens[] = { 19126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen #define FLATBUFFERS_TOKEN(NAME, VALUE, STRING) STRING, 19226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen FLATBUFFERS_GEN_TOKENS(FLATBUFFERS_TOKEN) 19326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen #undef FLATBUFFERS_TOKEN 19403e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen #define FLATBUFFERS_TD(ENUM, IDLTYPE, \ 195f2b3705c2c62c40afdef96f73f0aeaf32b4c8e0eMikkelFJ CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \ 19648dfc69ee613a176f13b04c2310adb7a08fe6737rw IDLTYPE, 19726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) 19826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen #undef FLATBUFFERS_TD 19926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen }; 20026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (t < 256) { // A single ascii char token. 20126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen std::string s; 2028e40902d5284ac479baea5a8ba5eeb31c8edb1a9Wouter van Oortmerssen s.append(1, static_cast<char>(t)); 20326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen return s; 20426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else { // Other tokens. 20526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen return tokens[t - 256]; 20626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 20726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 20826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 20994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssenstd::string Parser::TokenToStringId(int t) { 21003e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen return t == kTokenIdentifier ? attribute_ : TokenToString(t); 21194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen} 21294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen 213ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen// Parses exactly nibbles worth of hex digits into a number, or error. 21429574282a283ddc7904d096d27b783b794da7e91Wouter van OortmerssenCheckedError Parser::ParseHexNum(int nibbles, uint64_t *val) { 215ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen for (int i = 0; i < nibbles; i++) 21630013b4ff80dd7d4fde56e1b2b8b988feed6437fChris Pickett if (!isxdigit(static_cast<const unsigned char>(cursor_[i]))) 21740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("escape code must be followed by " + NumToString(nibbles) + 21840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen " hex digits"); 2197cf74cb8644262f8ca02d69705bbc394d66514ceHiroshi Matsunaga std::string target(cursor_, cursor_ + nibbles); 220b6ba322a0411925757196a1ca6f3a1a87f46831eSahil Jain *val = StringToUInt(target.c_str(), nullptr, 16); 221ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen cursor_ += nibbles; 22240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 223ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen} 224ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen 225cbe8747b59d143ad2bfe73ecc838b711f8102886Oli Wilkinson <OliCheckedError Parser::SkipByteOrderMark() { 22603e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen if (static_cast<unsigned char>(*cursor_) != 0xef) 22703e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen return NoError(); 228cbe8747b59d143ad2bfe73ecc838b711f8102886Oli Wilkinson <Oli cursor_++; 22903e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen if (static_cast<unsigned char>(*cursor_) != 0xbb) 23003e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen return Error("invalid utf-8 byte order mark"); 231f6330ab8f137871f786fc72a7700b54da21f0603Wouter van Oortmerssen cursor_++; 23203e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen if (static_cast<unsigned char>(*cursor_) != 0xbf) 23303e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen return Error("invalid utf-8 byte order mark"); 234f6330ab8f137871f786fc72a7700b54da21f0603Wouter van Oortmerssen cursor_++; 235cbe8747b59d143ad2bfe73ecc838b711f8102886Oli Wilkinson <Oli return NoError(); 236cbe8747b59d143ad2bfe73ecc838b711f8102886Oli Wilkinson <Oli} 237cbe8747b59d143ad2bfe73ecc838b711f8102886Oli Wilkinson <Oli 238fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssenbool IsIdentifierStart(char c) { 239fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen return isalpha(static_cast<unsigned char>(c)) || c == '_'; 240fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen} 241fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen 24240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::Next() { 24326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen doc_comment_.clear(); 24426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen bool seen_newline = false; 24594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen attribute_.clear(); 24626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen for (;;) { 24726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen char c = *cursor_++; 24826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen token_ = c; 24926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen switch (c) { 25040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen case '\0': cursor_--; token_ = kTokenEof; return NoError(); 25126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case ' ': case '\r': case '\t': break; 25226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case '\n': line_++; seen_newline = true; break; 25340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen case '{': case '}': case '(': case ')': case '[': case ']': 25440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen case ',': case ':': case ';': case '=': return NoError(); 25526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case '.': 25630013b4ff80dd7d4fde56e1b2b8b988feed6437fChris Pickett if(!isdigit(static_cast<const unsigned char>(*cursor_))) return NoError(); 25740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("floating point constant can\'t start with \".\""); 25826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case '\"': 2596704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield case '\'': { 2606704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield int unicode_high_surrogate = -1; 2616704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield 26294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen while (*cursor_ != c) { 26326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (*cursor_ < ' ' && *cursor_ >= 0) 26440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("illegal character in string constant"); 26526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (*cursor_ == '\\') { 26626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen cursor_++; 2676704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield if (unicode_high_surrogate != -1 && 2686704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield *cursor_ != 'u') { 2696704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield return Error( 2706704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield "illegal Unicode sequence (unpaired high surrogate)"); 2716704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield } 27226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen switch (*cursor_) { 27326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case 'n': attribute_ += '\n'; cursor_++; break; 27426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case 't': attribute_ += '\t'; cursor_++; break; 27526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case 'r': attribute_ += '\r'; cursor_++; break; 276ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen case 'b': attribute_ += '\b'; cursor_++; break; 277ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen case 'f': attribute_ += '\f'; cursor_++; break; 27826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case '\"': attribute_ += '\"'; cursor_++; break; 27994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen case '\'': attribute_ += '\''; cursor_++; break; 28026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case '\\': attribute_ += '\\'; cursor_++; break; 281ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen case '/': attribute_ += '/'; cursor_++; break; 282ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen case 'x': { // Not in the JSON standard 283ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen cursor_++; 28429574282a283ddc7904d096d27b783b794da7e91Wouter van Oortmerssen uint64_t val; 28540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseHexNum(2, &val)); 28640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen attribute_ += static_cast<char>(val); 287ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen break; 288ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen } 289ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen case 'u': { 290ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen cursor_++; 29129574282a283ddc7904d096d27b783b794da7e91Wouter van Oortmerssen uint64_t val; 29240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseHexNum(4, &val)); 2936704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield if (val >= 0xD800 && val <= 0xDBFF) { 2946704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield if (unicode_high_surrogate != -1) { 2956704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield return Error( 2966704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield "illegal Unicode sequence (multiple high surrogates)"); 2976704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield } else { 298e92ae5199d52fd59540a800bec7eef46cd778257Wouter van Oortmerssen unicode_high_surrogate = static_cast<int>(val); 2996704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield } 3006704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield } else if (val >= 0xDC00 && val <= 0xDFFF) { 3016704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield if (unicode_high_surrogate == -1) { 3026704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield return Error( 3036704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield "illegal Unicode sequence (unpaired low surrogate)"); 3046704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield } else { 3056704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield int code_point = 0x10000 + 3066704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield ((unicode_high_surrogate & 0x03FF) << 10) + 3076704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield (val & 0x03FF); 3086704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield ToUTF8(code_point, &attribute_); 3096704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield unicode_high_surrogate = -1; 3106704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield } 3116704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield } else { 3126704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield if (unicode_high_surrogate != -1) { 3136704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield return Error( 3146704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield "illegal Unicode sequence (unpaired high surrogate)"); 3156704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield } 3166704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield ToUTF8(static_cast<int>(val), &attribute_); 3176704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield } 318ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen break; 319ebac1e1940b16e096e500ae95381706397d86feeWouter van Oortmerssen } 32040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen default: return Error("unknown escape code in string constant"); 32126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 32226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else { // printable chars + UTF-8 bytes 3236704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield if (unicode_high_surrogate != -1) { 3246704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield return Error( 3256704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield "illegal Unicode sequence (unpaired high surrogate)"); 3266704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield } 32726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen attribute_ += *cursor_++; 32826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 32926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 3306704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield if (unicode_high_surrogate != -1) { 3316704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield return Error( 3326704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield "illegal Unicode sequence (unpaired high surrogate)"); 3336704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield } 33426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen cursor_++; 335f6416d847186802e03d2fa3c05963ec377c146fcBen Hamilton if (!opts.allow_non_utf8 && !ValidateUTF8(attribute_)) { 336f6416d847186802e03d2fa3c05963ec377c146fcBen Hamilton return Error("illegal UTF-8 sequence"); 337f6416d847186802e03d2fa3c05963ec377c146fcBen Hamilton } 33826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen token_ = kTokenStringConstant; 33940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 3406704b19db65727d9afbc74e92733516693df9b18Ben Gertzfield } 34126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case '/': 34226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (*cursor_ == '/') { 34326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen const char *start = ++cursor_; 344a8d6962ac2fbf5075ee5f58877d488eb74ed32dfMormegil while (*cursor_ && *cursor_ != '\n' && *cursor_ != '\r') cursor_++; 34526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (*start == '/') { // documentation comment 34607d5965c812fa5e82dc4d3eb32b37540b7c91598Zbigniew Mandziejewicz if (cursor_ != source_ && !seen_newline) 34740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error( 34840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen "a documentation comment should be on a line on its own"); 349730c0cadde2302efa1487d672a1e2f53680ce2eaGabriel Martinez doc_comment_.push_back(std::string(start + 1, cursor_)); 35026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 35126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen break; 35294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else if (*cursor_ == '*') { 35394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen cursor_++; 35494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // TODO: make nested. 35594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen while (*cursor_ != '*' || cursor_[1] != '/') { 356ab51b030939e02e55cac6f9e779d8696013819a9Wouter van Oortmerssen if (*cursor_ == '\n') line_++; 35740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!*cursor_) return Error("end of file in comment"); 35894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen cursor_++; 35994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 36094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen cursor_ += 2; 36194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen break; 36226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 36326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // fall thru 36426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen default: 365fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen if (IsIdentifierStart(c)) { 36626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // Collect all chars of an identifier: 36726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen const char *start = cursor_ - 1; 36826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen while (isalnum(static_cast<unsigned char>(*cursor_)) || 36926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen *cursor_ == '_') 37026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen cursor_++; 37126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen attribute_.append(start, cursor_); 37226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen token_ = kTokenIdentifier; 37340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 37426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else if (isdigit(static_cast<unsigned char>(c)) || c == '-') { 37526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen const char *start = cursor_ - 1; 37629574282a283ddc7904d096d27b783b794da7e91Wouter van Oortmerssen if (c == '-' && *cursor_ == '0' && 37729574282a283ddc7904d096d27b783b794da7e91Wouter van Oortmerssen (cursor_[1] == 'x' || cursor_[1] == 'X')) { 378f6f88e567ef7f2d282991c761ad2c8d106f6b183Raman ++start; 379f6f88e567ef7f2d282991c761ad2c8d106f6b183Raman ++cursor_; 380f6f88e567ef7f2d282991c761ad2c8d106f6b183Raman attribute_.append(&c, &c + 1); 381f6f88e567ef7f2d282991c761ad2c8d106f6b183Raman c = '0'; 382f6f88e567ef7f2d282991c761ad2c8d106f6b183Raman } 38394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (c == '0' && (*cursor_ == 'x' || *cursor_ == 'X')) { 38494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen cursor_++; 38594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen while (isxdigit(static_cast<unsigned char>(*cursor_))) cursor_++; 38694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen attribute_.append(start + 2, cursor_); 38729574282a283ddc7904d096d27b783b794da7e91Wouter van Oortmerssen attribute_ = NumToString(static_cast<int64_t>( 38829574282a283ddc7904d096d27b783b794da7e91Wouter van Oortmerssen StringToUInt(attribute_.c_str(), nullptr, 16))); 38994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen token_ = kTokenIntegerConstant; 39040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 39194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 39226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen while (isdigit(static_cast<unsigned char>(*cursor_))) cursor_++; 39394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (*cursor_ == '.' || *cursor_ == 'e' || *cursor_ == 'E') { 39494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (*cursor_ == '.') { 39594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen cursor_++; 39694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen while (isdigit(static_cast<unsigned char>(*cursor_))) cursor_++; 39794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 39893df5697a04e406929d7a3fa1f17904d2859e36dWouter van Oortmerssen // See if this float has a scientific notation suffix. Both JSON 39993df5697a04e406929d7a3fa1f17904d2859e36dWouter van Oortmerssen // and C++ (through strtod() we use) have the same format: 40093df5697a04e406929d7a3fa1f17904d2859e36dWouter van Oortmerssen if (*cursor_ == 'e' || *cursor_ == 'E') { 40193df5697a04e406929d7a3fa1f17904d2859e36dWouter van Oortmerssen cursor_++; 40293df5697a04e406929d7a3fa1f17904d2859e36dWouter van Oortmerssen if (*cursor_ == '+' || *cursor_ == '-') cursor_++; 40393df5697a04e406929d7a3fa1f17904d2859e36dWouter van Oortmerssen while (isdigit(static_cast<unsigned char>(*cursor_))) cursor_++; 40493df5697a04e406929d7a3fa1f17904d2859e36dWouter van Oortmerssen } 40526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen token_ = kTokenFloatConstant; 40626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else { 40726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen token_ = kTokenIntegerConstant; 40826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 40926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen attribute_.append(start, cursor_); 41040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 41126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 41226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen std::string ch; 41326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen ch = c; 41426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (c < ' ' || c > '~') ch = "code: " + NumToString(c); 41540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("illegal character: " + ch); 41626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 41726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 41826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 41926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 42040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen// Check if a given token is next. 42140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssenbool Parser::Is(int t) { 42240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return t == token_; 42326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 42426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 42503e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssenbool Parser::IsIdent(const char *id) { 42603e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen return token_ == kTokenIdentifier && attribute_ == id; 42703e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen} 42803e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen 42926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen// Expect a given token to be next, consume it, or error if not present. 43040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::Expect(int t) { 43126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (t != token_) { 43240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("expecting: " + TokenToString(t) + " instead got: " + 43340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen TokenToStringId(token_)); 43426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 43540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 43640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 43726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 43826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 43940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseNamespacing(std::string *id, std::string *last) { 44040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen while (Is('.')) { 44140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 44239833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van Oortmerssen *id += "."; 44339833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van Oortmerssen *id += attribute_; 44439833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van Oortmerssen if (last) *last = attribute_; 44540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 44639833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van Oortmerssen } 44740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 44839833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van Oortmerssen} 44939833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van Oortmerssen 45039833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van OortmerssenEnumDef *Parser::LookupEnum(const std::string &id) { 45194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Search thru parent namespaces. 452321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen for (int components = static_cast<int>(current_namespace_->components.size()); 45394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen components >= 0; components--) { 45440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen auto ed = enums_.Lookup( 455321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen current_namespace_->GetFullyQualifiedName(id, components)); 45694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (ed) return ed; 45794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 45894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen return nullptr; 45939833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van Oortmerssen} 46039833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van Oortmerssen 4619c3920d0ab90e9442759c6b41c28af577759a692Wouter van OortmerssenStructDef *Parser::LookupStruct(const std::string &id) const { 4629c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen auto sd = structs_.Lookup(id); 4639c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen if (sd) sd->refcount++; 4649c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen return sd; 4659c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen} 4669c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen 46740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseTypeIdent(Type &type) { 46839833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van Oortmerssen std::string id = attribute_; 46940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 47040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseNamespacing(&id, nullptr)); 47139833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van Oortmerssen auto enum_def = LookupEnum(id); 472d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen if (enum_def) { 473d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen type = enum_def->underlying_type; 474d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen if (enum_def->is_union) type.base_type = BASE_TYPE_UNION; 475d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen } else { 476d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen type.base_type = BASE_TYPE_STRUCT; 47739833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van Oortmerssen type.struct_def = LookupCreateStruct(id); 478d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen } 47940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 480d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen} 481d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen 48226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen// Parse any IDL type. 48340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseType(Type &type) { 48403e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen if (token_ == kTokenIdentifier) { 48503e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen if (IsIdent("bool")) { 48603e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen type.base_type = BASE_TYPE_BOOL; 48703e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen NEXT(); 48803e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if (IsIdent("byte") || IsIdent("int8")) { 48903e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen type.base_type = BASE_TYPE_CHAR; 49003e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen NEXT(); 49103e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if (IsIdent("ubyte") || IsIdent("uint8")) { 49203e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen type.base_type = BASE_TYPE_UCHAR; 49303e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen NEXT(); 49403e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if (IsIdent("short") || IsIdent("int16")) { 49503e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen type.base_type = BASE_TYPE_SHORT; 49603e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen NEXT(); 49703e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if (IsIdent("ushort") || IsIdent("uint16")) { 49803e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen type.base_type = BASE_TYPE_USHORT; 49903e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen NEXT(); 50003e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if (IsIdent("int") || IsIdent("int32")) { 50103e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen type.base_type = BASE_TYPE_INT; 50203e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen NEXT(); 50303e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if (IsIdent("uint") || IsIdent("uint32")) { 50403e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen type.base_type = BASE_TYPE_UINT; 50503e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen NEXT(); 50603e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if (IsIdent("long") || IsIdent("int64")) { 50703e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen type.base_type = BASE_TYPE_LONG; 50803e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen NEXT(); 50903e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if (IsIdent("ulong") || IsIdent("uint64")) { 51003e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen type.base_type = BASE_TYPE_ULONG; 51103e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen NEXT(); 51203e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if (IsIdent("float") || IsIdent("float32")) { 51303e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen type.base_type = BASE_TYPE_FLOAT; 51403e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen NEXT(); 51503e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if (IsIdent("double") || IsIdent("float64")) { 51603e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen type.base_type = BASE_TYPE_DOUBLE; 51703e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen NEXT(); 51803e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if (IsIdent("string")) { 51903e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen type.base_type = BASE_TYPE_STRING; 52040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 52126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else { 52203e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen ECHECK(ParseTypeIdent(type)); 52303e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } 52403e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if (token_ == '[') { 52503e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen NEXT(); 52603e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen Type subtype; 52703e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen ECHECK(ParseType(subtype)); 52803e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen if (subtype.base_type == BASE_TYPE_VECTOR) { 52903e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen // We could support this, but it will complicate things, and it's 53003e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen // easier to work around with a struct around the inner vector. 53103e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen return Error( 53203e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen "nested vector types not supported (wrap in table first)."); 53326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 53403e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen type = Type(BASE_TYPE_VECTOR, subtype.struct_def, subtype.enum_def); 53503e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen type.element = subtype.base_type; 53603e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen EXPECT(']'); 53703e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else { 53803e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen return Error("illegal type syntax"); 53926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 54040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 54126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 54226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 54340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::AddField(StructDef &struct_def, const std::string &name, 54440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen const Type &type, FieldDef **dest) { 54526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto &field = *new FieldDef(); 54626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen field.value.offset = 54726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen FieldIndexToOffset(static_cast<voffset_t>(struct_def.fields.vec.size())); 54826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen field.name = name; 549df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez field.file = struct_def.file; 55026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen field.value.type = type; 55126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (struct_def.fixed) { // statically compute the field offset 55226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto size = InlineSize(type); 55326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto alignment = InlineAlignment(type); 55426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // structs_ need to have a predictable format, so we need to align to 55526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // the largest scalar 55626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen struct_def.minalign = std::max(struct_def.minalign, alignment); 55726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen struct_def.PadLastField(alignment); 5581256307a388f05917b112253ef79e9b79ff76e1dWouter van Oortmerssen field.value.offset = static_cast<voffset_t>(struct_def.bytesize); 55926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen struct_def.bytesize += size; 56026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 56126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (struct_def.fields.Add(name, &field)) 56240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("field already exists: " + name); 56340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen *dest = &field; 56440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 56526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 56626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 56740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseField(StructDef &struct_def) { 56826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen std::string name = attribute_; 569e9f1f4d9b7fb41f9f66a24ef03ccbea1780d2674Wouter van Oortmerssen 5709c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen if (LookupStruct(name)) 571e9f1f4d9b7fb41f9f66a24ef03ccbea1780d2674Wouter van Oortmerssen return Error("field name can not be the same as table/struct name"); 572e9f1f4d9b7fb41f9f66a24ef03ccbea1780d2674Wouter van Oortmerssen 573730c0cadde2302efa1487d672a1e2f53680ce2eaGabriel Martinez std::vector<std::string> dc = doc_comment_; 57440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 57540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(':'); 57626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Type type; 57740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseType(type)); 57826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 57926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (struct_def.fixed && !IsScalar(type.base_type) && !IsStruct(type)) 58040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("structs_ may contain only scalar or struct fields"); 58126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 5829140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen FieldDef *typefield = nullptr; 58326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (type.base_type == BASE_TYPE_UNION) { 58426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // For union fields, add a second auto-generated field to hold the type, 5859e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen // with a special suffix. 5869e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen ECHECK(AddField(struct_def, name + UnionTypeFieldSuffix(), 5879e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen type.enum_def->underlying_type, &typefield)); 58868bbe983e9819bcbcd214cf84d73a440863ed6caBei Li } else if (type.base_type == BASE_TYPE_VECTOR && 58968bbe983e9819bcbcd214cf84d73a440863ed6caBei Li type.element == BASE_TYPE_UNION) { 59046bb05d95226c72cc85242eee386465860786333Kamil Rojewski // Only cpp, js and ts supports the union vector feature so far. 59146bb05d95226c72cc85242eee386465860786333Kamil Rojewski if (!SupportsVectorOfUnions()) { 59268bbe983e9819bcbcd214cf84d73a440863ed6caBei Li return Error("Vectors of unions are not yet supported in all " 59368bbe983e9819bcbcd214cf84d73a440863ed6caBei Li "the specified programming languages."); 59468bbe983e9819bcbcd214cf84d73a440863ed6caBei Li } 59568bbe983e9819bcbcd214cf84d73a440863ed6caBei Li // For vector of union fields, add a second auto-generated vector field to 59668bbe983e9819bcbcd214cf84d73a440863ed6caBei Li // hold the types, with a special suffix. 59768bbe983e9819bcbcd214cf84d73a440863ed6caBei Li Type union_vector(BASE_TYPE_VECTOR, nullptr, type.enum_def); 59868bbe983e9819bcbcd214cf84d73a440863ed6caBei Li union_vector.element = BASE_TYPE_UTYPE; 59968bbe983e9819bcbcd214cf84d73a440863ed6caBei Li ECHECK(AddField(struct_def, name + UnionTypeFieldSuffix(), 60068bbe983e9819bcbcd214cf84d73a440863ed6caBei Li union_vector, &typefield)); 60126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 60226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 60340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen FieldDef *field; 60440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(AddField(struct_def, name, type, &field)); 60526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 60626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (token_ == '=') { 60740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 60815dc1a86cd9e1fd22a46fde1a3632418eb8d9466Wouter van Oortmerssen if (!IsScalar(type.base_type)) 60940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("default values currently only supported for scalars"); 61040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseSingleValue(field->value)); 611fd542c71e35774f640073cb6fb3fa939d2f19f87Wouter van Oortmerssen } 612fd542c71e35774f640073cb6fb3fa939d2f19f87Wouter van Oortmerssen if (IsFloat(field->value.type.base_type)) { 613fd542c71e35774f640073cb6fb3fa939d2f19f87Wouter van Oortmerssen if (!strpbrk(field->value.constant.c_str(), ".eE")) 614fd542c71e35774f640073cb6fb3fa939d2f19f87Wouter van Oortmerssen field->value.constant += ".0"; 61526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 61626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 6177b8053570e4407cedfde8d32f6a3c59e5585ef7bWouter van Oortmerssen if (type.enum_def && 6187b8053570e4407cedfde8d32f6a3c59e5585ef7bWouter van Oortmerssen IsScalar(type.base_type) && 6197b8053570e4407cedfde8d32f6a3c59e5585ef7bWouter van Oortmerssen !struct_def.fixed && 6207b8053570e4407cedfde8d32f6a3c59e5585ef7bWouter van Oortmerssen !type.enum_def->attributes.Lookup("bit_flags") && 621d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen !type.enum_def->ReverseLookup(static_cast<int>( 62240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen StringToInt(field->value.constant.c_str())))) 6239c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen Warning("enum " + type.enum_def->name + 6247b8053570e4407cedfde8d32f6a3c59e5585ef7bWouter van Oortmerssen " does not have a declaration for this field\'s default of " + 62540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen field->value.constant); 6267b8053570e4407cedfde8d32f6a3c59e5585ef7bWouter van Oortmerssen 62740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen field->doc_comment = dc; 628e6b79f00022aee3108427977c9823ff57154e1c6Wouter van Oortmerssen ECHECK(ParseMetaData(&field->attributes)); 62940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen field->deprecated = field->attributes.Lookup("deprecated") != nullptr; 63040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen auto hash_name = field->attributes.Lookup("hash"); 631d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames if (hash_name) { 632d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames switch (type.base_type) { 633d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames case BASE_TYPE_INT: 634d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames case BASE_TYPE_UINT: { 635d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames if (FindHashFunction32(hash_name->constant.c_str()) == nullptr) 63640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("Unknown hashing algorithm for 32 bit types: " + 637d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames hash_name->constant); 638d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames break; 639d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames } 640d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames case BASE_TYPE_LONG: 641d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames case BASE_TYPE_ULONG: { 642d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames if (FindHashFunction64(hash_name->constant.c_str()) == nullptr) 64340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("Unknown hashing algorithm for 64 bit types: " + 644d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames hash_name->constant); 645d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames break; 646d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames } 647d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames default: 64840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error( 64940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen "only int, uint, long and ulong data types support hashing."); 650d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames } 651d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames } 652dc2fa215b854b31aa9a7f8c959ce08297ec79e23Wouter van Oortmerssen auto cpp_type = field->attributes.Lookup("cpp_type"); 653dc2fa215b854b31aa9a7f8c959ce08297ec79e23Wouter van Oortmerssen if (cpp_type) { 654dc2fa215b854b31aa9a7f8c959ce08297ec79e23Wouter van Oortmerssen if (!hash_name) 655dc2fa215b854b31aa9a7f8c959ce08297ec79e23Wouter van Oortmerssen return Error("cpp_type can only be used with a hashed field"); 656dc2fa215b854b31aa9a7f8c959ce08297ec79e23Wouter van Oortmerssen } 65740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (field->deprecated && struct_def.fixed) 65840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("can't deprecate fields in a struct"); 65940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen field->required = field->attributes.Lookup("required") != nullptr; 66040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (field->required && (struct_def.fixed || 66140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen IsScalar(field->value.type.base_type))) 66240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("only non-scalar fields in tables may be 'required'"); 66340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen field->key = field->attributes.Lookup("key") != nullptr; 66440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (field->key) { 6653550899987f9590357dec34d302380874bb2311cWouter van Oortmerssen if (struct_def.has_key) 66640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("only one field may be set as 'key'"); 6673550899987f9590357dec34d302380874bb2311cWouter van Oortmerssen struct_def.has_key = true; 66840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!IsScalar(field->value.type.base_type)) { 66940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen field->required = true; 67040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (field->value.type.base_type != BASE_TYPE_STRING) 67140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("'key' field must be string or scalar type"); 6723550899987f9590357dec34d302380874bb2311cWouter van Oortmerssen } 6733550899987f9590357dec34d302380874bb2311cWouter van Oortmerssen } 674641b397f8b79701b44184a52b5b9c6da98eb7580Wouter van Oortmerssen 67553a897731e23320e67602d3d4c56e09caffb98carmawatson auto field_native_custom_alloc = field->attributes.Lookup("native_custom_alloc"); 67653a897731e23320e67602d3d4c56e09caffb98carmawatson if (field_native_custom_alloc) 67753a897731e23320e67602d3d4c56e09caffb98carmawatson return Error("native_custom_alloc can only be used with a table or struct definition"); 67853a897731e23320e67602d3d4c56e09caffb98carmawatson 679641b397f8b79701b44184a52b5b9c6da98eb7580Wouter van Oortmerssen field->native_inline = field->attributes.Lookup("native_inline") != nullptr; 680641b397f8b79701b44184a52b5b9c6da98eb7580Wouter van Oortmerssen if (field->native_inline && !IsStruct(field->value.type)) 681641b397f8b79701b44184a52b5b9c6da98eb7580Wouter van Oortmerssen return Error("native_inline can only be defined on structs'"); 682641b397f8b79701b44184a52b5b9c6da98eb7580Wouter van Oortmerssen 68340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen auto nested = field->attributes.Lookup("nested_flatbuffer"); 6843e201a99b2f23c8c8475e43803d122b105db9a68Wouter van Oortmerssen if (nested) { 6853e201a99b2f23c8c8475e43803d122b105db9a68Wouter van Oortmerssen if (nested->type.base_type != BASE_TYPE_STRING) 68640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error( 68740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen "nested_flatbuffer attribute must be a string (the root type)"); 68840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (field->value.type.base_type != BASE_TYPE_VECTOR || 68940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen field->value.type.element != BASE_TYPE_UCHAR) 69040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error( 69140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen "nested_flatbuffer attribute may only apply to a vector of ubyte"); 6923e201a99b2f23c8c8475e43803d122b105db9a68Wouter van Oortmerssen // This will cause an error if the root type of the nested flatbuffer 6933e201a99b2f23c8c8475e43803d122b105db9a68Wouter van Oortmerssen // wasn't defined elsewhere. 6943e201a99b2f23c8c8475e43803d122b105db9a68Wouter van Oortmerssen LookupCreateStruct(nested->constant); 69589a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich 69689a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich // Keep a pointer to StructDef in FieldDef to simplify re-use later 697321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen auto nested_qualified_name = 698321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen current_namespace_->GetFullyQualifiedName(nested->constant); 6999c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen field->nested_flatbuffer = LookupStruct(nested_qualified_name); 7003e201a99b2f23c8c8475e43803d122b105db9a68Wouter van Oortmerssen } 70126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 702dddd0865cb161a081afbdfa11919622a49f4141aWouter van Oortmerssen if (field->attributes.Lookup("flexbuffer")) { 7038f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen field->flexbuffer = true; 704dddd0865cb161a081afbdfa11919622a49f4141aWouter van Oortmerssen uses_flexbuffers_ = true; 705dddd0865cb161a081afbdfa11919622a49f4141aWouter van Oortmerssen if (field->value.type.base_type != BASE_TYPE_VECTOR || 706dddd0865cb161a081afbdfa11919622a49f4141aWouter van Oortmerssen field->value.type.element != BASE_TYPE_UCHAR) 707dddd0865cb161a081afbdfa11919622a49f4141aWouter van Oortmerssen return Error( 708dddd0865cb161a081afbdfa11919622a49f4141aWouter van Oortmerssen "flexbuffer attribute may only apply to a vector of ubyte"); 709dddd0865cb161a081afbdfa11919622a49f4141aWouter van Oortmerssen } 710dddd0865cb161a081afbdfa11919622a49f4141aWouter van Oortmerssen 7119140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen if (typefield) { 7127cc72e4b11df064391a909ee7fa0ee5dd7630f9bKamil Rojewski if (!IsScalar(typefield->value.type.base_type)) { 7137cc72e4b11df064391a909ee7fa0ee5dd7630f9bKamil Rojewski // this is a union vector field 7147cc72e4b11df064391a909ee7fa0ee5dd7630f9bKamil Rojewski typefield->required = field->required; 7157cc72e4b11df064391a909ee7fa0ee5dd7630f9bKamil Rojewski } 7169140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen // If this field is a union, and it has a manually assigned id, 7179140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen // the automatically added type field should have an id as well (of N - 1). 71840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen auto attr = field->attributes.Lookup("id"); 7199140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen if (attr) { 7209140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen auto id = atoi(attr->constant.c_str()); 7219140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen auto val = new Value(); 7229140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen val->type = attr->type; 7239140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen val->constant = NumToString(id - 1); 7249140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen typefield->attributes.Add("id", val); 7259140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen } 7269140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen } 7279140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen 72840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(';'); 72940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 73026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 73126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 732b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van OortmerssenCheckedError Parser::ParseString(Value &val) { 733b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen auto s = attribute_; 734b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen EXPECT(kTokenStringConstant); 735b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen val.constant = NumToString(builder_.CreateString(s).o); 736b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen return NoError(); 737b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen} 738b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen 739f325cce6fdfc0c85e081fe90c7267fb0e8c79878Wouter van OortmerssenCheckedError Parser::ParseComma() { 740f325cce6fdfc0c85e081fe90c7267fb0e8c79878Wouter van Oortmerssen if (!opts.protobuf_ascii_alike) EXPECT(','); 741f325cce6fdfc0c85e081fe90c7267fb0e8c79878Wouter van Oortmerssen return NoError(); 742f325cce6fdfc0c85e081fe90c7267fb0e8c79878Wouter van Oortmerssen} 743f325cce6fdfc0c85e081fe90c7267fb0e8c79878Wouter van Oortmerssen 74440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseAnyValue(Value &val, FieldDef *field, 7459e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen size_t parent_fieldn, 7469e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen const StructDef *parent_struct_def) { 74726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen switch (val.type.base_type) { 74826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case BASE_TYPE_UNION: { 74926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen assert(field); 7509e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen std::string constant; 751eac2905568ec764f2d6fb0864ff95acec419d163Wouter van Oortmerssen // Find corresponding type field we may have already parsed. 752eac2905568ec764f2d6fb0864ff95acec419d163Wouter van Oortmerssen for (auto elem = field_stack_.rbegin(); 753eac2905568ec764f2d6fb0864ff95acec419d163Wouter van Oortmerssen elem != field_stack_.rbegin() + parent_fieldn; ++elem) { 754eac2905568ec764f2d6fb0864ff95acec419d163Wouter van Oortmerssen auto &type = elem->second->value.type; 755eac2905568ec764f2d6fb0864ff95acec419d163Wouter van Oortmerssen if (type.base_type == BASE_TYPE_UTYPE && 756eac2905568ec764f2d6fb0864ff95acec419d163Wouter van Oortmerssen type.enum_def == val.type.enum_def) { 757eac2905568ec764f2d6fb0864ff95acec419d163Wouter van Oortmerssen constant = elem->first.constant; 758eac2905568ec764f2d6fb0864ff95acec419d163Wouter van Oortmerssen break; 759eac2905568ec764f2d6fb0864ff95acec419d163Wouter van Oortmerssen } 760eac2905568ec764f2d6fb0864ff95acec419d163Wouter van Oortmerssen } 761eac2905568ec764f2d6fb0864ff95acec419d163Wouter van Oortmerssen if (constant.empty()) { 7629e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen // We haven't seen the type field yet. Sadly a lot of JSON writers 7639e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen // output these in alphabetical order, meaning it comes after this 7649e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen // value. So we scan past the value to find it, then come back here. 7659e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen auto type_name = field->name + UnionTypeFieldSuffix(); 7669e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen assert(parent_struct_def); 7679e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen auto type_field = parent_struct_def->fields.Lookup(type_name); 7689e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen assert(type_field); // Guaranteed by ParseField(). 7699e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen // Remember where we are in the source file, so we can come back here. 7709e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen auto backup = *static_cast<ParserState *>(this); 7719e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen ECHECK(SkipAnyJsonValue()); // The table. 772f325cce6fdfc0c85e081fe90c7267fb0e8c79878Wouter van Oortmerssen ECHECK(ParseComma()); 7739e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen auto next_name = attribute_; 7749e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen if (Is(kTokenStringConstant)) { 7759e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen NEXT(); 7769e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen } else { 7779e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen EXPECT(kTokenIdentifier); 7789e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen } 7799e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen if (next_name != type_name) 7809e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen return Error("missing type field after this union value: " + 7819e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen type_name); 7829e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen EXPECT(':'); 7839e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen Value type_val = type_field->value; 7849e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen ECHECK(ParseAnyValue(type_val, type_field, 0, nullptr)); 7859e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen constant = type_val.constant; 7869e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen // Got the information we needed, now rewind: 7879e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen *static_cast<ParserState *>(this) = backup; 7889e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen } 78940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen uint8_t enum_idx; 7909e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen ECHECK(atot(constant.c_str(), *this, &enum_idx)); 7913fb6a86d020f7423553a4e2dbba637b56d7760f6Wouter van Oortmerssen auto enum_val = val.type.enum_def->ReverseLookup(enum_idx); 79240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!enum_val) return Error("illegal type id for: " + field->name); 793b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen if (enum_val->union_type.base_type == BASE_TYPE_STRUCT) { 794b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen ECHECK(ParseTable(*enum_val->union_type.struct_def, &val.constant, 795b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen nullptr)); 796b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen if (enum_val->union_type.struct_def->fixed) { 797b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen // All BASE_TYPE_UNION values are offsets, so turn this into one. 798b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen SerializeStruct(*enum_val->union_type.struct_def, val); 799b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen builder_.ClearOffsets(); 800b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen val.constant = NumToString(builder_.GetSize()); 801b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen } 802b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen } else if (enum_val->union_type.base_type == BASE_TYPE_STRING) { 803b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen ECHECK(ParseString(val)); 804b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen } else { 805b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen assert(false); 806b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen } 80726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen break; 80826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 80926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case BASE_TYPE_STRUCT: 81040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseTable(*val.type.struct_def, &val.constant, nullptr)); 81126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen break; 81226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case BASE_TYPE_STRING: { 813b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen ECHECK(ParseString(val)); 81426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen break; 81526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 81626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case BASE_TYPE_VECTOR: { 81740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen uoffset_t off; 81840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseVector(val.type.VectorType(), &off)); 81940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen val.constant = NumToString(off); 82026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen break; 82126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 822d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames case BASE_TYPE_INT: 823d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames case BASE_TYPE_UINT: 824d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames case BASE_TYPE_LONG: 825d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames case BASE_TYPE_ULONG: { 826d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames if (field && field->attributes.Lookup("hash") && 827d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames (token_ == kTokenIdentifier || token_ == kTokenStringConstant)) { 82840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseHash(val, field)); 829d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames } else { 83040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseSingleValue(val)); 831d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames } 832d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames break; 833d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames } 83426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen default: 83540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseSingleValue(val)); 83626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen break; 83726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 83840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 83926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 84026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 84126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenvoid Parser::SerializeStruct(const StructDef &struct_def, const Value &val) { 8424d7810424c8f964dbcb8dd3179d8c46cd896c4dcWouter van Oortmerssen assert(val.constant.length() == struct_def.bytesize); 84326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen builder_.Align(struct_def.minalign); 8444d7810424c8f964dbcb8dd3179d8c46cd896c4dcWouter van Oortmerssen builder_.PushBytes(reinterpret_cast<const uint8_t *>(val.constant.c_str()), 8454d7810424c8f964dbcb8dd3179d8c46cd896c4dcWouter van Oortmerssen struct_def.bytesize); 84626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen builder_.AddStructOffset(val.offset, builder_.GetSize()); 84726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 84826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 8498f864aad7b875d645236be59ab1037051b12ba10Wouter van OortmerssenCheckedError Parser::ParseTableDelimiters(size_t &fieldn, 8508f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen const StructDef *struct_def, 851a8923222033763f1a74f836c656af19d9f620378Stewart Miles ParseTableDelimitersBody body, 852a8923222033763f1a74f836c656af19d9f620378Stewart Miles void *state) { 8538f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen // We allow tables both as JSON object{ .. } with field names 854b1740688bfbebc0d7fa2d8106d5c0eaa8c6e27d8Guillaume Giraud // or vector[..] with all fields in order 8558f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen char terminator = '}'; 8568f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen bool is_nested_vector = struct_def && Is('['); 8578f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen if (is_nested_vector) { 858b1740688bfbebc0d7fa2d8106d5c0eaa8c6e27d8Guillaume Giraud NEXT(); 8598f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen terminator = ']'; 860b1740688bfbebc0d7fa2d8106d5c0eaa8c6e27d8Guillaume Giraud } else { 861b1740688bfbebc0d7fa2d8106d5c0eaa8c6e27d8Guillaume Giraud EXPECT('{'); 862b1740688bfbebc0d7fa2d8106d5c0eaa8c6e27d8Guillaume Giraud } 8636c2dc41e0df3d6edc8cd8f452dd7a8ad7ff840c0Wouter van Oortmerssen for (;;) { 8648f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen if ((!opts.strict_json || !fieldn) && Is(terminator)) break; 865b1740688bfbebc0d7fa2d8106d5c0eaa8c6e27d8Guillaume Giraud std::string name; 8668f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen if (is_nested_vector) { 8678f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen if (fieldn > struct_def->fields.vec.size()) { 868b1740688bfbebc0d7fa2d8106d5c0eaa8c6e27d8Guillaume Giraud return Error("too many unnamed fields in nested array"); 869b1740688bfbebc0d7fa2d8106d5c0eaa8c6e27d8Guillaume Giraud } 8708f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen name = struct_def->fields.vec[fieldn]->name; 87140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } else { 872b1740688bfbebc0d7fa2d8106d5c0eaa8c6e27d8Guillaume Giraud name = attribute_; 873b1740688bfbebc0d7fa2d8106d5c0eaa8c6e27d8Guillaume Giraud if (Is(kTokenStringConstant)) { 874b1740688bfbebc0d7fa2d8106d5c0eaa8c6e27d8Guillaume Giraud NEXT(); 875b1740688bfbebc0d7fa2d8106d5c0eaa8c6e27d8Guillaume Giraud } else { 876b1740688bfbebc0d7fa2d8106d5c0eaa8c6e27d8Guillaume Giraud EXPECT(opts.strict_json ? kTokenStringConstant : kTokenIdentifier); 877b1740688bfbebc0d7fa2d8106d5c0eaa8c6e27d8Guillaume Giraud } 878f325cce6fdfc0c85e081fe90c7267fb0e8c79878Wouter van Oortmerssen if (!opts.protobuf_ascii_alike || !(Is('{') || Is('['))) EXPECT(':'); 87940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } 880a8923222033763f1a74f836c656af19d9f620378Stewart Miles ECHECK(body(name, fieldn, struct_def, state)); 8818f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen if (Is(terminator)) break; 882f325cce6fdfc0c85e081fe90c7267fb0e8c79878Wouter van Oortmerssen ECHECK(ParseComma()); 8838f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen } 8848f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen NEXT(); 8858f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen if (is_nested_vector && fieldn != struct_def->fields.vec.size()) { 8868f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen return Error("wrong number of unnamed fields in table vector"); 8878f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen } 8888f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen return NoError(); 8898f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen} 8908f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen 8918f864aad7b875d645236be59ab1037051b12ba10Wouter van OortmerssenCheckedError Parser::ParseTable(const StructDef &struct_def, std::string *value, 8928f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen uoffset_t *ovalue) { 893a8923222033763f1a74f836c656af19d9f620378Stewart Miles size_t fieldn_outer = 0; 894a8923222033763f1a74f836c656af19d9f620378Stewart Miles auto err = ParseTableDelimiters(fieldn_outer, &struct_def, 895a8923222033763f1a74f836c656af19d9f620378Stewart Miles [](const std::string &name, size_t &fieldn, 896a8923222033763f1a74f836c656af19d9f620378Stewart Miles const StructDef *struct_def_inner, 897a8923222033763f1a74f836c656af19d9f620378Stewart Miles void *state) -> CheckedError { 898a8923222033763f1a74f836c656af19d9f620378Stewart Miles Parser *parser = static_cast<Parser *>(state); 8992e2063cbeb6ea95c804796c443153f71797c3629schoetbi if (name == "$schema") { 900a8923222033763f1a74f836c656af19d9f620378Stewart Miles ECHECK(parser->Expect(kTokenStringConstant)); 9012e2063cbeb6ea95c804796c443153f71797c3629schoetbi return NoError(); 9022e2063cbeb6ea95c804796c443153f71797c3629schoetbi } 903a8923222033763f1a74f836c656af19d9f620378Stewart Miles auto field = struct_def_inner->fields.Lookup(name); 90413d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke if (!field) { 905a8923222033763f1a74f836c656af19d9f620378Stewart Miles if (!parser->opts.skip_unexpected_fields_in_json) { 906a8923222033763f1a74f836c656af19d9f620378Stewart Miles return parser->Error("unknown field: " + name); 90713d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke } else { 908a8923222033763f1a74f836c656af19d9f620378Stewart Miles ECHECK(parser->SkipAnyJsonValue()); 90913d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke } 91013d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke } else { 91103e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen if (parser->IsIdent("null")) { 912a8923222033763f1a74f836c656af19d9f620378Stewart Miles ECHECK(parser->Next()); // Ignore this field. 913049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen } else { 914049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen Value val = field->value; 9158f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen if (field->flexbuffer) { 9168f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen flexbuffers::Builder builder(1024, 9178f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen flexbuffers::BUILDER_FLAG_SHARE_ALL); 918a8923222033763f1a74f836c656af19d9f620378Stewart Miles ECHECK(parser->ParseFlexBufferValue(&builder)); 9198f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen builder.Finish(); 920a8923222033763f1a74f836c656af19d9f620378Stewart Miles auto off = parser->builder_.CreateVector(builder.GetBuffer()); 9218f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen val.constant = NumToString(off.o); 92289a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich } else if (field->nested_flatbuffer) { 92389a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich ECHECK(parser->ParseNestedFlatbuffer(val, field, fieldn, struct_def_inner)); 9248f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen } else { 925a8923222033763f1a74f836c656af19d9f620378Stewart Miles ECHECK(parser->ParseAnyValue(val, field, fieldn, struct_def_inner)); 9268f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen } 927049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen // Hardcoded insertion-sort with error-check. 928049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen // If fields are specified in order, then this loop exits immediately. 929a8923222033763f1a74f836c656af19d9f620378Stewart Miles auto elem = parser->field_stack_.rbegin(); 930a8923222033763f1a74f836c656af19d9f620378Stewart Miles for (; elem != parser->field_stack_.rbegin() + fieldn; ++elem) { 931eac2905568ec764f2d6fb0864ff95acec419d163Wouter van Oortmerssen auto existing_field = elem->second; 932049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen if (existing_field == field) 933a8923222033763f1a74f836c656af19d9f620378Stewart Miles return parser->Error("field set more than once: " + field->name); 934049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen if (existing_field->value.offset < field->value.offset) break; 935049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen } 936eac2905568ec764f2d6fb0864ff95acec419d163Wouter van Oortmerssen // Note: elem points to before the insertion point, thus .base() points 937eac2905568ec764f2d6fb0864ff95acec419d163Wouter van Oortmerssen // to the correct spot. 938a8923222033763f1a74f836c656af19d9f620378Stewart Miles parser->field_stack_.insert(elem.base(), 939a8923222033763f1a74f836c656af19d9f620378Stewart Miles std::make_pair(val, field)); 940049f3f7907e9fc8eb1ecd7c3775139de65552585Wouter van Oortmerssen fieldn++; 94113d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke } 9424d7810424c8f964dbcb8dd3179d8c46cd896c4dcWouter van Oortmerssen } 9438f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen return NoError(); 944a8923222033763f1a74f836c656af19d9f620378Stewart Miles }, this); 9458f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen ECHECK(err); 94655dec4d2f8817ede5a98d302d0b947c759f97098sfariv 94755dec4d2f8817ede5a98d302d0b947c759f97098sfariv // Check if all required fields are parsed. 94855dec4d2f8817ede5a98d302d0b947c759f97098sfariv for (auto field_it = struct_def.fields.vec.begin(); 94955dec4d2f8817ede5a98d302d0b947c759f97098sfariv field_it != struct_def.fields.vec.end(); 95055dec4d2f8817ede5a98d302d0b947c759f97098sfariv ++field_it) { 95155dec4d2f8817ede5a98d302d0b947c759f97098sfariv auto required_field = *field_it; 95255dec4d2f8817ede5a98d302d0b947c759f97098sfariv if (!required_field->required) { 95355dec4d2f8817ede5a98d302d0b947c759f97098sfariv continue; 95455dec4d2f8817ede5a98d302d0b947c759f97098sfariv } 95555dec4d2f8817ede5a98d302d0b947c759f97098sfariv bool found = false; 956a8923222033763f1a74f836c656af19d9f620378Stewart Miles for (auto pf_it = field_stack_.end() - fieldn_outer; 95755dec4d2f8817ede5a98d302d0b947c759f97098sfariv pf_it != field_stack_.end(); 95855dec4d2f8817ede5a98d302d0b947c759f97098sfariv ++pf_it) { 95955dec4d2f8817ede5a98d302d0b947c759f97098sfariv auto parsed_field = pf_it->second; 96055dec4d2f8817ede5a98d302d0b947c759f97098sfariv if (parsed_field == required_field) { 96155dec4d2f8817ede5a98d302d0b947c759f97098sfariv found = true; 96255dec4d2f8817ede5a98d302d0b947c759f97098sfariv break; 96355dec4d2f8817ede5a98d302d0b947c759f97098sfariv } 96455dec4d2f8817ede5a98d302d0b947c759f97098sfariv } 96555dec4d2f8817ede5a98d302d0b947c759f97098sfariv if (!found) { 96655dec4d2f8817ede5a98d302d0b947c759f97098sfariv return Error("required field is missing: " + required_field->name + " in " + struct_def.name); 96755dec4d2f8817ede5a98d302d0b947c759f97098sfariv } 96826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 96913d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke 970a8923222033763f1a74f836c656af19d9f620378Stewart Miles if (struct_def.fixed && fieldn_outer != struct_def.fields.vec.size()) 97140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("struct: wrong number of initializers: " + struct_def.name); 9724d7810424c8f964dbcb8dd3179d8c46cd896c4dcWouter van Oortmerssen 97326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto start = struct_def.fixed 97426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen ? builder_.StartStruct(struct_def.minalign) 97526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen : builder_.StartTable(); 97626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 97726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen for (size_t size = struct_def.sortbysize ? sizeof(largest_scalar_t) : 1; 97826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen size; 97926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen size /= 2) { 98026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // Go through elements in reverse, since we're building the data backwards. 981a8923222033763f1a74f836c656af19d9f620378Stewart Miles for (auto it = field_stack_.rbegin(); it != field_stack_.rbegin() + 982a8923222033763f1a74f836c656af19d9f620378Stewart Miles fieldn_outer; 983a8923222033763f1a74f836c656af19d9f620378Stewart Miles ++it) { 984721d21923efe8fabd2e1df0f94891a47f8eb9000Shuhei Tanuma auto &field_value = it->first; 98526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto field = it->second; 98640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!struct_def.sortbysize || 98740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen size == SizeOf(field_value.type.base_type)) { 988721d21923efe8fabd2e1df0f94891a47f8eb9000Shuhei Tanuma switch (field_value.type.base_type) { 98903e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen #define FLATBUFFERS_TD(ENUM, IDLTYPE, \ 990f2b3705c2c62c40afdef96f73f0aeaf32b4c8e0eMikkelFJ CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \ 99126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case BASE_TYPE_ ## ENUM: \ 99226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen builder_.Pad(field->padding); \ 993be3c8742585326447a6f9e776ad90a6b0fceb953Wouter van Oortmerssen if (struct_def.fixed) { \ 99440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen CTYPE val; \ 99540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(atot(field_value.constant.c_str(), *this, &val)); \ 99640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen builder_.PushElement(val); \ 997be3c8742585326447a6f9e776ad90a6b0fceb953Wouter van Oortmerssen } else { \ 99840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen CTYPE val, valdef; \ 99940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(atot(field_value.constant.c_str(), *this, &val)); \ 100040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(atot(field->value.constant.c_str(), *this, &valdef)); \ 100140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen builder_.AddElement(field_value.offset, val, valdef); \ 1002be3c8742585326447a6f9e776ad90a6b0fceb953Wouter van Oortmerssen } \ 100326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen break; 100426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen FLATBUFFERS_GEN_TYPES_SCALAR(FLATBUFFERS_TD); 100526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen #undef FLATBUFFERS_TD 100603e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen #define FLATBUFFERS_TD(ENUM, IDLTYPE, \ 1007f2b3705c2c62c40afdef96f73f0aeaf32b4c8e0eMikkelFJ CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \ 100826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case BASE_TYPE_ ## ENUM: \ 100926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen builder_.Pad(field->padding); \ 101026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (IsStruct(field->value.type)) { \ 1011721d21923efe8fabd2e1df0f94891a47f8eb9000Shuhei Tanuma SerializeStruct(*field->value.type.struct_def, field_value); \ 101226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else { \ 101340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen CTYPE val; \ 101440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(atot(field_value.constant.c_str(), *this, &val)); \ 101540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen builder_.AddOffset(field_value.offset, val); \ 101626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } \ 101726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen break; 101826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen FLATBUFFERS_GEN_TYPES_POINTER(FLATBUFFERS_TD); 101926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen #undef FLATBUFFERS_TD 102026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 102126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 102226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 102326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 1024a8923222033763f1a74f836c656af19d9f620378Stewart Miles for (size_t i = 0; i < fieldn_outer; i++) field_stack_.pop_back(); 102526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 102626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (struct_def.fixed) { 102726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen builder_.ClearOffsets(); 102826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen builder_.EndStruct(); 10294d7810424c8f964dbcb8dd3179d8c46cd896c4dcWouter van Oortmerssen assert(value); 10304d7810424c8f964dbcb8dd3179d8c46cd896c4dcWouter van Oortmerssen // Temporarily store this struct in the value string, since it is to 10314d7810424c8f964dbcb8dd3179d8c46cd896c4dcWouter van Oortmerssen // be serialized in-place elsewhere. 10324d7810424c8f964dbcb8dd3179d8c46cd896c4dcWouter van Oortmerssen value->assign( 10334d7810424c8f964dbcb8dd3179d8c46cd896c4dcWouter van Oortmerssen reinterpret_cast<const char *>(builder_.GetCurrentBufferPointer()), 10344d7810424c8f964dbcb8dd3179d8c46cd896c4dcWouter van Oortmerssen struct_def.bytesize); 103526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen builder_.PopBytes(struct_def.bytesize); 103640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen assert(!ovalue); 103726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else { 1038ac1015e3c417ecb18d8f449a4e6aaaff3c4f53b9Wouter van Oortmerssen auto val = builder_.EndTable(start); 103940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (ovalue) *ovalue = val; 104040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (value) *value = NumToString(val); 104126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 104240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 104326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 104426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 10458f864aad7b875d645236be59ab1037051b12ba10Wouter van OortmerssenCheckedError Parser::ParseVectorDelimiters(size_t &count, 1046a8923222033763f1a74f836c656af19d9f620378Stewart Miles ParseVectorDelimitersBody body, 1047a8923222033763f1a74f836c656af19d9f620378Stewart Miles void *state) { 10488f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen EXPECT('['); 10496c2dc41e0df3d6edc8cd8f452dd7a8ad7ff840c0Wouter van Oortmerssen for (;;) { 10508f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen if ((!opts.strict_json || !count) && Is(']')) break; 1051a8923222033763f1a74f836c656af19d9f620378Stewart Miles ECHECK(body(count, state)); 10528f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen count++; 10538f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen if (Is(']')) break; 1054f325cce6fdfc0c85e081fe90c7267fb0e8c79878Wouter van Oortmerssen ECHECK(ParseComma()); 10558f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen } 10568f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen NEXT(); 10578f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen return NoError(); 10588f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen} 10598f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen 10608f864aad7b875d645236be59ab1037051b12ba10Wouter van OortmerssenCheckedError Parser::ParseVector(const Type &type, uoffset_t *ovalue) { 10618f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen size_t count = 0; 1062a8923222033763f1a74f836c656af19d9f620378Stewart Miles std::pair<Parser *, const Type &> parser_and_type_state(this, type); 1063a8923222033763f1a74f836c656af19d9f620378Stewart Miles auto err = ParseVectorDelimiters(count, 1064a8923222033763f1a74f836c656af19d9f620378Stewart Miles [](size_t &, void *state) -> CheckedError { 1065a8923222033763f1a74f836c656af19d9f620378Stewart Miles auto *parser_and_type = 1066a8923222033763f1a74f836c656af19d9f620378Stewart Miles static_cast<std::pair<Parser *, const Type &> *>(state); 1067a8923222033763f1a74f836c656af19d9f620378Stewart Miles auto *parser = parser_and_type->first; 106826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen Value val; 1069a8923222033763f1a74f836c656af19d9f620378Stewart Miles val.type = parser_and_type->second; 1070a8923222033763f1a74f836c656af19d9f620378Stewart Miles ECHECK(parser->ParseAnyValue(val, nullptr, 0, nullptr)); 1071a8923222033763f1a74f836c656af19d9f620378Stewart Miles parser->field_stack_.push_back(std::make_pair(val, nullptr)); 10728f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen return NoError(); 1073a8923222033763f1a74f836c656af19d9f620378Stewart Miles }, &parser_and_type_state); 10748f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen ECHECK(err); 107526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 1076be3c8742585326447a6f9e776ad90a6b0fceb953Wouter van Oortmerssen builder_.StartVector(count * InlineSize(type) / InlineAlignment(type), 1077be3c8742585326447a6f9e776ad90a6b0fceb953Wouter van Oortmerssen InlineAlignment(type)); 10788f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen for (size_t i = 0; i < count; i++) { 107926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // start at the back, since we're building the data backwards. 108026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto &val = field_stack_.back().first; 108126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen switch (val.type.base_type) { 108203e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen #define FLATBUFFERS_TD(ENUM, IDLTYPE, \ 1083f2b3705c2c62c40afdef96f73f0aeaf32b4c8e0eMikkelFJ CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \ 108426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen case BASE_TYPE_ ## ENUM: \ 108526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (IsStruct(val.type)) SerializeStruct(*val.type.struct_def, val); \ 108640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen else { \ 108740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen CTYPE elem; \ 108840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(atot(val.constant.c_str(), *this, &elem)); \ 108940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen builder_.PushElement(elem); \ 109040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } \ 109126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen break; 109226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) 109326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen #undef FLATBUFFERS_TD 109426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 109526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen field_stack_.pop_back(); 109626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 109726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 109826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen builder_.ClearOffsets(); 109940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen *ovalue = builder_.EndVector(count); 110040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 110126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 110226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 110389a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian HelmichCheckedError Parser::ParseNestedFlatbuffer(Value &val, FieldDef *field, 110489a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich size_t fieldn, 110589a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich const StructDef *parent_struct_def) { 110689a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich if (token_ == '[') {// backwards compat for 'legacy' ubyte buffers 110789a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich ECHECK(ParseAnyValue(val, field, fieldn, parent_struct_def)); 110889a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich } else { 110989a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich auto cursor_at_value_begin = cursor_; 111089a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich ECHECK(SkipAnyJsonValue()); 111189a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich std::string substring(cursor_at_value_begin -1 , cursor_ -1); 111289a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich 111389a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich // Create and initialize new parser 111489a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich Parser nested_parser; 111589a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich assert(field->nested_flatbuffer); 111689a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich nested_parser.root_struct_def_ = field->nested_flatbuffer; 111789a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich nested_parser.enums_ = enums_; 111889a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich nested_parser.opts = opts; 111989a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich nested_parser.uses_flexbuffers_ = uses_flexbuffers_; 112089a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich 112189a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich // Parse JSON substring into new flatbuffer builder using nested_parser 112289a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich if (!nested_parser.Parse(substring.c_str(), nullptr, nullptr)) { 112389a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich ECHECK(Error(nested_parser.error_)); 112489a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich } 112589a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich auto off = builder_.CreateVector(nested_parser.builder_.GetBufferPointer(), nested_parser.builder_.GetSize()); 112689a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich val.constant = NumToString(off.o); 112789a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich 112889a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich // Clean nested_parser before destruction to avoid deleting the elements in the SymbolTables 112989a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich nested_parser.enums_.dict.clear(); 113089a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich nested_parser.enums_.vec.clear(); 113189a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich } 113289a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich return NoError(); 113389a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich} 113489a68942acdeeb51ceb102d19153dcc23ba8c0ddChristian Helmich 1135e6b79f00022aee3108427977c9823ff57154e1c6Wouter van OortmerssenCheckedError Parser::ParseMetaData(SymbolTable<Value> *attributes) { 113640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is('(')) { 113740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 113826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen for (;;) { 113926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto name = attribute_; 114040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 11410952143971bdbb5ef20dae8a865e811a0e31b4b3Wouter van Oortmerssen if (known_attributes_.find(name) == known_attributes_.end()) 114240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("user define attributes must be declared before use: " + 114340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen name); 114426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto e = new Value(); 1145e6b79f00022aee3108427977c9823ff57154e1c6Wouter van Oortmerssen attributes->Add(name, e); 114640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is(':')) { 114740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 114840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseSingleValue(*e)); 114926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 115040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is(')')) { NEXT(); break; } 115140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(','); 115226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 115326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 115440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 115526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 115626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 115740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::TryTypedValue(int dtoken, bool check, Value &e, 115840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen BaseType req, bool *destmatch) { 115926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen bool match = dtoken == token_; 116026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (match) { 116140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen *destmatch = true; 116226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen e.constant = attribute_; 116326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (!check) { 116426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (e.type.base_type == BASE_TYPE_NONE) { 116526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen e.type.base_type = req; 116626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else { 116740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error(std::string("type mismatch: expecting: ") + 116840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen kTypeNames[e.type.base_type] + 116940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ", found: " + 117040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen kTypeNames[req]); 117126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 117226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 117340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 117426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 117540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 117626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 117726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 1178fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van OortmerssenCheckedError Parser::ParseEnumFromString(Type &type, int64_t *result) { 117940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen *result = 0; 11809c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen // Parse one or more enum identifiers, separated by spaces. 11819c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen const char *next = attribute_.c_str(); 11829c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen do { 11839c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen const char *divider = strchr(next, ' '); 11849c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen std::string word; 11859c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen if (divider) { 11869c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen word = std::string(next, divider); 11879c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen next = divider + strspn(divider, " "); 11889c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen } else { 11899c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen word = next; 11909c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen next += word.length(); 11919c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen } 11929c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen if (type.enum_def) { // The field has an enum type 11939c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen auto enum_val = type.enum_def->vals.Lookup(word); 11949c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen if (!enum_val) 119540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("unknown enum value: " + word + 11969c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen ", for enum: " + type.enum_def->name); 119740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen *result |= enum_val->value; 11989c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen } else { // No enum type, probably integral field. 11999c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen if (!IsInteger(type.base_type)) 120040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("not a valid value for this field: " + word); 12019c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen // TODO: could check if its a valid number constant here. 120239833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van Oortmerssen const char *dot = strrchr(word.c_str(), '.'); 120340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!dot) 120440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("enum values need to be qualified by an enum type"); 12059c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen std::string enum_def_str(word.c_str(), dot); 12069c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen std::string enum_val_str(dot + 1, word.c_str() + word.length()); 120739833d7cf051e4a2ecfb342419a86dc02c7e77aaWouter van Oortmerssen auto enum_def = LookupEnum(enum_def_str); 120840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!enum_def) return Error("unknown enum: " + enum_def_str); 12099c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen auto enum_val = enum_def->vals.Lookup(enum_val_str); 121040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!enum_val) return Error("unknown enum value: " + enum_val_str); 121140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen *result |= enum_val->value; 12129c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen } 12139c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen } while(*next); 121440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 12159c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen} 12169c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen 1217d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames 121840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseHash(Value &e, FieldDef* field) { 1219d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames assert(field); 1220d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames Value *hash_name = field->attributes.Lookup("hash"); 1221d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames switch (e.type.base_type) { 122246497e4f9ad2f8193dc12cad02d525f93c8f4fd0Wouter van Oortmerssen case BASE_TYPE_INT: { 122346497e4f9ad2f8193dc12cad02d525f93c8f4fd0Wouter van Oortmerssen auto hash = FindHashFunction32(hash_name->constant.c_str()); 122446497e4f9ad2f8193dc12cad02d525f93c8f4fd0Wouter van Oortmerssen int32_t hashed_value = static_cast<int32_t>(hash(attribute_.c_str())); 122546497e4f9ad2f8193dc12cad02d525f93c8f4fd0Wouter van Oortmerssen e.constant = NumToString(hashed_value); 122646497e4f9ad2f8193dc12cad02d525f93c8f4fd0Wouter van Oortmerssen break; 122746497e4f9ad2f8193dc12cad02d525f93c8f4fd0Wouter van Oortmerssen } 1228d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames case BASE_TYPE_UINT: { 1229d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames auto hash = FindHashFunction32(hash_name->constant.c_str()); 1230d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames uint32_t hashed_value = hash(attribute_.c_str()); 1231d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames e.constant = NumToString(hashed_value); 1232d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames break; 1233d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames } 123446497e4f9ad2f8193dc12cad02d525f93c8f4fd0Wouter van Oortmerssen case BASE_TYPE_LONG: { 123546497e4f9ad2f8193dc12cad02d525f93c8f4fd0Wouter van Oortmerssen auto hash = FindHashFunction64(hash_name->constant.c_str()); 123646497e4f9ad2f8193dc12cad02d525f93c8f4fd0Wouter van Oortmerssen int64_t hashed_value = static_cast<int64_t>(hash(attribute_.c_str())); 123746497e4f9ad2f8193dc12cad02d525f93c8f4fd0Wouter van Oortmerssen e.constant = NumToString(hashed_value); 123846497e4f9ad2f8193dc12cad02d525f93c8f4fd0Wouter van Oortmerssen break; 123946497e4f9ad2f8193dc12cad02d525f93c8f4fd0Wouter van Oortmerssen } 1240d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames case BASE_TYPE_ULONG: { 1241d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames auto hash = FindHashFunction64(hash_name->constant.c_str()); 1242d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames uint64_t hashed_value = hash(attribute_.c_str()); 1243d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames e.constant = NumToString(hashed_value); 1244d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames break; 1245d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames } 1246d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames default: 1247d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames assert(0); 1248d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames } 124940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 125040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 1251d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames} 1252d575321eba7f83f40de5fb23685ed3cdb47bc9ccAlex Ames 12538f864aad7b875d645236be59ab1037051b12ba10Wouter van OortmerssenCheckedError Parser::TokenError() { 12548f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen return Error("cannot parse value starting with: " + 12558f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen TokenToStringId(token_)); 12568f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen} 12578f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen 125840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseSingleValue(Value &e) { 1259d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen // First see if this could be a conversion function: 1260d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen if (token_ == kTokenIdentifier && *cursor_ == '(') { 1261d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen auto functionname = attribute_; 1262d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen NEXT(); 1263d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen EXPECT('('); 1264d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen ECHECK(ParseSingleValue(e)); 1265d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen EXPECT(')'); 1266d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen #define FLATBUFFERS_FN_DOUBLE(name, op) \ 1267d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen if (functionname == name) { \ 1268d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen auto x = strtod(e.constant.c_str(), nullptr); \ 1269d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen e.constant = NumToString(op); \ 1270d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen } 127185b131a719b3ca554a6cf4840f8ec27feb60ec07Bastien Brunnenstein FLATBUFFERS_FN_DOUBLE("deg", x / kPi * 180); 127285b131a719b3ca554a6cf4840f8ec27feb60ec07Bastien Brunnenstein FLATBUFFERS_FN_DOUBLE("rad", x * kPi / 180); 1273d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen FLATBUFFERS_FN_DOUBLE("sin", sin(x)); 1274d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen FLATBUFFERS_FN_DOUBLE("cos", cos(x)); 1275d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen FLATBUFFERS_FN_DOUBLE("tan", tan(x)); 1276d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen FLATBUFFERS_FN_DOUBLE("asin", asin(x)); 1277d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen FLATBUFFERS_FN_DOUBLE("acos", acos(x)); 1278d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen FLATBUFFERS_FN_DOUBLE("atan", atan(x)); 1279d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen // TODO(wvo): add more useful conversion functions here. 1280d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen #undef FLATBUFFERS_FN_DOUBLE 1281d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen // Then check if this could be a string/identifier enum value: 1282d3ac0bc149a9e62feec8e3a00f10ca88491e2254Wouter van Oortmerssen } else if (e.type.base_type != BASE_TYPE_STRING && 128303e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen e.type.base_type != BASE_TYPE_BOOL && 12849c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen e.type.base_type != BASE_TYPE_NONE && 12859c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen (token_ == kTokenIdentifier || token_ == kTokenStringConstant)) { 1286fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen if (IsIdentifierStart(attribute_[0])) { // Enum value. 1287fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen int64_t val; 1288fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen ECHECK(ParseEnumFromString(e.type, &val)); 1289fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen e.constant = NumToString(val); 1290fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen NEXT(); 1291fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen } else { // Numeric constant in string. 1292fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen if (IsInteger(e.type.base_type)) { 1293b6ba322a0411925757196a1ca6f3a1a87f46831eSahil Jain char *end; 1294b6ba322a0411925757196a1ca6f3a1a87f46831eSahil Jain e.constant = NumToString(StringToInt(attribute_.c_str(), &end)); 1295b6ba322a0411925757196a1ca6f3a1a87f46831eSahil Jain if (*end) 1296b6ba322a0411925757196a1ca6f3a1a87f46831eSahil Jain return Error("invalid integer: " + attribute_); 1297fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen } else if (IsFloat(e.type.base_type)) { 1298b6ba322a0411925757196a1ca6f3a1a87f46831eSahil Jain char *end; 1299b6ba322a0411925757196a1ca6f3a1a87f46831eSahil Jain e.constant = NumToString(strtod(attribute_.c_str(), &end)); 1300b6ba322a0411925757196a1ca6f3a1a87f46831eSahil Jain if (*end) 1301b6ba322a0411925757196a1ca6f3a1a87f46831eSahil Jain return Error("invalid float: " + attribute_); 1302fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen } else { 1303fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen assert(0); // Shouldn't happen, we covered all types. 1304fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen e.constant = "0"; 1305fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen } 130683dc5ed4a7267c78fb3f00e972de4db30762166dWouter van Oortmerssen NEXT(); 1307fbc8af40e34bebbbbf287bee25e3e4aab81213c3Wouter van Oortmerssen } 130826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } else { 130940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen bool match = false; 131040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(TryTypedValue(kTokenIntegerConstant, 131140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen IsScalar(e.type.base_type), 131240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen e, 131340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen BASE_TYPE_INT, 131440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen &match)); 131540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(TryTypedValue(kTokenFloatConstant, 131640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen IsFloat(e.type.base_type), 131740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen e, 131840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen BASE_TYPE_FLOAT, 131940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen &match)); 132040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(TryTypedValue(kTokenStringConstant, 132140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen e.type.base_type == BASE_TYPE_STRING, 132240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen e, 132340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen BASE_TYPE_STRING, 132440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen &match)); 132503e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen auto istrue = IsIdent("true"); 132603e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen if (istrue || IsIdent("false")) { 132703e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen attribute_ = NumToString(istrue); 132803e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen ECHECK(TryTypedValue(kTokenIdentifier, 132903e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen IsBool(e.type.base_type), 133003e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen e, 133103e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen BASE_TYPE_BOOL, 133203e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen &match)); 133303e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } 13348f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen if (!match) return TokenError(); 133526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 133640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 133726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 133826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 133994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van OortmerssenStructDef *Parser::LookupCreateStruct(const std::string &name, 134094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen bool create_if_new, bool definition) { 1341321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen std::string qualified_name = current_namespace_->GetFullyQualifiedName(name); 134220c0082ee5bfeeecaa443c001a89934e9448ffa4Wouter van Oortmerssen // See if it exists pre-declared by an unqualified use. 13439c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen auto struct_def = LookupStruct(name); 134494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (struct_def && struct_def->predecl) { 134594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (definition) { 134620c0082ee5bfeeecaa443c001a89934e9448ffa4Wouter van Oortmerssen // Make sure it has the current namespace, and is registered under its 134720c0082ee5bfeeecaa443c001a89934e9448ffa4Wouter van Oortmerssen // qualified name. 1348321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen struct_def->defined_namespace = current_namespace_; 134994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen structs_.Move(name, qualified_name); 135094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 135194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen return struct_def; 135294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 135320c0082ee5bfeeecaa443c001a89934e9448ffa4Wouter van Oortmerssen // See if it exists pre-declared by an qualified use. 13549c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen struct_def = LookupStruct(qualified_name); 135520c0082ee5bfeeecaa443c001a89934e9448ffa4Wouter van Oortmerssen if (struct_def && struct_def->predecl) { 135620c0082ee5bfeeecaa443c001a89934e9448ffa4Wouter van Oortmerssen if (definition) { 135720c0082ee5bfeeecaa443c001a89934e9448ffa4Wouter van Oortmerssen // Make sure it has the current namespace. 1358321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen struct_def->defined_namespace = current_namespace_; 135920c0082ee5bfeeecaa443c001a89934e9448ffa4Wouter van Oortmerssen } 136020c0082ee5bfeeecaa443c001a89934e9448ffa4Wouter van Oortmerssen return struct_def; 136120c0082ee5bfeeecaa443c001a89934e9448ffa4Wouter van Oortmerssen } 136294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (!definition) { 136394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Search thru parent namespaces. 1364321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen for (size_t components = current_namespace_->components.size(); 136594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen components && !struct_def; components--) { 13669c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen struct_def = LookupStruct( 1367321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen current_namespace_->GetFullyQualifiedName(name, components - 1)); 136894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 136994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 137094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (!struct_def && create_if_new) { 137126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen struct_def = new StructDef(); 137294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (definition) { 137394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen structs_.Add(qualified_name, struct_def); 137494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen struct_def->name = name; 1375321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen struct_def->defined_namespace = current_namespace_; 137694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else { 137794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Not a definition. 137894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Rather than failing, we create a "pre declared" StructDef, due to 137994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // circular references, and check for errors at the end of parsing. 13809c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen // It is defined in the current namespace, as the best guess what the 138194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // final namespace will be. 138294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen structs_.Add(name, struct_def); 138394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen struct_def->name = name; 13849c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen struct_def->defined_namespace = current_namespace_; 13859c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen struct_def->original_location.reset(new std::string(file_being_parsed_ + 13869c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen ":" + NumToString(line_))); 138794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 138826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 138926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen return struct_def; 139026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 139126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 139240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseEnum(bool is_union, EnumDef **dest) { 1393c3807fa39dda5445924ef77253efb446459f6e56Max Galkin std::vector<std::string> enum_comment = doc_comment_; 139440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 1395c3807fa39dda5445924ef77253efb446459f6e56Max Galkin std::string enum_name = attribute_; 139640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 139726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto &enum_def = *new EnumDef(); 1398c3807fa39dda5445924ef77253efb446459f6e56Max Galkin enum_def.name = enum_name; 139940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen enum_def.file = file_being_parsed_; 1400c3807fa39dda5445924ef77253efb446459f6e56Max Galkin enum_def.doc_comment = enum_comment; 140126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen enum_def.is_union = is_union; 1402321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen enum_def.defined_namespace = current_namespace_; 1403321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen if (enums_.Add(current_namespace_->GetFullyQualifiedName(enum_name), 140494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen &enum_def)) 140540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("enum already exists: " + enum_name); 140626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (is_union) { 140726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen enum_def.underlying_type.base_type = BASE_TYPE_UTYPE; 140826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen enum_def.underlying_type.enum_def = &enum_def; 1409a5f50019bc979c352bb7e0c08b8bbfd8ab06af4dWouter van Oortmerssen } else { 141045bda6e08de1436e8a25e791b776e0bcc38f232bWouter van Oortmerssen if (opts.proto_mode) { 141194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen enum_def.underlying_type.base_type = BASE_TYPE_INT; 1412d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen } else { 1413d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen // Give specialized error message, since this type spec used to 1414d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen // be optional in the first FlatBuffers release. 141540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!Is(':')) { 141640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("must specify the underlying integer type for this" 141740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen " enum (e.g. \': short\', which was the default)."); 141840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } else { 141940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 142040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } 1421d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen // Specify the integer type underlying this enum. 142240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseType(enum_def.underlying_type)); 1423d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen if (!IsInteger(enum_def.underlying_type.base_type)) 142440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("underlying enum type must be integral"); 1425d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen } 14263fb6a86d020f7423553a4e2dbba637b56d7760f6Wouter van Oortmerssen // Make this type refer back to the enum it was derived from. 14273fb6a86d020f7423553a4e2dbba637b56d7760f6Wouter van Oortmerssen enum_def.underlying_type.enum_def = &enum_def; 142826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 1429e6b79f00022aee3108427977c9823ff57154e1c6Wouter van Oortmerssen ECHECK(ParseMetaData(&enum_def.attributes)); 143040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT('{'); 143126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (is_union) enum_def.vals.Add("NONE", new EnumVal("NONE", 0)); 143240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen for (;;) { 143345bda6e08de1436e8a25e791b776e0bcc38f232bWouter van Oortmerssen if (opts.proto_mode && attribute_ == "option") { 143440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseProtoOption()); 143594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else { 143694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen auto value_name = attribute_; 143794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen auto full_name = value_name; 143894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen std::vector<std::string> value_comment = doc_comment_; 143940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 14403639032d1e2224663202f79ca33c5039eed95f29Wouter van Oortmerssen if (is_union) { 14413639032d1e2224663202f79ca33c5039eed95f29Wouter van Oortmerssen ECHECK(ParseNamespacing(&full_name, &value_name)); 1442d70f5ac6b02f250dca8e2c6e8f59a4223d1f66f6Wouter van Oortmerssen if (opts.union_value_namespacing) { 1443d70f5ac6b02f250dca8e2c6e8f59a4223d1f66f6Wouter van Oortmerssen // Since we can't namespace the actual enum identifiers, turn 1444d70f5ac6b02f250dca8e2c6e8f59a4223d1f66f6Wouter van Oortmerssen // namespace parts into part of the identifier. 1445d70f5ac6b02f250dca8e2c6e8f59a4223d1f66f6Wouter van Oortmerssen value_name = full_name; 1446d70f5ac6b02f250dca8e2c6e8f59a4223d1f66f6Wouter van Oortmerssen std::replace(value_name.begin(), value_name.end(), '.', '_'); 1447d70f5ac6b02f250dca8e2c6e8f59a4223d1f66f6Wouter van Oortmerssen } 14483639032d1e2224663202f79ca33c5039eed95f29Wouter van Oortmerssen } 144994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen auto prevsize = enum_def.vals.vec.size(); 145094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen auto value = enum_def.vals.vec.size() 145194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen ? enum_def.vals.vec.back()->value + 1 145294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen : 0; 145394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen auto &ev = *new EnumVal(value_name, value); 145494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (enum_def.vals.Add(value_name, &ev)) 145540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("enum value already exists: " + value_name); 145694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen ev.doc_comment = value_comment; 145794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (is_union) { 1458b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen if (Is(':')) { 1459b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen NEXT(); 1460b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen ECHECK(ParseType(ev.union_type)); 1461b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen if (ev.union_type.base_type != BASE_TYPE_STRUCT && 1462b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen ev.union_type.base_type != BASE_TYPE_STRING) 1463b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen return Error("union value type may only be table/struct/string"); 1464b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen enum_def.uses_type_aliases = true; 1465b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen } else { 1466b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen ev.union_type = Type(BASE_TYPE_STRUCT, LookupCreateStruct(full_name)); 1467b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen } 146894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 146940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is('=')) { 147040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 1471d779308b3e48124dae91896700bf3cc12b5251e3Wouter van Oortmerssen ev.value = StringToInt(attribute_.c_str()); 147240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIntegerConstant); 147345bda6e08de1436e8a25e791b776e0bcc38f232bWouter van Oortmerssen if (!opts.proto_mode && prevsize && 147494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen enum_def.vals.vec[prevsize - 1]->value >= ev.value) 147540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("enum values must be specified in ascending order"); 147694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 14779d01bfaea3befaa0e12b0b310cadc1ed036ecfe3Wouter van Oortmerssen if (is_union) { 14789d01bfaea3befaa0e12b0b310cadc1ed036ecfe3Wouter van Oortmerssen if (ev.value < 0 || ev.value >= 256) 14799d01bfaea3befaa0e12b0b310cadc1ed036ecfe3Wouter van Oortmerssen return Error("union enum value must fit in a ubyte"); 14809d01bfaea3befaa0e12b0b310cadc1ed036ecfe3Wouter van Oortmerssen } 148140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (opts.proto_mode && Is('[')) { 148240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 148394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // ignore attributes on enums. 148440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen while (token_ != ']') NEXT(); 148540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 148694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 148726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 148840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!Is(opts.proto_mode ? ';' : ',')) break; 148940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 149040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is('}')) break; 149140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } 149240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT('}'); 1493127d35085a22cb33034f608ee21d65a655d1582cWouter van Oortmerssen if (enum_def.attributes.Lookup("bit_flags")) { 1494127d35085a22cb33034f608ee21d65a655d1582cWouter van Oortmerssen for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end(); 1495127d35085a22cb33034f608ee21d65a655d1582cWouter van Oortmerssen ++it) { 1496127d35085a22cb33034f608ee21d65a655d1582cWouter van Oortmerssen if (static_cast<size_t>((*it)->value) >= 1497127d35085a22cb33034f608ee21d65a655d1582cWouter van Oortmerssen SizeOf(enum_def.underlying_type.base_type) * 8) 149840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("bit flag out of range of underlying integral type"); 14999c3de1e2a0591c2526453cf85260c09e3c624189Wouter van Oortmerssen (*it)->value = 1LL << (*it)->value; 1500127d35085a22cb33034f608ee21d65a655d1582cWouter van Oortmerssen } 1501127d35085a22cb33034f608ee21d65a655d1582cWouter van Oortmerssen } 150240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (dest) *dest = &enum_def; 1503321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen types_.Add(current_namespace_->GetFullyQualifiedName(enum_def.name), 15049b3d8b318a3bc9d71d08b50d723996f556557c86Wouter van Oortmerssen new Type(BASE_TYPE_UNION, nullptr, &enum_def)); 150540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 150626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 150726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 150840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::StartStruct(const std::string &name, StructDef **dest) { 150994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen auto &struct_def = *LookupCreateStruct(name, true, true); 151040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!struct_def.predecl) return Error("datatype already exists: " + name); 151126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen struct_def.predecl = false; 151226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen struct_def.name = name; 151340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen struct_def.file = file_being_parsed_; 151426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen // Move this struct to the back of the vector just in case it was predeclared, 1515d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen // to preserve declaration order. 1516370693a200cf2a6eb58be5d17fe6482f3e05c067Dmitry Ermolov *std::remove(structs_.vec.begin(), structs_.vec.end(), &struct_def) = &struct_def; 151740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen *dest = &struct_def; 151840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 1519d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen} 1520d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen 1521b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra PenkeCheckedError Parser::CheckClash(std::vector<FieldDef*> &fields, 1522b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke StructDef *struct_def, 1523b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke const char *suffix, 1524b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke BaseType basetype) { 1525b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke auto len = strlen(suffix); 1526b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke for (auto it = fields.begin(); it != fields.end(); ++it) { 1527b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke auto &fname = (*it)->name; 1528b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke if (fname.length() > len && 1529b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke fname.compare(fname.length() - len, len, suffix) == 0 && 1530b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke (*it)->value.type.base_type != BASE_TYPE_UTYPE) { 1531b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke auto field = struct_def->fields.Lookup( 1532b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke fname.substr(0, fname.length() - len)); 1533b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke if (field && field->value.type.base_type == basetype) 1534b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke return Error("Field " + fname + 1535b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke " would clash with generated functions for field " + 1536b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke field->name); 1537b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke } 1538b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke } 1539b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke return NoError(); 1540b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke} 1541d779308b3e48124dae91896700bf3cc12b5251e3Wouter van Oortmerssen 154246bb05d95226c72cc85242eee386465860786333Kamil Rojewskibool Parser::SupportsVectorOfUnions() const { 154346bb05d95226c72cc85242eee386465860786333Kamil Rojewski return opts.lang_to_generate != 0 && (opts.lang_to_generate & 154446bb05d95226c72cc85242eee386465860786333Kamil Rojewski ~(IDLOptions::kCpp | IDLOptions::kJs | IDLOptions::kTs | IDLOptions::kPhp)) == 0; 154546bb05d95226c72cc85242eee386465860786333Kamil Rojewski} 154646bb05d95226c72cc85242eee386465860786333Kamil Rojewski 1547321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van OortmerssenNamespace *Parser::UniqueNamespace(Namespace *ns) { 1548321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen for (auto it = namespaces_.begin(); it != namespaces_.end(); ++it) { 1549321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen if (ns->components == (*it)->components) { 1550321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen delete ns; 1551321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen return *it; 1552321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen } 1553321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen } 1554321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen namespaces_.push_back(ns); 1555321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen return ns; 1556321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen} 1557321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen 1558b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penkestatic bool compareFieldDefs(const FieldDef *a, const FieldDef *b) { 1559b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke auto a_id = atoi(a->attributes.Lookup("id")->constant.c_str()); 1560b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke auto b_id = atoi(b->attributes.Lookup("id")->constant.c_str()); 1561b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke return a_id < b_id; 1562b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke} 1563b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke 156440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseDecl() { 1565d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen std::vector<std::string> dc = doc_comment_; 156603e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen bool fixed = IsIdent("struct"); 156703e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen if (!fixed && !IsIdent("table")) return Error("declaration expected"); 156803e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen NEXT(); 156994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen std::string name = attribute_; 157040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 157140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen StructDef *struct_def; 157240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(StartStruct(name, &struct_def)); 157340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen struct_def->doc_comment = dc; 157440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen struct_def->fixed = fixed; 1575e6b79f00022aee3108427977c9823ff57154e1c6Wouter van Oortmerssen ECHECK(ParseMetaData(&struct_def->attributes)); 157640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen struct_def->sortbysize = 157740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen struct_def->attributes.Lookup("original_order") == nullptr && !fixed; 157840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT('{'); 157940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen while (token_ != '}') ECHECK(ParseField(*struct_def)); 158040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen auto force_align = struct_def->attributes.Lookup("force_align"); 158126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (fixed && force_align) { 158226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen auto align = static_cast<size_t>(atoi(force_align->constant.c_str())); 158326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen if (force_align->type.base_type != BASE_TYPE_INT || 158440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen align < struct_def->minalign || 15856862b2ff08021c7ba474334a6e2a3f3b1fc0dee5Wouter van Oortmerssen align > FLATBUFFERS_MAX_ALIGNMENT || 158626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen align & (align - 1)) 158740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("force_align must be a power of two integer ranging from the" 15886862b2ff08021c7ba474334a6e2a3f3b1fc0dee5Wouter van Oortmerssen "struct\'s natural alignment to " + 15896862b2ff08021c7ba474334a6e2a3f3b1fc0dee5Wouter van Oortmerssen NumToString(FLATBUFFERS_MAX_ALIGNMENT)); 159040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen struct_def->minalign = align; 159126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 159240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen struct_def->PadLastField(struct_def->minalign); 15939140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen // Check if this is a table that has manual id assignments 159440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen auto &fields = struct_def->fields.vec; 159540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!struct_def->fixed && fields.size()) { 15967fcbe723fc821785abfec0348023d9ebf5b4db96Wouter van Oortmerssen size_t num_id_fields = 0; 15979140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen for (auto it = fields.begin(); it != fields.end(); ++it) { 15989140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen if ((*it)->attributes.Lookup("id")) num_id_fields++; 15999140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen } 16009140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen // If any fields have ids.. 16019140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen if (num_id_fields) { 16029140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen // Then all fields must have them. 16039140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen if (num_id_fields != fields.size()) 160440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error( 160540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen "either all fields or no fields must have an 'id' attribute"); 16069140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen // Simply sort by id, then the fields are the same as if no ids had 16079140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen // been specified. 1608b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke std::sort(fields.begin(), fields.end(), compareFieldDefs); 16099140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen // Verify we have a contiguous set, and reassign vtable offsets. 16109140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen for (int i = 0; i < static_cast<int>(fields.size()); i++) { 16119140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen if (i != atoi(fields[i]->attributes.Lookup("id")->constant.c_str())) 161240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("field id\'s must be consecutive from 0, id " + 16139140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen NumToString(i) + " missing or set twice"); 16149140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen fields[i]->value.offset = FieldIndexToOffset(static_cast<voffset_t>(i)); 16159140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen } 16169140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen } 16179140144d5161124623a27cf8b8038f6e7c9bb74dWouter van Oortmerssen } 1618b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke 16199e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen ECHECK(CheckClash(fields, struct_def, UnionTypeFieldSuffix(), 16209e6c5f9f2c543a5ca608e8c1c4c9205139a87dcdWouter van Oortmerssen BASE_TYPE_UNION)); 1621b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke ECHECK(CheckClash(fields, struct_def, "Type", BASE_TYPE_UNION)); 1622b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke ECHECK(CheckClash(fields, struct_def, "_length", BASE_TYPE_VECTOR)); 1623b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke ECHECK(CheckClash(fields, struct_def, "Length", BASE_TYPE_VECTOR)); 1624b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke ECHECK(CheckClash(fields, struct_def, "_byte_vector", BASE_TYPE_STRING)); 1625b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke ECHECK(CheckClash(fields, struct_def, "ByteVector", BASE_TYPE_STRING)); 162640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT('}'); 1627321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen types_.Add(current_namespace_->GetFullyQualifiedName(struct_def->name), 16289b3d8b318a3bc9d71d08b50d723996f556557c86Wouter van Oortmerssen new Type(BASE_TYPE_STRUCT, struct_def, nullptr)); 162940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 163026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 163126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 16321a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van OortmerssenCheckedError Parser::ParseService() { 16331a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen std::vector<std::string> service_comment = doc_comment_; 16341a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen NEXT(); 16351a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen auto service_name = attribute_; 16361a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen EXPECT(kTokenIdentifier); 16371a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen auto &service_def = *new ServiceDef(); 16381a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen service_def.name = service_name; 16391a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen service_def.file = file_being_parsed_; 16401a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen service_def.doc_comment = service_comment; 1641321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen service_def.defined_namespace = current_namespace_; 1642321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen if (services_.Add(current_namespace_->GetFullyQualifiedName(service_name), 16431a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen &service_def)) 16441a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen return Error("service already exists: " + service_name); 1645e6b79f00022aee3108427977c9823ff57154e1c6Wouter van Oortmerssen ECHECK(ParseMetaData(&service_def.attributes)); 16461a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen EXPECT('{'); 16471a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen do { 16481a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen auto rpc_name = attribute_; 16491a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen EXPECT(kTokenIdentifier); 16501a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen EXPECT('('); 16511a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen Type reqtype, resptype; 16521a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen ECHECK(ParseTypeIdent(reqtype)); 16531a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen EXPECT(')'); 16541a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen EXPECT(':'); 16551a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen ECHECK(ParseTypeIdent(resptype)); 16561a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen if (reqtype.base_type != BASE_TYPE_STRUCT || reqtype.struct_def->fixed || 16571a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen resptype.base_type != BASE_TYPE_STRUCT || resptype.struct_def->fixed) 16581a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen return Error("rpc request and response types must be tables"); 16591a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen auto &rpc = *new RPCCall(); 16601a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen rpc.name = rpc_name; 16611a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen rpc.request = reqtype.struct_def; 16621a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen rpc.response = resptype.struct_def; 16631a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen if (service_def.calls.Add(rpc_name, &rpc)) 16641a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen return Error("rpc already exists: " + rpc_name); 1665e6b79f00022aee3108427977c9823ff57154e1c6Wouter van Oortmerssen ECHECK(ParseMetaData(&rpc.attributes)); 16661a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen EXPECT(';'); 16671a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen } while (token_ != '}'); 16681a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen NEXT(); 16691a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen return NoError(); 16701a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen} 16711a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen 167226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenbool Parser::SetRootType(const char *name) { 16739c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen root_struct_def_ = LookupStruct(name); 16744dcaec7938e0a9fe9f0451fe296b6151e3554275Wouter van Oortmerssen if (!root_struct_def_) 16759c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen root_struct_def_ = LookupStruct( 1676321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen current_namespace_->GetFullyQualifiedName(name)); 167781312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen return root_struct_def_ != nullptr; 167826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 167926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 1680be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssenvoid Parser::MarkGenerated() { 16813881bbd6517f97deb239f32ff5ebec8db86e902fWouter van Oortmerssen // This function marks all existing definitions as having already 16823881bbd6517f97deb239f32ff5ebec8db86e902fWouter van Oortmerssen // been generated, which signals no code for included files should be 16833881bbd6517f97deb239f32ff5ebec8db86e902fWouter van Oortmerssen // generated. 1684be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen for (auto it = enums_.vec.begin(); 1685be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen it != enums_.vec.end(); ++it) { 1686be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen (*it)->generated = true; 1687be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen } 1688be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen for (auto it = structs_.vec.begin(); 1689be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen it != structs_.vec.end(); ++it) { 16900e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath if (!(*it)->predecl) { 16910e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath (*it)->generated = true; 16920e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath } 1693be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen } 169448f37f9e0a04f2b60046dda7fef20a8b0ebc1a70Wouter van Oortmerssen for (auto it = services_.vec.begin(); 169548f37f9e0a04f2b60046dda7fef20a8b0ebc1a70Wouter van Oortmerssen it != services_.vec.end(); ++it) { 169648f37f9e0a04f2b60046dda7fef20a8b0ebc1a70Wouter van Oortmerssen (*it)->generated = true; 169748f37f9e0a04f2b60046dda7fef20a8b0ebc1a70Wouter van Oortmerssen } 1698be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen} 1699be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen 170040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseNamespace() { 170140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 1702d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen auto ns = new Namespace(); 1703321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen namespaces_.push_back(ns); // Store it here to not leak upon error. 170494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (token_ != ';') { 170594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen for (;;) { 170694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen ns->components.push_back(attribute_); 170740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 170840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is('.')) NEXT() else break; 170994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 1710d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen } 1711321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen namespaces_.pop_back(); 1712321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen current_namespace_ = UniqueNamespace(ns); 171340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(';'); 171440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 1715d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen} 1716d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen 1717b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penkestatic bool compareEnumVals(const EnumVal *a, const EnumVal* b) { 1718b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke return a->value < b->value; 1719b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke} 1720b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke 1721d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen// Best effort parsing of .proto declarations, with the aim to turn them 1722d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen// in the closest corresponding FlatBuffer equivalent. 1723d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen// We parse everything as identifiers instead of keywords, since we don't 1724d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen// want protobuf keywords to become invalid identifiers in FlatBuffers. 172540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseProtoDecl() { 172603e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen bool isextend = IsIdent("extend"); 172703e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen if (IsIdent("package")) { 1728d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen // These are identical in syntax to FlatBuffer's namespace decl. 172940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseNamespace()); 173003e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if (IsIdent("message") || isextend) { 17313ad853630c6bf76a9c8fc2a15e3fc40cd52de691Advay Mengle std::vector<std::string> struct_comment = doc_comment_; 173240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 173394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen StructDef *struct_def = nullptr; 1734321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen Namespace *parent_namespace = nullptr; 173594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (isextend) { 173640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is('.')) NEXT(); // qualified names may start with a . ? 173794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen auto id = attribute_; 173840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 173940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseNamespacing(&id, nullptr)); 174094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen struct_def = LookupCreateStruct(id, false); 174140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!struct_def) 174240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("cannot extend unknown message type: " + id); 174394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else { 174494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen std::string name = attribute_; 174540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 174640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(StartStruct(name, &struct_def)); 174794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Since message definitions can be nested, we create a new namespace. 174894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen auto ns = new Namespace(); 174994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Copy of current namespace. 1750321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen *ns = *current_namespace_; 175194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // But with current message name. 175294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen ns->components.push_back(name); 17539c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen ns->from_table++; 1754321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen parent_namespace = current_namespace_; 1755321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen current_namespace_ = UniqueNamespace(ns); 175694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 175794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen struct_def->doc_comment = struct_comment; 175840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseProtoFields(struct_def, isextend, false)); 175994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (!isextend) { 1760321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen current_namespace_ = parent_namespace; 176194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 176240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is(';')) NEXT(); 176303e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if (IsIdent("enum")) { 176494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // These are almost the same, just with different terminator: 176540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EnumDef *enum_def; 176640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseEnum(false, &enum_def)); 176740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is(';')) NEXT(); 176894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Protobuf allows them to be specified in any order, so sort afterwards. 176940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen auto &v = enum_def->vals.vec; 1770d779308b3e48124dae91896700bf3cc12b5251e3Wouter van Oortmerssen std::sort(v.begin(), v.end(), compareEnumVals); 1771b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke 177294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Temp: remove any duplicates, as .fbs files can't handle them. 177394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen for (auto it = v.begin(); it != v.end(); ) { 177494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (it != v.begin() && it[0]->value == it[-1]->value) it = v.erase(it); 177594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen else ++it; 177694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 177703e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if (IsIdent("syntax")) { // Skip these. 177840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 177940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT('='); 178040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenStringConstant); 178140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(';'); 178203e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if (IsIdent("option")) { // Skip these. 178340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseProtoOption()); 178440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(';'); 178503e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if (IsIdent("service")) { // Skip these. 178640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 178740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 178840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseProtoCurliesOrIdent()); 178994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else { 179040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("don\'t know how to parse .proto declaration starting with " + 179194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen TokenToStringId(token_)); 179294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 179340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 179494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen} 179594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen 179640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseProtoFields(StructDef *struct_def, bool isextend, 179740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen bool inside_oneof) { 179840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT('{'); 179994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen while (token_ != '}') { 180003e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen if (IsIdent("message") || IsIdent("extend") || IsIdent("enum")) { 180194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Nested declarations. 180240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseProtoDecl()); 180303e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if (IsIdent("extensions")) { // Skip these. 180440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 180540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIntegerConstant); 180640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is(kTokenIdentifier)) { 180740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); // to 180840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); // num 180994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 181040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(';'); 181103e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if (IsIdent("option")) { // Skip these. 181240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseProtoOption()); 181340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(';'); 181403e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if (IsIdent("reserved")) { // Skip these. 181540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 18169c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen while (!Is(';')) { NEXT(); } // A variety of formats, just skip. 18179c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen NEXT(); 181894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else { 181994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen std::vector<std::string> field_comment = doc_comment_; 182094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Parse the qualifier. 182194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen bool required = false; 182294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen bool repeated = false; 182394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen bool oneof = false; 182494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (!inside_oneof) { 182503e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen if (IsIdent("optional")) { 18262abe24b9ddd22fd095d96f002fb8c16b4edc36d2Wouter van Oortmerssen // This is the default. 182703e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen NEXT(); 182803e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if (IsIdent("required")) { 18292abe24b9ddd22fd095d96f002fb8c16b4edc36d2Wouter van Oortmerssen required = true; 183003e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen NEXT(); 183103e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if (IsIdent("repeated")) { 18322abe24b9ddd22fd095d96f002fb8c16b4edc36d2Wouter van Oortmerssen repeated = true; 183303e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen NEXT(); 183403e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if (IsIdent("oneof")) { 183594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen oneof = true; 183603e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen NEXT(); 18372abe24b9ddd22fd095d96f002fb8c16b4edc36d2Wouter van Oortmerssen } else { 183894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // can't error, proto3 allows decls without any of the above. 18392abe24b9ddd22fd095d96f002fb8c16b4edc36d2Wouter van Oortmerssen } 184094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 184194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen StructDef *anonymous_struct = nullptr; 184294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen Type type; 184303e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen if (IsIdent("group") || oneof) { 184403e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen if (!oneof) NEXT(); 184594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen auto name = "Anonymous" + NumToString(anonymous_counter++); 184640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(StartStruct(name, &anonymous_struct)); 184794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen type = Type(BASE_TYPE_STRUCT, anonymous_struct); 184894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else { 184940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseTypeFromProtoType(&type)); 185094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 185194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Repeated elements get mapped to a vector. 185294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (repeated) { 185394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen type.element = type.base_type; 185494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen type.base_type = BASE_TYPE_VECTOR; 18559c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen if (type.element == BASE_TYPE_VECTOR) { 18569c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen // We have a vector or vectors, which FlatBuffers doesn't support. 18579c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen // For now make it a vector of string (since the source is likely 18589c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen // "repeated bytes"). 18599c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen // TODO(wvo): A better solution would be to wrap this in a table. 18609c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen type.element = BASE_TYPE_STRING; 18619c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen } 186294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 186394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen std::string name = attribute_; 186403e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen EXPECT(kTokenIdentifier); 186594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (!oneof) { 18662abe24b9ddd22fd095d96f002fb8c16b4edc36d2Wouter van Oortmerssen // Parse the field id. Since we're just translating schemas, not 18672abe24b9ddd22fd095d96f002fb8c16b4edc36d2Wouter van Oortmerssen // any kind of binary compatibility, we can safely ignore these, and 18682abe24b9ddd22fd095d96f002fb8c16b4edc36d2Wouter van Oortmerssen // assign our own. 186940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT('='); 187040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIntegerConstant); 187194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 187240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen FieldDef *field = nullptr; 187394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (isextend) { 187494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // We allow a field to be re-defined when extending. 187594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // TODO: are there situations where that is problematic? 187640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen field = struct_def->fields.Lookup(name); 187794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 187840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!field) ECHECK(AddField(*struct_def, name, type, &field)); 187940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen field->doc_comment = field_comment; 188040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!IsScalar(type.base_type)) field->required = required; 188194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // See if there's a default specified. 188240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is('[')) { 188340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 188440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen for (;;) { 188594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen auto key = attribute_; 188640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseProtoKey()); 188740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT('='); 188894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen auto val = attribute_; 188940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseProtoCurliesOrIdent()); 189094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (key == "default") { 189194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Temp: skip non-numeric defaults (enums). 189294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen auto numeric = strpbrk(val.c_str(), "0123456789-+."); 189394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (IsScalar(type.base_type) && numeric == val.c_str()) 189440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen field->value.constant = val; 189594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else if (key == "deprecated") { 189640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen field->deprecated = val == "true"; 189794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 189840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!Is(',')) break; 189940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 190040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } 190140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(']'); 190294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 190394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (anonymous_struct) { 190440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseProtoFields(anonymous_struct, false, oneof)); 190540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is(';')) NEXT(); 190694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else { 190740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(';'); 1908d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen } 1909d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen } 191094680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 191140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 191240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 191394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen} 191494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen 191540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseProtoKey() { 191694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (token_ == '(') { 191740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 191894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Skip "(a.b)" style custom attributes. 191940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen while (token_ == '.' || token_ == kTokenIdentifier) NEXT(); 192040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(')'); 192140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen while (Is('.')) { NEXT(); EXPECT(kTokenIdentifier); } 192294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } else { 192340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 192494680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 192540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 192694680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen} 192794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen 192840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseProtoCurliesOrIdent() { 192940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is('{')) { 193040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 193194680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen for (int nesting = 1; nesting; ) { 193294680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen if (token_ == '{') nesting++; 193394680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen else if (token_ == '}') nesting--; 193440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 193594680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 1936d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen } else { 193740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); // Any single token. 1938d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen } 193940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 1940d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen} 1941d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen 194240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseProtoOption() { 194340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 194440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseProtoKey()); 194540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT('='); 194640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseProtoCurliesOrIdent()); 194740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 194894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen} 194994680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen 1950d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen// Parse a protobuf type, and map it to the corresponding FlatBuffer one. 195140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van OortmerssenCheckedError Parser::ParseTypeFromProtoType(Type *type) { 195269776b9e7eddd7aa9388f67d06f668e257f02704Wouter van Oortmerssen struct type_lookup { const char *proto_type; BaseType fb_type, element; }; 1953d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen static type_lookup lookup[] = { 195469776b9e7eddd7aa9388f67d06f668e257f02704Wouter van Oortmerssen { "float", BASE_TYPE_FLOAT, BASE_TYPE_NONE }, 195569776b9e7eddd7aa9388f67d06f668e257f02704Wouter van Oortmerssen { "double", BASE_TYPE_DOUBLE, BASE_TYPE_NONE }, 195669776b9e7eddd7aa9388f67d06f668e257f02704Wouter van Oortmerssen { "int32", BASE_TYPE_INT, BASE_TYPE_NONE }, 195769776b9e7eddd7aa9388f67d06f668e257f02704Wouter van Oortmerssen { "int64", BASE_TYPE_LONG, BASE_TYPE_NONE }, 195869776b9e7eddd7aa9388f67d06f668e257f02704Wouter van Oortmerssen { "uint32", BASE_TYPE_UINT, BASE_TYPE_NONE }, 195969776b9e7eddd7aa9388f67d06f668e257f02704Wouter van Oortmerssen { "uint64", BASE_TYPE_ULONG, BASE_TYPE_NONE }, 196069776b9e7eddd7aa9388f67d06f668e257f02704Wouter van Oortmerssen { "sint32", BASE_TYPE_INT, BASE_TYPE_NONE }, 196169776b9e7eddd7aa9388f67d06f668e257f02704Wouter van Oortmerssen { "sint64", BASE_TYPE_LONG, BASE_TYPE_NONE }, 196269776b9e7eddd7aa9388f67d06f668e257f02704Wouter van Oortmerssen { "fixed32", BASE_TYPE_UINT, BASE_TYPE_NONE }, 196369776b9e7eddd7aa9388f67d06f668e257f02704Wouter van Oortmerssen { "fixed64", BASE_TYPE_ULONG, BASE_TYPE_NONE }, 196469776b9e7eddd7aa9388f67d06f668e257f02704Wouter van Oortmerssen { "sfixed32", BASE_TYPE_INT, BASE_TYPE_NONE }, 196569776b9e7eddd7aa9388f67d06f668e257f02704Wouter van Oortmerssen { "sfixed64", BASE_TYPE_LONG, BASE_TYPE_NONE }, 196669776b9e7eddd7aa9388f67d06f668e257f02704Wouter van Oortmerssen { "bool", BASE_TYPE_BOOL, BASE_TYPE_NONE }, 196769776b9e7eddd7aa9388f67d06f668e257f02704Wouter van Oortmerssen { "string", BASE_TYPE_STRING, BASE_TYPE_NONE }, 196869776b9e7eddd7aa9388f67d06f668e257f02704Wouter van Oortmerssen { "bytes", BASE_TYPE_VECTOR, BASE_TYPE_UCHAR }, 196969776b9e7eddd7aa9388f67d06f668e257f02704Wouter van Oortmerssen { nullptr, BASE_TYPE_NONE, BASE_TYPE_NONE } 1970d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen }; 1971d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen for (auto tl = lookup; tl->proto_type; tl++) { 1972d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen if (attribute_ == tl->proto_type) { 197340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen type->base_type = tl->fb_type; 197469776b9e7eddd7aa9388f67d06f668e257f02704Wouter van Oortmerssen type->element = tl->element; 197540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 197640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 1977d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen } 1978d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen } 197940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (Is('.')) NEXT(); // qualified names may start with a . ? 198040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseTypeIdent(*type)); 198140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 1982d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen} 1983d38b9af243d8dcfc53ab69c79e0ce404759240d4Wouter van Oortmerssen 198413d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra PenkeCheckedError Parser::SkipAnyJsonValue() { 198513d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke switch (token_) { 19868f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen case '{': { 1987a8923222033763f1a74f836c656af19d9f620378Stewart Miles size_t fieldn_outer = 0; 1988a8923222033763f1a74f836c656af19d9f620378Stewart Miles return ParseTableDelimiters(fieldn_outer, nullptr, 1989a8923222033763f1a74f836c656af19d9f620378Stewart Miles [](const std::string &, 1990a8923222033763f1a74f836c656af19d9f620378Stewart Miles size_t &fieldn, const StructDef *, 1991a8923222033763f1a74f836c656af19d9f620378Stewart Miles void *state) -> CheckedError { 1992a8923222033763f1a74f836c656af19d9f620378Stewart Miles auto *parser = static_cast<Parser *>(state); 1993a8923222033763f1a74f836c656af19d9f620378Stewart Miles ECHECK(parser->SkipAnyJsonValue()); 1994a8923222033763f1a74f836c656af19d9f620378Stewart Miles fieldn++; 1995a8923222033763f1a74f836c656af19d9f620378Stewart Miles return NoError(); 1996a8923222033763f1a74f836c656af19d9f620378Stewart Miles }, 1997a8923222033763f1a74f836c656af19d9f620378Stewart Miles this); 19988f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen } 19998f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen case '[': { 20008f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen size_t count = 0; 2001a8923222033763f1a74f836c656af19d9f620378Stewart Miles return ParseVectorDelimiters(count, [](size_t &, 2002a8923222033763f1a74f836c656af19d9f620378Stewart Miles void *state) -> CheckedError { 2003a8923222033763f1a74f836c656af19d9f620378Stewart Miles return static_cast<Parser *>(state)->SkipAnyJsonValue(); 2004a8923222033763f1a74f836c656af19d9f620378Stewart Miles }, 2005a8923222033763f1a74f836c656af19d9f620378Stewart Miles this); 20068f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen } 200713d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke case kTokenStringConstant: 200813d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke case kTokenIntegerConstant: 200913d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke case kTokenFloatConstant: 201003e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen NEXT(); 2011a2b1bfc1075e8e5ae7b347a04cbb796524f2c5c9rouzier break; 201213d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke default: 201303e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen if (IsIdent("true") || IsIdent("false") || IsIdent("null")) { NEXT(); } 201403e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen else return TokenError(); 201513d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke } 201613d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke return NoError(); 201713d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke} 201813d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke 20198f864aad7b875d645236be59ab1037051b12ba10Wouter van OortmerssenCheckedError Parser::ParseFlexBufferValue(flexbuffers::Builder *builder) { 20208f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen switch (token_) { 20218f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen case '{': { 2022a8923222033763f1a74f836c656af19d9f620378Stewart Miles std::pair<Parser *, flexbuffers::Builder *> parser_and_builder_state( 2023a8923222033763f1a74f836c656af19d9f620378Stewart Miles this, builder); 20248f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen auto start = builder->StartMap(); 2025a8923222033763f1a74f836c656af19d9f620378Stewart Miles size_t fieldn_outer = 0; 2026a8923222033763f1a74f836c656af19d9f620378Stewart Miles auto err = ParseTableDelimiters(fieldn_outer, nullptr, 2027a8923222033763f1a74f836c656af19d9f620378Stewart Miles [](const std::string &name, 2028a8923222033763f1a74f836c656af19d9f620378Stewart Miles size_t &fieldn, const StructDef *, 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 auto *parser = parser_and_builder->first; 2034a8923222033763f1a74f836c656af19d9f620378Stewart Miles auto *current_builder = parser_and_builder->second; 2035a8923222033763f1a74f836c656af19d9f620378Stewart Miles current_builder->Key(name); 2036a8923222033763f1a74f836c656af19d9f620378Stewart Miles ECHECK(parser->ParseFlexBufferValue(current_builder)); 2037a8923222033763f1a74f836c656af19d9f620378Stewart Miles fieldn++; 2038a8923222033763f1a74f836c656af19d9f620378Stewart Miles return NoError(); 2039a8923222033763f1a74f836c656af19d9f620378Stewart Miles }, 2040a8923222033763f1a74f836c656af19d9f620378Stewart Miles &parser_and_builder_state); 20418f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen ECHECK(err); 20428f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen builder->EndMap(start); 20438f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen break; 2044cbab26673b99b0a5dff9907fbe08e1efc211f1ffNalinichandra Penke } 20458f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen case '[':{ 20468f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen auto start = builder->StartVector(); 20478f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen size_t count = 0; 2048a8923222033763f1a74f836c656af19d9f620378Stewart Miles std::pair<Parser *, flexbuffers::Builder *> parser_and_builder_state( 2049a8923222033763f1a74f836c656af19d9f620378Stewart Miles this, builder); 2050a8923222033763f1a74f836c656af19d9f620378Stewart Miles ECHECK(ParseVectorDelimiters(count, [](size_t &, 2051a8923222033763f1a74f836c656af19d9f620378Stewart Miles void *state) -> CheckedError { 2052a8923222033763f1a74f836c656af19d9f620378Stewart Miles auto *parser_and_builder = 2053a8923222033763f1a74f836c656af19d9f620378Stewart Miles static_cast<std::pair<Parser *, flexbuffers::Builder *> *>( 2054a8923222033763f1a74f836c656af19d9f620378Stewart Miles state); 2055a8923222033763f1a74f836c656af19d9f620378Stewart Miles return parser_and_builder->first->ParseFlexBufferValue( 2056a8923222033763f1a74f836c656af19d9f620378Stewart Miles parser_and_builder->second); 2057a8923222033763f1a74f836c656af19d9f620378Stewart Miles }, 2058a8923222033763f1a74f836c656af19d9f620378Stewart Miles &parser_and_builder_state)); 20598f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen builder->EndVector(start, false, false); 20608f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen break; 2061cbab26673b99b0a5dff9907fbe08e1efc211f1ffNalinichandra Penke } 20628f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen case kTokenStringConstant: 20638f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen builder->String(attribute_); 20648f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen EXPECT(kTokenStringConstant); 20658f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen break; 20668f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen case kTokenIntegerConstant: 20678f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen builder->Int(StringToInt(attribute_.c_str())); 20688f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen EXPECT(kTokenIntegerConstant); 20698f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen break; 20708f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen case kTokenFloatConstant: 20718f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen builder->Double(strtod(attribute_.c_str(), nullptr)); 20728f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen EXPECT(kTokenFloatConstant); 20738f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen break; 20748f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen default: 207503e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen if (IsIdent("true")) { builder->Bool(true); NEXT(); } 207603e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen else if (IsIdent("false")) { builder->Bool(false); NEXT(); } 207703e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen else if (IsIdent("null")) { builder->Null(); NEXT(); } 207803e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen else return TokenError(); 207913d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke } 208013d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke return NoError(); 208113d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke} 208213d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke 20838f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssenbool Parser::ParseFlexBuffer(const char *source, const char *source_filename, 20848f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen flexbuffers::Builder *builder) { 20858f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen auto ok = !StartParseFile(source, source_filename).Check() && 20868f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen !ParseFlexBufferValue(builder).Check(); 20878f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen if (ok) builder->Finish(); 20888f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen return ok; 208913d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke} 209013d0594b4c8cd6677ddb43ecdbd2d7d3300b6208Nalinichandra Penke 209130642c5a6f0fe2728d5b05cd272880d325c18cf6Wouter van Oortmerssenbool Parser::Parse(const char *source, const char **include_paths, 209230642c5a6f0fe2728d5b05cd272880d325c18cf6Wouter van Oortmerssen const char *source_filename) { 20930e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath return !ParseRoot(source, include_paths, source_filename).Check(); 209440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen} 209540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen 20968f864aad7b875d645236be59ab1037051b12ba10Wouter van OortmerssenCheckedError Parser::StartParseFile(const char *source, const char *source_filename) { 20978f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen file_being_parsed_ = source_filename ? source_filename : ""; 20988f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen source_ = cursor_ = source; 20998f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen line_ = 1; 21008f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen error_.clear(); 21018f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen ECHECK(SkipByteOrderMark()); 21028f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen NEXT(); 21038f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen if (Is(kTokenEof)) 21048f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen return Error("input file is empty"); 21058f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen return NoError(); 21068f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen} 21078f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen 21080e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrathCheckedError Parser::ParseRoot(const char *source, const char **include_paths, 21090e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath const char *source_filename) { 21100e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath ECHECK(DoParse(source, include_paths, source_filename, nullptr)); 21110e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath 21120e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath // Check that all types were defined. 21139c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen for (auto it = structs_.vec.begin(); it != structs_.vec.end(); ) { 21149c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen auto &struct_def = **it; 21159c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen if (struct_def.predecl) { 21169c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen if (opts.proto_mode) { 21179c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen // Protos allow enums to be used before declaration, so check if that 21189c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen // is the case here. 21199c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen EnumDef *enum_def = nullptr; 21209c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen for (size_t components = struct_def.defined_namespace-> 21219c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen components.size() + 1; 21229c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen components && !enum_def; components--) { 21239c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen auto qualified_name = struct_def.defined_namespace-> 21249c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen GetFullyQualifiedName(struct_def.name, 21259c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen components - 1); 21269c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen enum_def = LookupEnum(qualified_name); 21279c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen } 21289c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen if (enum_def) { 21299c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen // This is pretty slow, but a simple solution for now. 21309c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen auto initial_count = struct_def.refcount; 21319c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen for (auto struct_it = structs_.vec.begin(); 21329c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen struct_it != structs_.vec.end(); 21339c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen ++struct_it) { 21349c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen auto &sd = **struct_it; 21359c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen for (auto field_it = sd.fields.vec.begin(); 21369c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen field_it != sd.fields.vec.end(); 21379c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen ++field_it) { 21389c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen auto &field = **field_it; 21399c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen if (field.value.type.struct_def == &struct_def) { 21409c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen field.value.type.struct_def = nullptr; 21419c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen field.value.type.enum_def = enum_def; 21429c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen auto &bt = field.value.type.base_type == BASE_TYPE_VECTOR 21439c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen ? field.value.type.element 21449c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen : field.value.type.base_type; 21459c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen assert(bt == BASE_TYPE_STRUCT); 21469c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen bt = enum_def->underlying_type.base_type; 21479c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen struct_def.refcount--; 21489c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen enum_def->refcount++; 21499c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen } 21509c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen } 21519c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen } 21529c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen if (struct_def.refcount) 21539c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen return Error("internal: " + NumToString(struct_def.refcount) + "/" + 21549c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen NumToString(initial_count) + 21559c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen " use(s) of pre-declaration enum not accounted for: " 21569c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen + enum_def->name); 21579c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen structs_.dict.erase(structs_.dict.find(struct_def.name)); 21589c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen it = structs_.vec.erase(it); 21599c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen delete &struct_def; 21609c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen continue; // Skip error. 21619c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen } 21629c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen } 21639c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen auto err = "type referenced but not defined (check namespace): " + 21649c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen struct_def.name; 21659c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen if (struct_def.original_location) 21669c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen err += ", originally at: " + *struct_def.original_location; 21679c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen return Error(err); 21680e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath } 21699c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen ++it; 21700e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath } 21710e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath 21720e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath // This check has to happen here and not earlier, because only now do we 21730e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath // know for sure what the type of these are. 21740e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath for (auto it = enums_.vec.begin(); it != enums_.vec.end(); ++it) { 21750e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath auto &enum_def = **it; 21760e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath if (enum_def.is_union) { 21770e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath for (auto val_it = enum_def.vals.vec.begin(); 21780e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath val_it != enum_def.vals.vec.end(); 21790e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath ++val_it) { 21800e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath auto &val = **val_it; 218146bb05d95226c72cc85242eee386465860786333Kamil Rojewski if (!SupportsVectorOfUnions() && 21820e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath val.union_type.struct_def && val.union_type.struct_def->fixed) 21830e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath return Error( 21840e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath "only tables can be union elements in the generated language: " 21850e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath + val.name); 21860e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath } 21870e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath } 21880e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath } 21890e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath return NoError(); 21900e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath} 21910e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath 21920e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrathCheckedError Parser::DoParse(const char *source, 21930e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath const char **include_paths, 21940e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath const char *source_filename, 21950e85eeef2c6ed3eb9ec201aaea6caa62612a8522Robbie McElrath const char *include_filename) { 2196df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez if (source_filename && 2197642254bee60e7c7cd793f8f636a9351f883ea97aPavel Kalinnikov included_files_.find(source_filename) == included_files_.end()) { 2198642254bee60e7c7cd793f8f636a9351f883ea97aPavel Kalinnikov included_files_[source_filename] = include_filename ? include_filename : ""; 2199df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez files_included_per_file_[source_filename] = std::set<std::string>(); 2200df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez } 2201df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez if (!include_paths) { 22021e6f8f5b8c4d0407d7db750858e7863e07091958Wouter van Oortmerssen static const char *current_directory[] = { "", nullptr }; 2203df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez include_paths = current_directory; 2204df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez } 2205fea6b525ee57bf61d307abc16ade8d9041a3a01dYonggang Li field_stack_.clear(); 220626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen builder_.Clear(); 220794680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen // Start with a blank namespace just in case this file doesn't have one. 2208321a1c9dc0bb2205feb1bb9fd079546403aa852fWouter van Oortmerssen current_namespace_ = empty_namespace_; 2209e7e4dc755d98ea33ef8e0dedb86f6cc466a89074Louis-Paul CORDIER 22108f864aad7b875d645236be59ab1037051b12ba10Wouter van Oortmerssen ECHECK(StartParseFile(source, source_filename)); 2211e7e4dc755d98ea33ef8e0dedb86f6cc466a89074Louis-Paul CORDIER 221240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // Includes must come before type declarations: 221340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen for (;;) { 221440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // Parse pre-include proto statements if any: 221540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (opts.proto_mode && 221640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen (attribute_ == "option" || attribute_ == "syntax" || 221740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen attribute_ == "package")) { 221840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseProtoDecl()); 221903e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if (IsIdent("native_include")) { 22203f936c5655d2e802db101c73c42ebaab4ed476aaWouter van Oortmerssen NEXT(); 2221a8923222033763f1a74f836c656af19d9f620378Stewart Miles vector_emplace_back(&native_included_files_, attribute_); 22223f936c5655d2e802db101c73c42ebaab4ed476aaWouter van Oortmerssen EXPECT(kTokenStringConstant); 222303e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if (IsIdent("include") || (opts.proto_mode && IsIdent("import"))) { 222440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 222540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (opts.proto_mode && attribute_ == "public") NEXT(); 2226aaf5598a032314767721fead8a0acf9ca37c5e09Wouter van Oortmerssen auto name = flatbuffers::PosixPath(attribute_.c_str()); 222740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenStringConstant); 222840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // Look for the file in include_paths. 222940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen std::string filepath; 223040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen for (auto paths = include_paths; paths && *paths; paths++) { 223140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen filepath = flatbuffers::ConCatPathFileName(*paths, name); 223240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if(FileExists(filepath.c_str())) break; 2233be894f09df2383844d6c19b1d173fec105451e0fWouter van Oortmerssen } 223440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (filepath.empty()) 223540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("unable to locate include file: " + name); 223640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (source_filename) 223740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen files_included_per_file_[source_filename].insert(filepath); 2238642254bee60e7c7cd793f8f636a9351f883ea97aPavel Kalinnikov if (included_files_.find(filepath) == included_files_.end()) { 223940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // We found an include file that we have not parsed yet. 224040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // Load it and parse it. 224140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen std::string contents; 224240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!LoadFile(filepath.c_str(), true, &contents)) 224340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("unable to load include file: " + name); 224422743ca45a3f835df423eb608837022a4a57dcc0Wouter van Oortmerssen ECHECK(DoParse(contents.c_str(), include_paths, filepath.c_str(), 224522743ca45a3f835df423eb608837022a4a57dcc0Wouter van Oortmerssen name.c_str())); 224640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // We generally do not want to output code for any included files: 224740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!opts.generate_all) MarkGenerated(); 2248432e7582c65aeb65b582724f601fc3202ecf9017Wouter van Oortmerssen // Reset these just in case the included file had them, and the 2249dca33ddb75a035344cb6ea3e38b9123dcce9b5fdWouter van Oortmerssen // parent doesn't. 2250dca33ddb75a035344cb6ea3e38b9123dcce9b5fdWouter van Oortmerssen root_struct_def_ = nullptr; 2251432e7582c65aeb65b582724f601fc3202ecf9017Wouter van Oortmerssen file_identifier_.clear(); 2252432e7582c65aeb65b582724f601fc3202ecf9017Wouter van Oortmerssen file_extension_.clear(); 225340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // This is the easiest way to continue this file after an include: 225440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // instead of saving and restoring all the state, we simply start the 225540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // file anew. This will cause it to encounter the same include 225640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // statement again, but this time it will skip it, because it was 225740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // entered into included_files_. 225840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // This is recursive, but only go as deep as the number of include 225940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // statements. 226022743ca45a3f835df423eb608837022a4a57dcc0Wouter van Oortmerssen return DoParse(source, include_paths, source_filename, include_filename); 226126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 226240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(';'); 226340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } else { 226440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen break; 226526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 226640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } 226740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen // Now parse all other kinds of declarations: 226840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen while (token_ != kTokenEof) { 226940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (opts.proto_mode) { 227040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseProtoDecl()); 227103e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if (IsIdent("namespace")) { 227240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseNamespace()); 227340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } else if (token_ == '{') { 227440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!root_struct_def_) 227540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("no root type set to parse json with"); 227640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (builder_.GetSize()) { 227740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("cannot have more than one json object in a file"); 227894680f5483593b1a48c79b516d153fd432b3f2e8Wouter van Oortmerssen } 227940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen uoffset_t toff; 228040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseTable(*root_struct_def_, nullptr, &toff)); 228140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen builder_.Finish(Offset<Table>(toff), 228240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen file_identifier_.length() ? file_identifier_.c_str() : nullptr); 228303e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if (IsIdent("enum")) { 228440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseEnum(false, nullptr)); 228503e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if (IsIdent("union")) { 228640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseEnum(true, nullptr)); 228703e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if (IsIdent("root_type")) { 228840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 228940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen auto root_type = attribute_; 229040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenIdentifier); 229140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseNamespacing(&root_type, nullptr)); 229240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (!SetRootType(root_type.c_str())) 229340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("unknown root type: " + root_type); 229440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (root_struct_def_->fixed) 229540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("root type must be a table"); 229640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(';'); 229703e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if (IsIdent("file_identifier")) { 229840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 229940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen file_identifier_ = attribute_; 230040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenStringConstant); 230140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen if (file_identifier_.length() != 230240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen FlatBufferBuilder::kFileIdentifierLength) 230340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("file_identifier must be exactly " + 230440a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NumToString(FlatBufferBuilder::kFileIdentifierLength) + 230540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen " characters"); 230640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(';'); 230703e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if (IsIdent("file_extension")) { 230840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 230940a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen file_extension_ = attribute_; 231040a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenStringConstant); 231140a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(';'); 231203e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if(IsIdent("include")) { 231340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return Error("includes must come before declarations"); 231403e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if(IsIdent("attribute")) { 231540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen NEXT(); 231640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen auto name = attribute_; 231740a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(kTokenStringConstant); 231840a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen EXPECT(';'); 231972fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen known_attributes_[name] = false; 232003e2899985849dbffa3178ae76c00288f7aca79bWouter van Oortmerssen } else if (IsIdent("rpc_service")) { 23211a63eb46bbbb9a0e0d269b2fc0ec31c552871128Wouter van Oortmerssen ECHECK(ParseService()); 232240a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } else { 232340a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen ECHECK(ParseDecl()); 232426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen } 232540a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen } 232640a33b1d0683d3d732620b7f8adb6c34678a5910Wouter van Oortmerssen return NoError(); 232726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} 232826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen 2329df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinezstd::set<std::string> Parser::GetIncludedFilesRecursive( 2330df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez const std::string &file_name) const { 2331df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez std::set<std::string> included_files; 2332df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez std::list<std::string> to_process; 2333df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez 2334df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez if (file_name.empty()) return included_files; 2335df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez to_process.push_back(file_name); 2336df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez 2337df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez while (!to_process.empty()) { 2338df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez std::string current = to_process.front(); 2339df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez to_process.pop_front(); 2340df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez included_files.insert(current); 2341df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez 2342a8923222033763f1a74f836c656af19d9f620378Stewart Miles // Workaround the lack of const accessor in C++98 maps. 2343a8923222033763f1a74f836c656af19d9f620378Stewart Miles auto &new_files = 2344a8923222033763f1a74f836c656af19d9f620378Stewart Miles (*const_cast<std::map<std::string, std::set<std::string>> *>( 2345a8923222033763f1a74f836c656af19d9f620378Stewart Miles &files_included_per_file_))[current]; 2346df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez for (auto it = new_files.begin(); it != new_files.end(); ++it) { 2347df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez if (included_files.find(*it) == included_files.end()) 2348df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez to_process.push_back(*it); 2349df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez } 2350df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez } 2351df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez 2352df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez return included_files; 2353df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez} 2354df4909e5f6b7e60a90b32973567d24b90608c6fbGabriel Martinez 235581312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen// Schema serialization functionality: 235681312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen 2357b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penketemplate<typename T> bool compareName(const T* a, const T* b) { 2358df0991b7ded0533554d3665e782273b6c8736376Xun Liu return a->defined_namespace->GetFullyQualifiedName(a->name) 2359df0991b7ded0533554d3665e782273b6c8736376Xun Liu < b->defined_namespace->GetFullyQualifiedName(b->name); 2360b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke} 2361b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke 236281312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssentemplate<typename T> void AssignIndices(const std::vector<T *> &defvec) { 236381312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen // Pre-sort these vectors, such that we can set the correct indices for them. 236481312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen auto vec = defvec; 2365b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke std::sort(vec.begin(), vec.end(), compareName<T>); 236681312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen for (int i = 0; i < static_cast<int>(vec.size()); i++) vec[i]->index = i; 236781312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen} 236881312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen 236981312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssenvoid Parser::Serialize() { 237081312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen builder_.Clear(); 237181312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen AssignIndices(structs_.vec); 237281312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen AssignIndices(enums_.vec); 237381312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen std::vector<Offset<reflection::Object>> object_offsets; 237481312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen for (auto it = structs_.vec.begin(); it != structs_.vec.end(); ++it) { 237572fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen auto offset = (*it)->Serialize(&builder_, *this); 237681312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen object_offsets.push_back(offset); 237781312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen (*it)->serialized_location = offset.o; 237881312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen } 237981312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen std::vector<Offset<reflection::Enum>> enum_offsets; 238081312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen for (auto it = enums_.vec.begin(); it != enums_.vec.end(); ++it) { 238172fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen auto offset = (*it)->Serialize(&builder_, *this); 238281312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen enum_offsets.push_back(offset); 238381312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen (*it)->serialized_location = offset.o; 238481312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen } 238581312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen auto schema_offset = reflection::CreateSchema( 238681312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen builder_, 238781312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen builder_.CreateVectorOfSortedTables(&object_offsets), 238881312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen builder_.CreateVectorOfSortedTables(&enum_offsets), 238981312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen builder_.CreateString(file_identifier_), 239081312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen builder_.CreateString(file_extension_), 239136c7e9a9625b65332e16615897f1ef9c1b99e203Wouter van Oortmerssen root_struct_def_ 239236c7e9a9625b65332e16615897f1ef9c1b99e203Wouter van Oortmerssen ? root_struct_def_->serialized_location 239336c7e9a9625b65332e16615897f1ef9c1b99e203Wouter van Oortmerssen : 0); 239481312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen builder_.Finish(schema_offset, reflection::SchemaIdentifier()); 239581312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen} 239681312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen 239772fc45aa6acbc11052c6baa462fac26c5075392aWouter van OortmerssenOffset<reflection::Object> StructDef::Serialize(FlatBufferBuilder *builder, 239872fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen const Parser &parser) const { 239981312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen std::vector<Offset<reflection::Field>> field_offsets; 240081312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen for (auto it = fields.vec.begin(); it != fields.vec.end(); ++it) { 2401622b8d05cf69cc26babc6a043d1f7a4153755652Wouter van Oortmerssen field_offsets.push_back( 2402622b8d05cf69cc26babc6a043d1f7a4153755652Wouter van Oortmerssen (*it)->Serialize(builder, 240372fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen static_cast<uint16_t>(it - fields.vec.begin()), parser)); 240481312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen } 2405df0991b7ded0533554d3665e782273b6c8736376Xun Liu auto qualified_name = defined_namespace->GetFullyQualifiedName(name); 240681312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen return reflection::CreateObject(*builder, 2407df0991b7ded0533554d3665e782273b6c8736376Xun Liu builder->CreateString(qualified_name), 240881312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen builder->CreateVectorOfSortedTables( 240981312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen &field_offsets), 2410cb2b2be54eb52fb009f30f5ca300165a95fa5df6Wouter van Oortmerssen fixed, 2411cb2b2be54eb52fb009f30f5ca300165a95fa5df6Wouter van Oortmerssen static_cast<int>(minalign), 241272fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen static_cast<int>(bytesize), 24131fb6b9ee6f817befae08f39549d5bd80de3931ccWouter van Oortmerssen SerializeAttributes(builder, parser), 24141fb6b9ee6f817befae08f39549d5bd80de3931ccWouter van Oortmerssen parser.opts.binary_schema_comments 24151fb6b9ee6f817befae08f39549d5bd80de3931ccWouter van Oortmerssen ? builder->CreateVectorOfStrings( 24161fb6b9ee6f817befae08f39549d5bd80de3931ccWouter van Oortmerssen doc_comment) 24171fb6b9ee6f817befae08f39549d5bd80de3931ccWouter van Oortmerssen : 0); 241881312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen} 241981312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen 242081312c21281430449aef20f7a71ad9e0962791d3Wouter van OortmerssenOffset<reflection::Field> FieldDef::Serialize(FlatBufferBuilder *builder, 242172fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen uint16_t id, 242272fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen const Parser &parser) const { 242381312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen return reflection::CreateField(*builder, 242481312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen builder->CreateString(name), 242581312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen value.type.Serialize(builder), 242681312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen id, 242781312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen value.offset, 242881312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen IsInteger(value.type.base_type) 242981312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen ? StringToInt(value.constant.c_str()) 243081312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen : 0, 243181312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen IsFloat(value.type.base_type) 243281312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen ? strtod(value.constant.c_str(), nullptr) 243381312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen : 0.0, 243481312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen deprecated, 243581312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen required, 243672fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen key, 24371fb6b9ee6f817befae08f39549d5bd80de3931ccWouter van Oortmerssen SerializeAttributes(builder, parser), 24381fb6b9ee6f817befae08f39549d5bd80de3931ccWouter van Oortmerssen parser.opts.binary_schema_comments 24391fb6b9ee6f817befae08f39549d5bd80de3931ccWouter van Oortmerssen ? builder->CreateVectorOfStrings(doc_comment) 24401fb6b9ee6f817befae08f39549d5bd80de3931ccWouter van Oortmerssen : 0); 244181312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen // TODO: value.constant is almost always "0", we could save quite a bit of 244281312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen // space by sharing it. Same for common values of value.type. 244381312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen} 244481312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen 244572fc45aa6acbc11052c6baa462fac26c5075392aWouter van OortmerssenOffset<reflection::Enum> EnumDef::Serialize(FlatBufferBuilder *builder, 244672fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen const Parser &parser) const { 244781312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen std::vector<Offset<reflection::EnumVal>> enumval_offsets; 244881312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen for (auto it = vals.vec.begin(); it != vals.vec.end(); ++it) { 244981312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen enumval_offsets.push_back((*it)->Serialize(builder)); 245081312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen } 2451df0991b7ded0533554d3665e782273b6c8736376Xun Liu auto qualified_name = defined_namespace->GetFullyQualifiedName(name); 245281312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen return reflection::CreateEnum(*builder, 2453df0991b7ded0533554d3665e782273b6c8736376Xun Liu builder->CreateString(qualified_name), 245481312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen builder->CreateVector(enumval_offsets), 245581312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen is_union, 245672fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen underlying_type.Serialize(builder), 24571fb6b9ee6f817befae08f39549d5bd80de3931ccWouter van Oortmerssen SerializeAttributes(builder, parser), 24581fb6b9ee6f817befae08f39549d5bd80de3931ccWouter van Oortmerssen parser.opts.binary_schema_comments 24591fb6b9ee6f817befae08f39549d5bd80de3931ccWouter van Oortmerssen ? builder->CreateVectorOfStrings(doc_comment) 24601fb6b9ee6f817befae08f39549d5bd80de3931ccWouter van Oortmerssen : 0); 246181312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen} 246281312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen 246381312c21281430449aef20f7a71ad9e0962791d3Wouter van OortmerssenOffset<reflection::EnumVal> EnumVal::Serialize(FlatBufferBuilder *builder) const 246481312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen { 246581312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen return reflection::CreateEnumVal(*builder, 246681312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen builder->CreateString(name), 246781312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen value, 2468b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen union_type.struct_def 2469b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen ? union_type.struct_def-> 2470b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen serialized_location 2471b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen : 0, 2472b0752e179bdbae516125cccacd7aebcfd83033a9Wouter van Oortmerssen union_type.Serialize(builder)); 247381312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen} 247481312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen 247581312c21281430449aef20f7a71ad9e0962791d3Wouter van OortmerssenOffset<reflection::Type> Type::Serialize(FlatBufferBuilder *builder) const { 247681312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen return reflection::CreateType(*builder, 247781312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen static_cast<reflection::BaseType>(base_type), 247881312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen static_cast<reflection::BaseType>(element), 247981312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen struct_def ? struct_def->index : 248081312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen (enum_def ? enum_def->index : -1)); 248181312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen} 248281312c21281430449aef20f7a71ad9e0962791d3Wouter van Oortmerssen 248372fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssenflatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset< 248472fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen reflection::KeyValue>>> 248572fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen Definition::SerializeAttributes(FlatBufferBuilder *builder, 248672fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen const Parser &parser) const { 248772fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen std::vector<flatbuffers::Offset<reflection::KeyValue>> attrs; 2488e92ae5199d52fd59540a800bec7eef46cd778257Wouter van Oortmerssen for (auto kv = attributes.dict.begin(); kv != attributes.dict.end(); ++kv) { 2489e92ae5199d52fd59540a800bec7eef46cd778257Wouter van Oortmerssen auto it = parser.known_attributes_.find(kv->first); 249072fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen assert(it != parser.known_attributes_.end()); 249172fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen if (!it->second) { // Custom attribute. 249272fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen attrs.push_back( 2493e92ae5199d52fd59540a800bec7eef46cd778257Wouter van Oortmerssen reflection::CreateKeyValue(*builder, builder->CreateString(kv->first), 249472fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen builder->CreateString( 2495e92ae5199d52fd59540a800bec7eef46cd778257Wouter van Oortmerssen kv->second->constant))); 249672fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen } 249772fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen } 249872fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen if (attrs.size()) { 249972fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen return builder->CreateVectorOfSortedTables(&attrs); 250072fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen } else { 250172fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen return 0; 250272fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen } 250372fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen} 250472fc45aa6acbc11052c6baa462fac26c5075392aWouter van Oortmerssen 250505b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssenstd::string Parser::ConformTo(const Parser &base) { 250605b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen for (auto sit = structs_.vec.begin(); sit != structs_.vec.end(); ++sit) { 250705b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen auto &struct_def = **sit; 250805b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen auto qualified_name = 250905b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen struct_def.defined_namespace->GetFullyQualifiedName(struct_def.name); 25109c3920d0ab90e9442759c6b41c28af577759a692Wouter van Oortmerssen auto struct_def_base = base.LookupStruct(qualified_name); 251105b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen if (!struct_def_base) continue; 251205b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen for (auto fit = struct_def.fields.vec.begin(); 251305b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen fit != struct_def.fields.vec.end(); ++fit) { 251405b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen auto &field = **fit; 251505b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen auto field_base = struct_def_base->fields.Lookup(field.name); 251605b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen if (field_base) { 251705b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen if (field.value.offset != field_base->value.offset) 251805b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen return "offsets differ for field: " + field.name; 251905b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen if (field.value.constant != field_base->value.constant) 252005b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen return "defaults differ for field: " + field.name; 252105b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen if (!EqualByName(field.value.type, field_base->value.type)) 252205b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen return "types differ for field: " + field.name; 252305b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen } else { 252405b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen // Doesn't have to exist, deleting fields is fine. 252505b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen // But we should check if there is a field that has the same offset 252605b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen // but is incompatible (in the case of field renaming). 252705b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen for (auto fbit = struct_def_base->fields.vec.begin(); 252805b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen fbit != struct_def_base->fields.vec.end(); ++fbit) { 252905b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen field_base = *fbit; 253005b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen if (field.value.offset == field_base->value.offset) { 253105b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen if (!EqualByName(field.value.type, field_base->value.type)) 253205b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen return "field renamed to different type: " + field.name; 253305b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen break; 253405b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen } 253505b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen } 253605b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen } 253705b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen } 253805b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen } 253905b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen for (auto eit = enums_.vec.begin(); eit != enums_.vec.end(); ++eit) { 254005b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen auto &enum_def = **eit; 254105b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen auto qualified_name = 254205b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen enum_def.defined_namespace->GetFullyQualifiedName(enum_def.name); 254305b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen auto enum_def_base = base.enums_.Lookup(qualified_name); 254405b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen if (!enum_def_base) continue; 254505b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen for (auto evit = enum_def.vals.vec.begin(); 254605b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen evit != enum_def.vals.vec.end(); ++evit) { 254705b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen auto &enum_val = **evit; 254805b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen auto enum_val_base = enum_def_base->vals.Lookup(enum_val.name); 254905b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen if (enum_val_base) { 255005b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen if (enum_val.value != enum_val_base->value) 255105b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen return "values differ for enum: " + enum_val.name; 255205b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen } 255305b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen } 255405b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen } 255505b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen return ""; 255605b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen} 255705b00c50ad07a30974681005ef553eb546a12ce1Wouter van Oortmerssen 255826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen} // namespace flatbuffers 2559