blob: e8bb8f5e32bd241438ecb441f674c6c4a07118e9 [file] [log] [blame]
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001/*
2 * Copyright 2017 Google Inc. All rights reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef FLATBUFFERS_REGISTRY_H_
18#define FLATBUFFERS_REGISTRY_H_
19
James Kuszmaul8e62b022022-03-22 09:33:25 -070020#include "flatbuffers/base.h"
Austin Schuhe89fa2d2019-08-14 20:24:23 -070021#include "flatbuffers/idl.h"
22
23namespace flatbuffers {
24
25// Convenience class to easily parse or generate text for arbitrary FlatBuffers.
26// Simply pre-populate it with all schema filenames that may be in use, and
27// This class will look them up using the file_identifier declared in the
28// schema.
29class Registry {
30 public:
31 // Call this for all schemas that may be in use. The identifier has
32 // a function in the generated code, e.g. MonsterIdentifier().
33 void Register(const char *file_identifier, const char *schema_path) {
34 Schema schema;
35 schema.path_ = schema_path;
36 schemas_[file_identifier] = schema;
37 }
38
39 // Generate text from an arbitrary FlatBuffer by looking up its
40 // file_identifier in the registry.
41 bool FlatBufferToText(const uint8_t *flatbuf, size_t len, std::string *dest) {
42 // Get the identifier out of the buffer.
43 // If the buffer is truncated, exit.
James Kuszmaul8e62b022022-03-22 09:33:25 -070044 if (len < sizeof(uoffset_t) + kFileIdentifierLength) {
Austin Schuhe89fa2d2019-08-14 20:24:23 -070045 lasterror_ = "buffer truncated";
46 return false;
47 }
48 std::string ident(
49 reinterpret_cast<const char *>(flatbuf) + sizeof(uoffset_t),
James Kuszmaul8e62b022022-03-22 09:33:25 -070050 kFileIdentifierLength);
Austin Schuhe89fa2d2019-08-14 20:24:23 -070051 // Load and parse the schema.
52 Parser parser;
53 if (!LoadSchema(ident, &parser)) return false;
54 // Now we're ready to generate text.
55 if (!GenerateText(parser, flatbuf, dest)) {
56 lasterror_ = "unable to generate text for FlatBuffer binary";
57 return false;
58 }
59 return true;
60 }
61
62 // Converts a binary buffer to text using one of the schemas in the registry,
63 // use the file_identifier to indicate which.
64 // If DetachedBuffer::data() is null then parsing failed.
65 DetachedBuffer TextToFlatBuffer(const char *text,
66 const char *file_identifier) {
67 // Load and parse the schema.
68 Parser parser;
69 if (!LoadSchema(file_identifier, &parser)) return DetachedBuffer();
70 // Parse the text.
71 if (!parser.Parse(text)) {
72 lasterror_ = parser.error_;
73 return DetachedBuffer();
74 }
75 // We have a valid FlatBuffer. Detach it from the builder and return.
76 return parser.builder_.Release();
77 }
78
79 // Modify any parsing / output options used by the other functions.
80 void SetOptions(const IDLOptions &opts) { opts_ = opts; }
81
82 // If schemas used contain include statements, call this function for every
83 // directory the parser should search them for.
84 void AddIncludeDirectory(const char *path) { include_paths_.push_back(path); }
85
86 // Returns a human readable error if any of the above functions fail.
87 const std::string &GetLastError() { return lasterror_; }
88
89 private:
90 bool LoadSchema(const std::string &ident, Parser *parser) {
91 // Find the schema, if not, exit.
92 auto it = schemas_.find(ident);
93 if (it == schemas_.end()) {
94 // Don't attach the identifier, since it may not be human readable.
95 lasterror_ = "identifier for this buffer not in the registry";
96 return false;
97 }
98 auto &schema = it->second;
99 // Load the schema from disk. If not, exit.
100 std::string schematext;
101 if (!LoadFile(schema.path_.c_str(), false, &schematext)) {
102 lasterror_ = "could not load schema: " + schema.path_;
103 return false;
104 }
105 // Parse schema.
106 parser->opts = opts_;
James Kuszmaul8e62b022022-03-22 09:33:25 -0700107 if (!parser->Parse(schematext.c_str(), include_paths_.data(),
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700108 schema.path_.c_str())) {
109 lasterror_ = parser->error_;
110 return false;
111 }
112 return true;
113 }
114
115 struct Schema {
116 std::string path_;
117 // TODO(wvo) optionally cache schema file or parsed schema here.
118 };
119
120 std::string lasterror_;
121 IDLOptions opts_;
122 std::vector<const char *> include_paths_;
123 std::map<std::string, Schema> schemas_;
124};
125
126} // namespace flatbuffers
127
128#endif // FLATBUFFERS_REGISTRY_H_