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