/src/flatbuffers/include/codegen/namer.h
Line | Count | Source |
1 | | #ifndef FLATBUFFERS_INCLUDE_CODEGEN_NAMER_H_ |
2 | | #define FLATBUFFERS_INCLUDE_CODEGEN_NAMER_H_ |
3 | | |
4 | | #include "flatbuffers/util.h" |
5 | | |
6 | | namespace flatbuffers { |
7 | | |
8 | | // Options for Namer::File. |
9 | | enum class SkipFile { |
10 | | None = 0, |
11 | | Suffix = 1, |
12 | | Extension = 2, |
13 | | SuffixAndExtension = 3, |
14 | | }; |
15 | 0 | inline SkipFile operator&(SkipFile a, SkipFile b) { |
16 | 0 | return static_cast<SkipFile>(static_cast<int>(a) & static_cast<int>(b)); |
17 | 0 | } |
18 | | // Options for Namer::Directories |
19 | | enum class SkipDir { |
20 | | None = 0, |
21 | | // Skip prefixing the -o $output_path. |
22 | | OutputPath = 1, |
23 | | // Skip trailing path seperator. |
24 | | TrailingPathSeperator = 2, |
25 | | OutputPathAndTrailingPathSeparator = 3, |
26 | | }; |
27 | 0 | inline SkipDir operator&(SkipDir a, SkipDir b) { |
28 | 0 | return static_cast<SkipDir>(static_cast<int>(a) & static_cast<int>(b)); |
29 | 0 | } |
30 | | |
31 | | // `Namer` applies style configuration to symbols in generated code. It manages |
32 | | // casing, escapes keywords, and object API naming. |
33 | | // TODO: Refactor all code generators to use this. |
34 | | class Namer { |
35 | | public: |
36 | | struct Config { |
37 | | // Symbols in code. |
38 | | |
39 | | // Case style for flatbuffers-defined types. |
40 | | // e.g. `class TableA {}` |
41 | | Case types; |
42 | | // Case style for flatbuffers-defined constants. |
43 | | // e.g. `uint64_t ENUM_A_MAX`; |
44 | | Case constants; |
45 | | // Case style for flatbuffers-defined methods. |
46 | | // e.g. `class TableA { int field_a(); }` |
47 | | Case methods; |
48 | | // Case style for flatbuffers-defined functions. |
49 | | // e.g. `TableA* get_table_a_root()`; |
50 | | Case functions; |
51 | | // Case style for flatbuffers-defined fields. |
52 | | // e.g. `struct Struct { int my_field; }` |
53 | | Case fields; |
54 | | // Case style for flatbuffers-defined variables. |
55 | | // e.g. `int my_variable = 2` |
56 | | Case variables; |
57 | | // Case style for flatbuffers-defined variants. |
58 | | // e.g. `enum class Enum { MyVariant, }` |
59 | | Case variants; |
60 | | // Seperator for qualified enum names. |
61 | | // e.g. `Enum::MyVariant` uses `::`. |
62 | | std::string enum_variant_seperator; |
63 | | |
64 | | // Configures, when formatting code, whether symbols are checked against |
65 | | // keywords and escaped before or after case conversion. It does not make |
66 | | // sense to do so before, but its legacy behavior. :shrug: |
67 | | // TODO(caspern): Deprecate. |
68 | | enum class Escape { |
69 | | BeforeConvertingCase, |
70 | | AfterConvertingCase, |
71 | | }; |
72 | | Escape escape_keywords; |
73 | | |
74 | | // Namespaces |
75 | | |
76 | | // e.g. `namespace my_namespace {}` |
77 | | Case namespaces; |
78 | | // The seperator between namespaces in a namespace path. |
79 | | std::string namespace_seperator; |
80 | | |
81 | | // Object API. |
82 | | // Native versions flatbuffers types have this prefix. |
83 | | // e.g. "" (it's usually empty string) |
84 | | std::string object_prefix; |
85 | | // Native versions flatbuffers types have this suffix. |
86 | | // e.g. "T" |
87 | | std::string object_suffix; |
88 | | |
89 | | // Keywords. |
90 | | // Prefix used to escape keywords. It is usually empty string. |
91 | | std::string keyword_prefix; |
92 | | // Suffix used to escape keywords. It is usually "_". |
93 | | std::string keyword_suffix; |
94 | | |
95 | | // Files. |
96 | | |
97 | | // Case style for filenames. e.g. `foo_bar_generated.rs` |
98 | | Case filenames; |
99 | | // Case style for directories, e.g. `output_files/foo_bar/baz/` |
100 | | Case directories; |
101 | | // The directory within which we will generate files. |
102 | | std::string output_path; |
103 | | // Suffix for generated file names, e.g. "_generated". |
104 | | std::string filename_suffix; |
105 | | // Extension for generated files, e.g. ".cpp" or ".rs". |
106 | | std::string filename_extension; |
107 | | }; |
108 | | Namer(Config config, std::set<std::string> keywords) |
109 | 0 | : config_(config), keywords_(std::move(keywords)) {} |
110 | | |
111 | 0 | virtual ~Namer() {} |
112 | | |
113 | | template <typename T> |
114 | 0 | std::string Method(const T& s) const { |
115 | 0 | return Method(s.name); |
116 | 0 | } Unexecuted instantiation: std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > flatbuffers::Namer::Method<flatbuffers::FieldDef>(flatbuffers::FieldDef const&) const Unexecuted instantiation: std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > flatbuffers::Namer::Method<flatbuffers::EnumVal>(flatbuffers::EnumVal const&) const Unexecuted instantiation: std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > flatbuffers::Namer::Method<flatbuffers::EnumDef>(flatbuffers::EnumDef const&) const |
117 | | |
118 | | virtual std::string Method(const std::string& pre, const std::string& mid, |
119 | 0 | const std::string& suf) const { |
120 | 0 | return Format(pre + "_" + mid + "_" + suf, config_.methods); |
121 | 0 | } |
122 | | virtual std::string Method(const std::string& pre, |
123 | 0 | const std::string& suf) const { |
124 | 0 | return Format(pre + "_" + suf, config_.methods); |
125 | 0 | } |
126 | 0 | virtual std::string Method(const std::string& s) const { |
127 | 0 | return Format(s, config_.methods); |
128 | 0 | } |
129 | | |
130 | 0 | virtual std::string Constant(const std::string& s) const { |
131 | 0 | return Format(s, config_.constants); |
132 | 0 | } |
133 | | |
134 | 0 | virtual std::string Function(const std::string& s) const { |
135 | 0 | return Format(s, config_.functions); |
136 | 0 | } |
137 | | |
138 | 0 | virtual std::string Variable(const std::string& s) const { |
139 | 0 | return Format(s, config_.variables); |
140 | 0 | } |
141 | | |
142 | | template <typename T> |
143 | 0 | std::string Variable(const std::string& p, const T& s) const { |
144 | 0 | return Format(p + "_" + s.name, config_.variables); |
145 | 0 | } |
146 | | virtual std::string Variable(const std::string& p, |
147 | 0 | const std::string& s) const { |
148 | 0 | return Format(p + "_" + s, config_.variables); |
149 | 0 | } |
150 | | |
151 | 0 | virtual std::string Namespace(const std::string& s) const { |
152 | 0 | return Format(s, config_.namespaces); |
153 | 0 | } |
154 | | |
155 | 0 | virtual std::string Namespace(const std::vector<std::string>& ns) const { |
156 | 0 | std::string result; |
157 | 0 | for (auto it = ns.begin(); it != ns.end(); it++) { |
158 | 0 | if (it != ns.begin()) result += config_.namespace_seperator; |
159 | 0 | result += Namespace(*it); |
160 | 0 | } |
161 | 0 | return result; |
162 | 0 | } |
163 | | |
164 | | virtual std::string NamespacedType(const std::vector<std::string>& ns, |
165 | 0 | const std::string& s) const { |
166 | 0 | return (ns.empty() ? "" : (Namespace(ns) + config_.namespace_seperator)) + |
167 | 0 | Type(s); |
168 | 0 | } |
169 | | |
170 | | // Returns `filename` with the right casing, suffix, and extension. |
171 | | virtual std::string File(const std::string& filename, |
172 | 0 | SkipFile skips = SkipFile::None) const { |
173 | 0 | const bool skip_suffix = (skips & SkipFile::Suffix) != SkipFile::None; |
174 | 0 | const bool skip_ext = (skips & SkipFile::Extension) != SkipFile::None; |
175 | 0 | return ConvertCase(filename, config_.filenames, Case::kUpperCamel) + |
176 | 0 | (skip_suffix ? "" : config_.filename_suffix) + |
177 | 0 | (skip_ext ? "" : config_.filename_extension); |
178 | 0 | } |
179 | | template <typename T> |
180 | 0 | std::string File(const T& f, SkipFile skips = SkipFile::None) const { |
181 | 0 | return File(f.name, skips); |
182 | 0 | } Unexecuted instantiation: std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > flatbuffers::Namer::File<flatbuffers::Definition>(flatbuffers::Definition const&, flatbuffers::SkipFile) const Unexecuted instantiation: std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > flatbuffers::Namer::File<flatbuffers::StructDef>(flatbuffers::StructDef const&, flatbuffers::SkipFile) const Unexecuted instantiation: std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > flatbuffers::Namer::File<flatbuffers::EnumDef>(flatbuffers::EnumDef const&, flatbuffers::SkipFile) const |
183 | | |
184 | | // Formats `directories` prefixed with the output_path and joined with the |
185 | | // right seperator. Output path prefixing and the trailing separator may be |
186 | | // skiped using `skips`. |
187 | | // Callers may want to use `EnsureDirExists` with the result. |
188 | | // input_case is used to tell how to modify namespace. e.g. kUpperCamel will |
189 | | // add a underscode between case changes, so MyGame turns into My_Game |
190 | | // (depending also on the output_case). |
191 | | virtual std::string Directories(const std::vector<std::string>& directories, |
192 | | SkipDir skips = SkipDir::None, |
193 | 0 | Case input_case = Case::kUpperCamel) const { |
194 | 0 | const bool skip_output_path = |
195 | 0 | (skips & SkipDir::OutputPath) != SkipDir::None; |
196 | 0 | const bool skip_trailing_seperator = |
197 | 0 | (skips & SkipDir::TrailingPathSeperator) != SkipDir::None; |
198 | 0 | std::string result = skip_output_path ? "" : config_.output_path; |
199 | 0 | for (auto d = directories.begin(); d != directories.end(); d++) { |
200 | 0 | result += ConvertCase(*d, config_.directories, input_case); |
201 | 0 | result.push_back(kPathSeparator); |
202 | 0 | } |
203 | 0 | if (skip_trailing_seperator && !result.empty()) result.pop_back(); |
204 | 0 | return result; |
205 | 0 | } |
206 | | |
207 | 0 | virtual std::string EscapeKeyword(const std::string& name) const { |
208 | 0 | if (keywords_.find(name) == keywords_.end()) { |
209 | 0 | return name; |
210 | 0 | } else { |
211 | 0 | return config_.keyword_prefix + name + config_.keyword_suffix; |
212 | 0 | } |
213 | 0 | } |
214 | | |
215 | 0 | virtual std::string Type(const std::string& s) const { |
216 | 0 | return Format(s, config_.types); |
217 | 0 | } |
218 | 0 | virtual std::string Type(const std::string& t, const std::string& s) const { |
219 | 0 | return Format(t + "_" + s, config_.types); |
220 | 0 | } |
221 | | |
222 | 0 | virtual std::string ObjectType(const std::string& s) const { |
223 | 0 | return config_.object_prefix + Type(s) + config_.object_suffix; |
224 | 0 | } |
225 | | |
226 | 0 | virtual std::string Field(const std::string& s) const { |
227 | 0 | return Format(s, config_.fields); |
228 | 0 | } |
229 | | |
230 | 0 | virtual std::string Variant(const std::string& s) const { |
231 | 0 | return Format(s, config_.variants); |
232 | 0 | } |
233 | | |
234 | 0 | virtual std::string Format(const std::string& s, Case casing) const { |
235 | 0 | if (config_.escape_keywords == Config::Escape::BeforeConvertingCase) { |
236 | 0 | return ConvertCase(EscapeKeyword(s), casing, Case::kLowerCamel); |
237 | 0 | } else { |
238 | 0 | return EscapeKeyword(ConvertCase(s, casing, Case::kLowerCamel)); |
239 | 0 | } |
240 | 0 | } |
241 | | |
242 | | // Denamespaces a string (e.g. The.Quick.Brown.Fox) by returning the last part |
243 | | // after the `delimiter` (Fox) and placing the rest in `namespace_prefix` |
244 | | // (The.Quick.Brown). |
245 | | virtual std::string Denamespace(const std::string& s, |
246 | | std::string& namespace_prefix, |
247 | 0 | const char delimiter = '.') const { |
248 | 0 | const size_t pos = s.find_last_of(delimiter); |
249 | 0 | if (pos == std::string::npos) { |
250 | 0 | namespace_prefix = ""; |
251 | 0 | return s; |
252 | 0 | } |
253 | 0 | namespace_prefix = s.substr(0, pos); |
254 | 0 | return s.substr(pos + 1); |
255 | 0 | } |
256 | | |
257 | | // Same as above, but disregards the prefix. |
258 | | virtual std::string Denamespace(const std::string& s, |
259 | 0 | const char delimiter = '.') const { |
260 | 0 | std::string prefix; |
261 | 0 | return Denamespace(s, prefix, delimiter); |
262 | 0 | } |
263 | | |
264 | | const Config config_; |
265 | | const std::set<std::string> keywords_; |
266 | | }; |
267 | | |
268 | | } // namespace flatbuffers |
269 | | |
270 | | #endif // FLATBUFFERS_INCLUDE_CODEGEN_NAMER_H_ |