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