blob: 9ea425b397816f664e6d0a6fef90676fc97afe01 [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
20#include "flatbuffers/idl.h"
21
22namespace flatbuffers {
23
24// Convenience class to easily parse or generate text for arbitrary FlatBuffers.
25// Simply pre-populate it with all schema filenames that may be in use, and
26// This class will look them up using the file_identifier declared in the
27// schema.
28class Registry {
29 public:
30 // Call this for all schemas that may be in use. The identifier has
31 // a function in the generated code, e.g. MonsterIdentifier().
32 void Register(const char *file_identifier, const char *schema_path) {
33 Schema schema;
34 schema.path_ = schema_path;
35 schemas_[file_identifier] = schema;
36 }
37
38 // Generate text from an arbitrary FlatBuffer by looking up its
39 // file_identifier in the registry.
40 bool FlatBufferToText(const uint8_t *flatbuf, size_t len, std::string *dest) {
41 // Get the identifier out of the buffer.
42 // If the buffer is truncated, exit.
43 if (len < sizeof(uoffset_t) + FlatBufferBuilder::kFileIdentifierLength) {
44 lasterror_ = "buffer truncated";
45 return false;
46 }
47 std::string ident(
48 reinterpret_cast<const char *>(flatbuf) + sizeof(uoffset_t),
49 FlatBufferBuilder::kFileIdentifierLength);
50 // Load and parse the schema.
51 Parser parser;
52 if (!LoadSchema(ident, &parser)) return false;
53 // Now we're ready to generate text.
54 if (!GenerateText(parser, flatbuf, dest)) {
55 lasterror_ = "unable to generate text for FlatBuffer binary";
56 return false;
57 }
58 return true;
59 }
60
61 // Converts a binary buffer to text using one of the schemas in the registry,
62 // use the file_identifier to indicate which.
63 // If DetachedBuffer::data() is null then parsing failed.
64 DetachedBuffer TextToFlatBuffer(const char *text,
65 const char *file_identifier) {
66 // Load and parse the schema.
67 Parser parser;
68 if (!LoadSchema(file_identifier, &parser)) return DetachedBuffer();
69 // Parse the text.
70 if (!parser.Parse(text)) {
71 lasterror_ = parser.error_;
72 return DetachedBuffer();
73 }
74 // We have a valid FlatBuffer. Detach it from the builder and return.
75 return parser.builder_.Release();
76 }
77
78 // Modify any parsing / output options used by the other functions.
79 void SetOptions(const IDLOptions &opts) { opts_ = opts; }
80
81 // If schemas used contain include statements, call this function for every
82 // directory the parser should search them for.
83 void AddIncludeDirectory(const char *path) { include_paths_.push_back(path); }
84
85 // Returns a human readable error if any of the above functions fail.
86 const std::string &GetLastError() { return lasterror_; }
87
88 private:
89 bool LoadSchema(const std::string &ident, Parser *parser) {
90 // Find the schema, if not, exit.
91 auto it = schemas_.find(ident);
92 if (it == schemas_.end()) {
93 // Don't attach the identifier, since it may not be human readable.
94 lasterror_ = "identifier for this buffer not in the registry";
95 return false;
96 }
97 auto &schema = it->second;
98 // Load the schema from disk. If not, exit.
99 std::string schematext;
100 if (!LoadFile(schema.path_.c_str(), false, &schematext)) {
101 lasterror_ = "could not load schema: " + schema.path_;
102 return false;
103 }
104 // Parse schema.
105 parser->opts = opts_;
106 if (!parser->Parse(schematext.c_str(), vector_data(include_paths_),
107 schema.path_.c_str())) {
108 lasterror_ = parser->error_;
109 return false;
110 }
111 return true;
112 }
113
114 struct Schema {
115 std::string path_;
116 // TODO(wvo) optionally cache schema file or parsed schema here.
117 };
118
119 std::string lasterror_;
120 IDLOptions opts_;
121 std::vector<const char *> include_paths_;
122 std::map<std::string, Schema> schemas_;
123};
124
125} // namespace flatbuffers
126
127#endif // FLATBUFFERS_REGISTRY_H_