172a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen/*
272a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen * Copyright 2017 Google Inc. All rights reserved.
372a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen *
472a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen * Licensed under the Apache License, Version 2.0 (the "License");
572a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen * you may not use this file except in compliance with the License.
672a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen * You may obtain a copy of the License at
772a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen *
872a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen *     http://www.apache.org/licenses/LICENSE-2.0
972a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen *
1072a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen * Unless required by applicable law or agreed to in writing, software
1172a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen * distributed under the License is distributed on an "AS IS" BASIS,
1272a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1372a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen * See the License for the specific language governing permissions and
1472a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen * limitations under the License.
1572a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen */
1672a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen
1772a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen#ifndef FLATBUFFERS_MINIREFLECT_H_
1872a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen#define FLATBUFFERS_MINIREFLECT_H_
1972a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen
2072a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen#include "flatbuffers/flatbuffers.h"
2172a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen#include "flatbuffers/util.h"
2272a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen
2372a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssennamespace flatbuffers {
2472a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen
2572a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen// Utilities that can be used with the "mini reflection" tables present
2672a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen// in generated code with --reflect-types (only types) or --reflect-names
2772a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen// (also names).
2872a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen// This allows basic reflection functionality such as pretty-printing
2972a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen// that does not require the use of the schema parser or loading of binary
3072a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen// schema files at runtime (reflection.h).
3172a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen
3272a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen// For any of the functions below that take `const TypeTable *`, you pass
3372a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen// `FooTypeTable()` if the type of the root is `Foo`.
3472a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen
3572a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen// First, a generic iterator that can be used by multiple algorithms.
3672a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen
3772a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssenstruct IterationVisitor {
3872a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  // These mark the scope of a table or struct.
3972a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  virtual void StartSequence() {}
4072a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  virtual void EndSequence() {}
4172a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  // Called for each field regardless of wether it is present or not.
4272a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  // If not present, val == nullptr. set_idx is the index of all set fields.
4372a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  virtual void Field(size_t /*field_idx*/, size_t /*set_idx*/,
4472a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen                     ElementaryType /*type*/, bool /*is_vector*/,
4572a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen                     const TypeTable * /*type_table*/, const char * /*name*/,
4672a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen                     const uint8_t * /*val*/) {}
4772a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  // Called for a value that is actually present, after a field, or as part
4872a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  // of a vector.
4972a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  virtual void UType(uint8_t, const char *) {}
5072a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  virtual void Bool(bool) {}
5172a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  virtual void Char(int8_t, const char *) {}
5272a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  virtual void UChar(uint8_t, const char *) {}
5372a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  virtual void Short(int16_t, const char *) {}
5472a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  virtual void UShort(uint16_t, const char *) {}
5572a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  virtual void Int(int32_t, const char *) {}
5672a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  virtual void UInt(uint32_t, const char *) {}
5772a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  virtual void Long(int64_t) {}
5872a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  virtual void ULong(uint64_t) {}
5972a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  virtual void Float(float) {}
6072a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  virtual void Double(double) {}
6172a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  virtual void String(const String *) {}
6272a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  virtual void Unknown(const uint8_t *) {}  // From a future version.
6372a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  // These mark the scope of a vector.
6472a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  virtual void StartVector() {}
6572a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  virtual void EndVector() {}
6672a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  virtual void Element(size_t /*i*/, ElementaryType /*type*/,
6772a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen                       const TypeTable * /*type_table*/,
6872a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen                       const uint8_t * /*val*/)
6972a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  {}
7072a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  virtual ~IterationVisitor() {}
7172a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen};
7272a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen
7372a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmersseninline size_t InlineSize(ElementaryType type, const TypeTable *type_table) {
7472a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  switch (type) {
7572a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    case ET_UTYPE:
7672a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    case ET_BOOL:
7772a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    case ET_CHAR:
7872a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    case ET_UCHAR:
7972a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen      return 1;
8072a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    case ET_SHORT:
8172a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    case ET_USHORT:
8272a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen      return 2;
8372a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    case ET_INT:
8472a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    case ET_UINT:
8572a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    case ET_FLOAT:
8672a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    case ET_STRING:
8772a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen      return 4;
8872a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    case ET_LONG:
8972a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    case ET_ULONG:
9072a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    case ET_DOUBLE:
9172a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen      return 8;
9272a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    case ET_SEQUENCE:
9372a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen      switch (type_table->st) {
9472a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen        case ST_TABLE:
9572a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen        case ST_UNION:
9672a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen          return 4;
9772a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen        case ST_STRUCT:
9872a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen          return type_table->values[type_table->num_elems];
9972a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen        default:
10072a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen          assert(false);
10172a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen          return 1;
10272a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen      }
10372a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    default:
10472a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen      assert(false);
10572a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen      return 1;
10672a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  }
10772a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen}
10872a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen
10972a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmersseninline int32_t LookupEnum(int32_t enum_val, const int32_t *values,
11072a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen                          size_t num_values) {
11172a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  if (!values) return enum_val;
11272a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  for (size_t i = 0; i < num_values; i++) {
11372a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    if (enum_val == values[i]) return static_cast<int32_t>(i);
11472a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  }
11572a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  return -1;  // Unknown enum value.
11672a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen}
11772a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen
11872a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssentemplate<typename T> const char *EnumName(T tval, const TypeTable *type_table) {
11972a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  if (!type_table || !type_table->names) return nullptr;
12072a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  auto i = LookupEnum(static_cast<int32_t>(tval), type_table->values,
12172a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen                                  type_table->num_elems);
12272a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  if (i >= 0 && i < static_cast<int32_t>(type_table->num_elems)) {
12372a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    return type_table->names[i];
12472a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  }
12572a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  return nullptr;
12672a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen}
12772a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen
12872a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssenvoid IterateObject(const uint8_t *obj, const TypeTable *type_table,
12972a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen                  IterationVisitor *visitor);
13072a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen
13172a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmersseninline void IterateValue(ElementaryType type, const uint8_t *val,
13272a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen                         const TypeTable *type_table,
13372a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen                         const uint8_t *prev_val,
13472a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen                         soffset_t vector_index,
13572a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen                         IterationVisitor *visitor) {
13672a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  switch (type) {
13772a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    case ET_UTYPE: {
13872a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen      auto tval = *reinterpret_cast<const uint8_t *>(val);
13972a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen      visitor->UType(tval, EnumName(tval, type_table));
14072a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen      break;
14172a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    }
14272a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    case ET_BOOL: {
14372a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen      visitor->Bool(*reinterpret_cast<const uint8_t *>(val) != 0);
14472a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen      break;
14572a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    }
14672a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    case ET_CHAR: {
14772a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen      auto tval = *reinterpret_cast<const int8_t *>(val);
14872a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen      visitor->Char(tval, EnumName(tval, type_table));
14972a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen      break;
15072a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    }
15172a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    case ET_UCHAR: {
15272a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen      auto tval = *reinterpret_cast<const uint8_t *>(val);
15372a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen      visitor->UChar(tval, EnumName(tval, type_table));
15472a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen      break;
15572a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    }
15672a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    case ET_SHORT: {
15772a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen      auto tval = *reinterpret_cast<const int16_t *>(val);
15872a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen      visitor->Short(tval, EnumName(tval, type_table));
15972a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen      break;
16072a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    }
16172a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    case ET_USHORT: {
16272a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen      auto tval = *reinterpret_cast<const uint16_t *>(val);
16372a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen      visitor->UShort(tval, EnumName(tval, type_table));
16472a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen      break;
16572a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    }
16672a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    case ET_INT: {
16772a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen      auto tval = *reinterpret_cast<const int32_t *>(val);
16872a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen      visitor->Int(tval, EnumName(tval, type_table));
16972a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen      break;
17072a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    }
17172a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    case ET_UINT: {
17272a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen      auto tval = *reinterpret_cast<const uint32_t *>(val);
17372a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen      visitor->UInt(tval, EnumName(tval, type_table));
17472a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen      break;
17572a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    }
17672a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    case ET_LONG: {
17772a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen      visitor->Long(*reinterpret_cast<const int64_t *>(val));
17872a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen      break;
17972a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    }
18072a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    case ET_ULONG: {
18172a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen      visitor->ULong(*reinterpret_cast<const uint64_t *>(val));
18272a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen      break;
18372a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    }
18472a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    case ET_FLOAT: {
18572a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen      visitor->Float(*reinterpret_cast<const float *>(val));
18672a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen      break;
18772a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    }
18872a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    case ET_DOUBLE: {
18972a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen      visitor->Double(*reinterpret_cast<const double *>(val));
19072a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen      break;
19172a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    }
19272a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    case ET_STRING: {
19372a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen      val += ReadScalar<uoffset_t>(val);
19472a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen      visitor->String(reinterpret_cast<const String *>(val));
19572a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen      break;
19672a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    }
19772a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    case ET_SEQUENCE: {
19872a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen      switch (type_table->st) {
19972a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen        case ST_TABLE:
20072a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen          val += ReadScalar<uoffset_t>(val);
20172a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen          IterateObject(val, type_table, visitor);
20272a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen          break;
20372a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen        case ST_STRUCT:
20472a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen          IterateObject(val, type_table, visitor);
20572a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen          break;
20672a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen        case ST_UNION: {
20772a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen          val += ReadScalar<uoffset_t>(val);
20872a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen          assert(prev_val);
20972a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen          auto union_type = *prev_val;  // Always a uint8_t.
21072a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen          if (vector_index >= 0) {
21172a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen            auto type_vec = reinterpret_cast<const Vector<uint8_t> *>(prev_val);
21272a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen            union_type = type_vec->Get(static_cast<uoffset_t>(vector_index));
21372a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen          }
21472a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen          auto type_code_idx = LookupEnum(union_type, type_table->values,
21572a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen                                          type_table->num_elems);
21672a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen          if (type_code_idx >= 0 && type_code_idx <
21772a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen              static_cast<int32_t>(type_table->num_elems)) {
21872a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen            auto type_code = type_table->type_codes[type_code_idx];
21972a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen            switch (type_code.base_type) {
22072a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen              case ET_SEQUENCE: {
22172a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen                auto ref = type_table->type_refs[type_code.sequence_ref]();
22272a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen                IterateObject(val, ref, visitor);
22372a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen                break;
22472a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen              }
22572a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen              case ET_STRING:
22672a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen                visitor->String(reinterpret_cast<const String *>(val));
22772a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen                break;
22872a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen              default:
22972a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen                visitor->Unknown(val);
23072a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen            }
23172a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen          } else {
23272a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen            visitor->Unknown(val);
23372a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen          }
23472a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen          break;
23572a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen        }
23672a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen        case ST_ENUM:
23772a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen          assert(false);
23872a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen          break;
23972a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen      }
24072a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen      break;
24172a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    }
24272a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    default: {
24372a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen      visitor->Unknown(val);
24472a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen      break;
24572a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    }
24672a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  }
24772a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen}
24872a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen
24972a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmersseninline void IterateObject(const uint8_t *obj, const TypeTable *type_table,
25072a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen                          IterationVisitor *visitor) {
25172a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  visitor->StartSequence();
25272a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  const uint8_t *prev_val = nullptr;
25372a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  size_t set_idx = 0;
25472a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  for (size_t i = 0; i < type_table->num_elems; i++) {
25572a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    auto type_code = type_table->type_codes[i];
25672a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    auto type = static_cast<ElementaryType>(type_code.base_type);
25772a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    auto is_vector = type_code.is_vector != 0;
25872a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    auto ref_idx = type_code.sequence_ref;
25972a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    const TypeTable *ref = nullptr;
26072a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    if (ref_idx >= 0) {
26172a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen      ref = type_table->type_refs[ref_idx]();
26272a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    }
26372a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    auto name = type_table->names ? type_table->names[i] : nullptr;
26472a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    const uint8_t *val = nullptr;
26572a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    if (type_table->st == ST_TABLE) {
26672a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen      val = reinterpret_cast<const Table *>(obj)->GetAddressOf(
26772a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen              FieldIndexToOffset(static_cast<voffset_t>(i)));
26872a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    } else {
26972a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen      val = obj + type_table->values[i];
27072a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    }
27172a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    visitor->Field(i, set_idx, type, is_vector, ref, name, val);
27272a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    if (val) {
27372a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen      set_idx++;
27472a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen      if (is_vector) {
27572a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen        val += ReadScalar<uoffset_t>(val);
27672a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen        auto vec = reinterpret_cast<const Vector<uint8_t> *>(val);
27772a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen        visitor->StartVector();
27872a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen        auto elem_ptr = vec->Data();
27972a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen        for (size_t j = 0; j < vec->size(); j++) {
28072a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen          visitor->Element(j, type, ref, elem_ptr);
28172a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen          IterateValue(type, elem_ptr, ref, prev_val, static_cast<soffset_t>(j),
28272a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen                       visitor);
28372a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen          elem_ptr += InlineSize(type, ref);
28472a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen        }
28572a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen        visitor->EndVector();
28672a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen      } else {
28772a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen        IterateValue(type, val, ref, prev_val, -1, visitor);
28872a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen      }
28972a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    }
29072a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    prev_val = val;
29172a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  }
29272a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  visitor->EndSequence();
29372a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen}
29472a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen
29572a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmersseninline void IterateFlatBuffer(const uint8_t *buffer,
29672a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen                              const TypeTable *type_table,
29772a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen                              IterationVisitor *callback) {
29872a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  IterateObject(GetRoot<uint8_t>(buffer), type_table, callback);
29972a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen}
30072a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen
30172a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen// Outputting a Flatbuffer to a string. Tries to conform as close to JSON /
30272a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen// the output generated by idl_gen_text.cpp.
30372a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen
30472a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssenstruct ToStringVisitor : public IterationVisitor {
30572a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  std::string s;
30672a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  void StartSequence() { s += "{ "; }
30772a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  void EndSequence() { s += " }"; }
30872a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  void Field(size_t /*field_idx*/, size_t set_idx, ElementaryType /*type*/,
30972a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen             bool /*is_vector*/, const TypeTable * /*type_table*/,
31072a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen             const char *name, const uint8_t *val) {
31172a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    if (!val) return;
31272a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    if (set_idx) s += ", ";
31372a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    if (name) { s += name; s += ": "; }
31472a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  }
31572a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  template<typename T> void Named(T x, const char *name) {
31672a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    if (name) s+= name;
31772a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    else s+= NumToString(x);
31872a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  }
31972a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  void UType(uint8_t x, const char *name) { Named(x, name); }
32072a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  void Bool(bool x) { s+= x ? "true" : "false"; }
32172a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  void Char(int8_t x, const char *name) { Named(x, name); }
32272a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  void UChar(uint8_t x, const char *name) { Named(x, name); }
32372a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  void Short(int16_t x, const char *name) { Named(x, name); }
32472a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  void UShort(uint16_t x, const char *name) { Named(x, name); }
32572a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  void Int(int32_t x, const char *name) { Named(x, name); }
32672a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  void UInt(uint32_t x, const char *name) { Named(x, name); }
32772a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  void Long(int64_t x) { s+= NumToString(x); }
32872a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  void ULong(uint64_t x) { s+= NumToString(x); }
32972a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  void Float(float x) { s+= NumToString(x); }
33072a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  void Double(double x) { s+= NumToString(x); }
33172a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  void String(const struct String *str) {
33272a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    EscapeString(str->c_str(), str->size(), &s, true);
33372a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  }
33472a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  void Unknown(const uint8_t *) { s += "(?)"; }
33572a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  void StartVector() { s += "[ "; }
33672a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  void EndVector() { s += " ]"; }
33772a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  void Element(size_t i, ElementaryType /*type*/,
33872a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen               const TypeTable * /*type_table*/, const uint8_t * /*val*/) {
33972a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen    if (i) s += ", ";
34072a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  }
34172a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen};
34272a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen
34372a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmersseninline std::string FlatBufferToString(const uint8_t *buffer,
34472a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen                                      const TypeTable *type_table) {
34572a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  ToStringVisitor tostring_visitor;
34672a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  IterateFlatBuffer(buffer, type_table, &tostring_visitor);
34772a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen  return tostring_visitor.s;
34872a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen}
34972a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen
35072a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen}  // namespace flatbuffers
35172a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen
35272a99abfb7db64dc49720b28b41f382b5ec7cde0Wouter van Oortmerssen#endif  // FLATBUFFERS_MINIREFLECT_H_
353