File indexing completed on 2025-08-27 09:30:27
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 #ifndef FLATBUFFERS_MINIREFLECT_H_
0018 #define FLATBUFFERS_MINIREFLECT_H_
0019
0020 #include "flatbuffers/flatbuffers.h"
0021 #include "flatbuffers/util.h"
0022
0023 namespace flatbuffers {
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037 struct IterationVisitor {
0038
0039 virtual void StartSequence() {}
0040 virtual void EndSequence() {}
0041
0042
0043 virtual void Field(size_t , size_t ,
0044 ElementaryType , bool ,
0045 const TypeTable * , const char * ,
0046 const uint8_t * ) {}
0047
0048
0049 virtual void UType(uint8_t, const char *) {}
0050 virtual void Bool(bool) {}
0051 virtual void Char(int8_t, const char *) {}
0052 virtual void UChar(uint8_t, const char *) {}
0053 virtual void Short(int16_t, const char *) {}
0054 virtual void UShort(uint16_t, const char *) {}
0055 virtual void Int(int32_t, const char *) {}
0056 virtual void UInt(uint32_t, const char *) {}
0057 virtual void Long(int64_t) {}
0058 virtual void ULong(uint64_t) {}
0059 virtual void Float(float) {}
0060 virtual void Double(double) {}
0061 virtual void String(const String *) {}
0062 virtual void Unknown(const uint8_t *) {}
0063
0064 virtual void StartVector() {}
0065 virtual void EndVector() {}
0066 virtual void Element(size_t , ElementaryType ,
0067 const TypeTable * ,
0068 const uint8_t * ) {}
0069 virtual ~IterationVisitor() {}
0070 };
0071
0072 inline size_t InlineSize(ElementaryType type, const TypeTable *type_table) {
0073 switch (type) {
0074 case ET_UTYPE:
0075 case ET_BOOL:
0076 case ET_CHAR:
0077 case ET_UCHAR: return 1;
0078 case ET_SHORT:
0079 case ET_USHORT: return 2;
0080 case ET_INT:
0081 case ET_UINT:
0082 case ET_FLOAT:
0083 case ET_STRING: return 4;
0084 case ET_LONG:
0085 case ET_ULONG:
0086 case ET_DOUBLE: return 8;
0087 case ET_SEQUENCE:
0088 switch (type_table->st) {
0089 case ST_TABLE:
0090 case ST_UNION: return 4;
0091 case ST_STRUCT:
0092 return static_cast<size_t>(type_table->values[type_table->num_elems]);
0093 default: FLATBUFFERS_ASSERT(false); return 1;
0094 }
0095 default: FLATBUFFERS_ASSERT(false); return 1;
0096 }
0097 }
0098
0099 inline int64_t LookupEnum(int64_t enum_val, const int64_t *values,
0100 size_t num_values) {
0101 if (!values) return enum_val;
0102 for (size_t i = 0; i < num_values; i++) {
0103 if (enum_val == values[i]) return static_cast<int64_t>(i);
0104 }
0105 return -1;
0106 }
0107
0108 template<typename T> const char *EnumName(T tval, const TypeTable *type_table) {
0109 if (!type_table || !type_table->names) return nullptr;
0110 auto i = LookupEnum(static_cast<int64_t>(tval), type_table->values,
0111 type_table->num_elems);
0112 if (i >= 0 && i < static_cast<int64_t>(type_table->num_elems)) {
0113 return type_table->names[i];
0114 }
0115 return nullptr;
0116 }
0117
0118 void IterateObject(const uint8_t *obj, const TypeTable *type_table,
0119 IterationVisitor *visitor);
0120
0121 inline void IterateValue(ElementaryType type, const uint8_t *val,
0122 const TypeTable *type_table, const uint8_t *prev_val,
0123 soffset_t vector_index, IterationVisitor *visitor) {
0124 switch (type) {
0125 case ET_UTYPE: {
0126 auto tval = ReadScalar<uint8_t>(val);
0127 visitor->UType(tval, EnumName(tval, type_table));
0128 break;
0129 }
0130 case ET_BOOL: {
0131 visitor->Bool(ReadScalar<uint8_t>(val) != 0);
0132 break;
0133 }
0134 case ET_CHAR: {
0135 auto tval = ReadScalar<int8_t>(val);
0136 visitor->Char(tval, EnumName(tval, type_table));
0137 break;
0138 }
0139 case ET_UCHAR: {
0140 auto tval = ReadScalar<uint8_t>(val);
0141 visitor->UChar(tval, EnumName(tval, type_table));
0142 break;
0143 }
0144 case ET_SHORT: {
0145 auto tval = ReadScalar<int16_t>(val);
0146 visitor->Short(tval, EnumName(tval, type_table));
0147 break;
0148 }
0149 case ET_USHORT: {
0150 auto tval = ReadScalar<uint16_t>(val);
0151 visitor->UShort(tval, EnumName(tval, type_table));
0152 break;
0153 }
0154 case ET_INT: {
0155 auto tval = ReadScalar<int32_t>(val);
0156 visitor->Int(tval, EnumName(tval, type_table));
0157 break;
0158 }
0159 case ET_UINT: {
0160 auto tval = ReadScalar<uint32_t>(val);
0161 visitor->UInt(tval, EnumName(tval, type_table));
0162 break;
0163 }
0164 case ET_LONG: {
0165 visitor->Long(ReadScalar<int64_t>(val));
0166 break;
0167 }
0168 case ET_ULONG: {
0169 visitor->ULong(ReadScalar<uint64_t>(val));
0170 break;
0171 }
0172 case ET_FLOAT: {
0173 visitor->Float(ReadScalar<float>(val));
0174 break;
0175 }
0176 case ET_DOUBLE: {
0177 visitor->Double(ReadScalar<double>(val));
0178 break;
0179 }
0180 case ET_STRING: {
0181 val += ReadScalar<uoffset_t>(val);
0182 visitor->String(reinterpret_cast<const String *>(val));
0183 break;
0184 }
0185 case ET_SEQUENCE: {
0186 switch (type_table->st) {
0187 case ST_TABLE:
0188 val += ReadScalar<uoffset_t>(val);
0189 IterateObject(val, type_table, visitor);
0190 break;
0191 case ST_STRUCT: IterateObject(val, type_table, visitor); break;
0192 case ST_UNION: {
0193 val += ReadScalar<uoffset_t>(val);
0194 FLATBUFFERS_ASSERT(prev_val);
0195 auto union_type = *prev_val;
0196 if (vector_index >= 0) {
0197 auto type_vec = reinterpret_cast<const Vector<uint8_t> *>(prev_val);
0198 union_type = type_vec->Get(static_cast<uoffset_t>(vector_index));
0199 }
0200 auto type_code_idx =
0201 LookupEnum(union_type, type_table->values, type_table->num_elems);
0202 if (type_code_idx >= 0 &&
0203 type_code_idx < static_cast<int32_t>(type_table->num_elems)) {
0204 auto type_code = type_table->type_codes[type_code_idx];
0205 switch (type_code.base_type) {
0206 case ET_SEQUENCE: {
0207 auto ref = type_table->type_refs[type_code.sequence_ref]();
0208 IterateObject(val, ref, visitor);
0209 break;
0210 }
0211 case ET_STRING:
0212 visitor->String(reinterpret_cast<const String *>(val));
0213 break;
0214 default: visitor->Unknown(val);
0215 }
0216 } else {
0217 visitor->Unknown(val);
0218 }
0219 break;
0220 }
0221 case ST_ENUM: FLATBUFFERS_ASSERT(false); break;
0222 }
0223 break;
0224 }
0225 default: {
0226 visitor->Unknown(val);
0227 break;
0228 }
0229 }
0230 }
0231
0232 inline void IterateObject(const uint8_t *obj, const TypeTable *type_table,
0233 IterationVisitor *visitor) {
0234 visitor->StartSequence();
0235 const uint8_t *prev_val = nullptr;
0236 size_t set_idx = 0;
0237 size_t array_idx = 0;
0238 for (size_t i = 0; i < type_table->num_elems; i++) {
0239 auto type_code = type_table->type_codes[i];
0240 auto type = static_cast<ElementaryType>(type_code.base_type);
0241 auto is_repeating = type_code.is_repeating != 0;
0242 auto ref_idx = type_code.sequence_ref;
0243 const TypeTable *ref = nullptr;
0244 if (ref_idx >= 0) { ref = type_table->type_refs[ref_idx](); }
0245 auto name = type_table->names ? type_table->names[i] : nullptr;
0246 const uint8_t *val = nullptr;
0247 if (type_table->st == ST_TABLE) {
0248 val = reinterpret_cast<const Table *>(obj)->GetAddressOf(
0249 FieldIndexToOffset(static_cast<voffset_t>(i)));
0250 } else {
0251 val = obj + type_table->values[i];
0252 }
0253 visitor->Field(i, set_idx, type, is_repeating, ref, name, val);
0254 if (val) {
0255 set_idx++;
0256 if (is_repeating) {
0257 auto elem_ptr = val;
0258 size_t size = 0;
0259 if (type_table->st == ST_TABLE) {
0260
0261 val += ReadScalar<uoffset_t>(val);
0262 auto vec = reinterpret_cast<const Vector<uint8_t> *>(val);
0263 elem_ptr = vec->Data();
0264 size = vec->size();
0265 } else {
0266
0267 size = type_table->array_sizes[array_idx];
0268 ++array_idx;
0269 }
0270 visitor->StartVector();
0271 for (size_t j = 0; j < size; j++) {
0272 visitor->Element(j, type, ref, elem_ptr);
0273 IterateValue(type, elem_ptr, ref, prev_val, static_cast<soffset_t>(j),
0274 visitor);
0275 elem_ptr += InlineSize(type, ref);
0276 }
0277 visitor->EndVector();
0278 } else {
0279 IterateValue(type, val, ref, prev_val, -1, visitor);
0280 }
0281 }
0282 prev_val = val;
0283 }
0284 visitor->EndSequence();
0285 }
0286
0287 inline void IterateFlatBuffer(const uint8_t *buffer,
0288 const TypeTable *type_table,
0289 IterationVisitor *callback) {
0290 IterateObject(GetRoot<uint8_t>(buffer), type_table, callback);
0291 }
0292
0293
0294
0295
0296 struct ToStringVisitor : public IterationVisitor {
0297 std::string s;
0298 std::string d;
0299 bool q;
0300 std::string in;
0301 size_t indent_level;
0302 bool vector_delimited;
0303 ToStringVisitor(std::string delimiter, bool quotes, std::string indent,
0304 bool vdelimited = true)
0305 : d(delimiter),
0306 q(quotes),
0307 in(indent),
0308 indent_level(0),
0309 vector_delimited(vdelimited) {}
0310 ToStringVisitor(std::string delimiter)
0311 : d(delimiter),
0312 q(false),
0313 in(""),
0314 indent_level(0),
0315 vector_delimited(true) {}
0316
0317 void append_indent() {
0318 for (size_t i = 0; i < indent_level; i++) { s += in; }
0319 }
0320
0321 void StartSequence() {
0322 s += "{";
0323 s += d;
0324 indent_level++;
0325 }
0326 void EndSequence() {
0327 s += d;
0328 indent_level--;
0329 append_indent();
0330 s += "}";
0331 }
0332 void Field(size_t , size_t set_idx, ElementaryType ,
0333 bool , const TypeTable * ,
0334 const char *name, const uint8_t *val) {
0335 if (!val) return;
0336 if (set_idx) {
0337 s += ",";
0338 s += d;
0339 }
0340 append_indent();
0341 if (name) {
0342 if (q) s += "\"";
0343 s += name;
0344 if (q) s += "\"";
0345 s += ": ";
0346 }
0347 }
0348 template<typename T> void Named(T x, const char *name) {
0349 if (name) {
0350 if (q) s += "\"";
0351 s += name;
0352 if (q) s += "\"";
0353 } else {
0354 s += NumToString(x);
0355 }
0356 }
0357 void UType(uint8_t x, const char *name) { Named(x, name); }
0358 void Bool(bool x) { s += x ? "true" : "false"; }
0359 void Char(int8_t x, const char *name) { Named(x, name); }
0360 void UChar(uint8_t x, const char *name) { Named(x, name); }
0361 void Short(int16_t x, const char *name) { Named(x, name); }
0362 void UShort(uint16_t x, const char *name) { Named(x, name); }
0363 void Int(int32_t x, const char *name) { Named(x, name); }
0364 void UInt(uint32_t x, const char *name) { Named(x, name); }
0365 void Long(int64_t x) { s += NumToString(x); }
0366 void ULong(uint64_t x) { s += NumToString(x); }
0367 void Float(float x) { s += NumToString(x); }
0368 void Double(double x) { s += NumToString(x); }
0369 void String(const struct String *str) {
0370 EscapeString(str->c_str(), str->size(), &s, true, false);
0371 }
0372 void Unknown(const uint8_t *) { s += "(?)"; }
0373 void StartVector() {
0374 s += "[";
0375 if (vector_delimited) {
0376 s += d;
0377 indent_level++;
0378 append_indent();
0379 } else {
0380 s += " ";
0381 }
0382 }
0383 void EndVector() {
0384 if (vector_delimited) {
0385 s += d;
0386 indent_level--;
0387 append_indent();
0388 } else {
0389 s += " ";
0390 }
0391 s += "]";
0392 }
0393 void Element(size_t i, ElementaryType ,
0394 const TypeTable * , const uint8_t * ) {
0395 if (i) {
0396 s += ",";
0397 if (vector_delimited) {
0398 s += d;
0399 append_indent();
0400 } else {
0401 s += " ";
0402 }
0403 }
0404 }
0405 };
0406
0407 inline std::string FlatBufferToString(const uint8_t *buffer,
0408 const TypeTable *type_table,
0409 bool multi_line = false,
0410 bool vector_delimited = true,
0411 const std::string &indent = "",
0412 bool quotes = false) {
0413 ToStringVisitor tostring_visitor(multi_line ? "\n" : " ", quotes, indent,
0414 vector_delimited);
0415 IterateFlatBuffer(buffer, type_table, &tostring_visitor);
0416 return tostring_visitor.s;
0417 }
0418
0419 }
0420
0421 #endif