summaryrefslogtreecommitdiff
path: root/onert-micro/externals/flatbuffers/registry.h
blob: c06bd5687880e179c4bdab70a0f452fb0de60fce (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
/*
 * Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved
 * Copyright 2017 Google Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef FLATBUFFERS_REGISTRY_H_
#define FLATBUFFERS_REGISTRY_H_

#include "flatbuffers/idl.h"

namespace flatbuffers
{

// Convenience class to easily parse or generate text for arbitrary FlatBuffers.
// Simply pre-populate it with all schema filenames that may be in use, and
// This class will look them up using the file_identifier declared in the
// schema.
class Registry
{
public:
  // Call this for all schemas that may be in use. The identifier has
  // a function in the generated code, e.g. MonsterIdentifier().
  void Register(const char *file_identifier, const char *schema_path)
  {
    Schema schema;
    schema.path_ = schema_path;
    schemas_[file_identifier] = schema;
  }

  // Generate text from an arbitrary FlatBuffer by looking up its
  // file_identifier in the registry.
  bool FlatBufferToText(const uint8_t *flatbuf, size_t len, std::string *dest)
  {
    // Get the identifier out of the buffer.
    // If the buffer is truncated, exit.
    if (len < sizeof(uoffset_t) + FlatBufferBuilder::kFileIdentifierLength)
    {
      lasterror_ = "buffer truncated";
      return false;
    }
    std::string ident(reinterpret_cast<const char *>(flatbuf) + sizeof(uoffset_t),
                      FlatBufferBuilder::kFileIdentifierLength);
    // Load and parse the schema.
    Parser parser;
    if (!LoadSchema(ident, &parser))
      return false;
    // Now we're ready to generate text.
    if (!GenerateText(parser, flatbuf, dest))
    {
      lasterror_ = "unable to generate text for FlatBuffer binary";
      return false;
    }
    return true;
  }

  // Converts a binary buffer to text using one of the schemas in the registry,
  // use the file_identifier to indicate which.
  // If DetachedBuffer::data() is null then parsing failed.
  DetachedBuffer TextToFlatBuffer(const char *text, const char *file_identifier)
  {
    // Load and parse the schema.
    Parser parser;
    if (!LoadSchema(file_identifier, &parser))
      return DetachedBuffer();
    // Parse the text.
    if (!parser.Parse(text))
    {
      lasterror_ = parser.error_;
      return DetachedBuffer();
    }
    // We have a valid FlatBuffer. Detach it from the builder and return.
    return parser.builder_.Release();
  }

  // Modify any parsing / output options used by the other functions.
  void SetOptions(const IDLOptions &opts) { opts_ = opts; }

  // If schemas used contain include statements, call this function for every
  // directory the parser should search them for.
  void AddIncludeDirectory(const char *path) { include_paths_.push_back(path); }

  // Returns a human readable error if any of the above functions fail.
  const std::string &GetLastError() { return lasterror_; }

private:
  bool LoadSchema(const std::string &ident, Parser *parser)
  {
    // Find the schema, if not, exit.
    auto it = schemas_.find(ident);
    if (it == schemas_.end())
    {
      // Don't attach the identifier, since it may not be human readable.
      lasterror_ = "identifier for this buffer not in the registry";
      return false;
    }
    auto &schema = it->second;
    // Load the schema from disk. If not, exit.
    std::string schematext;
    if (!LoadFile(schema.path_.c_str(), false, &schematext))
    {
      lasterror_ = "could not load schema: " + schema.path_;
      return false;
    }
    // Parse schema.
    parser->opts = opts_;
    if (!parser->Parse(schematext.c_str(), vector_data(include_paths_), schema.path_.c_str()))
    {
      lasterror_ = parser->error_;
      return false;
    }
    return true;
  }

  struct Schema
  {
    std::string path_;
    // TODO(wvo) optionally cache schema file or parsed schema here.
  };

  std::string lasterror_;
  IDLOptions opts_;
  std::vector<const char *> include_paths_;
  std::map<std::string, Schema> schemas_;
};

} // namespace flatbuffers

#endif // FLATBUFFERS_REGISTRY_H_