1 /* 2 * Copyright 2014 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_CODE_GENERATORS_H_ 18 #define FLATBUFFERS_CODE_GENERATORS_H_ 19 20 #include <map> 21 #include <sstream> 22 23 #include "flatbuffers/idl.h" 24 25 namespace flatbuffers { 26 27 // Utility class to assist in generating code through use of text templates. 28 // 29 // Example code: 30 // CodeWriter code("\t"); 31 // code.SetValue("NAME", "Foo"); 32 // code += "void {{NAME}}() { printf("%s", "{{NAME}}"); }"; 33 // code.SetValue("NAME", "Bar"); 34 // code += "void {{NAME}}() { printf("%s", "{{NAME}}"); }"; 35 // std::cout << code.ToString() << std::endl; 36 // 37 // Output: 38 // void Foo() { printf("%s", "Foo"); } 39 // void Bar() { printf("%s", "Bar"); } 40 class CodeWriter { 41 public: 42 CodeWriter(std::string pad = std::string()) pad_(pad)43 : pad_(pad), cur_ident_lvl_(0), ignore_ident_(false) {} 44 45 // Clears the current "written" code. Clear()46 void Clear() { 47 stream_.str(""); 48 stream_.clear(); 49 } 50 51 // Associates a key with a value. All subsequent calls to operator+=, where 52 // the specified key is contained in {{ and }} delimiters will be replaced by 53 // the given value. SetValue(const std::string & key,const std::string & value)54 void SetValue(const std::string &key, const std::string &value) { 55 value_map_[key] = value; 56 } 57 GetValue(const std::string & key)58 std::string GetValue(const std::string &key) const { 59 const auto it = value_map_.find(key); 60 return it == value_map_.end() ? "" : it->second; 61 } 62 63 // Appends the given text to the generated code as well as a newline 64 // character. Any text within {{ and }} delimiters is replaced by values 65 // previously stored in the CodeWriter by calling SetValue above. The newline 66 // will be suppressed if the text ends with the \\ character. 67 void operator+=(std::string text); 68 69 // Returns the current contents of the CodeWriter as a std::string. ToString()70 std::string ToString() const { return stream_.str(); } 71 72 // Increase ident level for writing code IncrementIdentLevel()73 void IncrementIdentLevel() { cur_ident_lvl_++; } 74 // Decrease ident level for writing code DecrementIdentLevel()75 void DecrementIdentLevel() { 76 if (cur_ident_lvl_) cur_ident_lvl_--; 77 } 78 SetPadding(const std::string & padding)79 void SetPadding(const std::string &padding) { pad_ = padding; } 80 81 private: 82 std::map<std::string, std::string> value_map_; 83 std::stringstream stream_; 84 std::string pad_; 85 int cur_ident_lvl_; 86 bool ignore_ident_; 87 88 // Add ident padding (tab or space) based on ident level 89 void AppendIdent(std::stringstream &stream); 90 }; 91 92 class BaseGenerator { 93 public: 94 virtual bool generate() = 0; 95 96 static std::string NamespaceDir(const Parser &parser, const std::string &path, 97 const Namespace &ns, 98 const bool dasherize = false); 99 100 static std::string ToDasherizedCase(const std::string pascal_case); 101 102 std::string GeneratedFileName(const std::string &path, 103 const std::string &file_name, 104 const IDLOptions &options) const; 105 106 protected: BaseGenerator(const Parser & parser,const std::string & path,const std::string & file_name,std::string qualifying_start,std::string qualifying_separator,std::string default_extension)107 BaseGenerator(const Parser &parser, const std::string &path, 108 const std::string &file_name, std::string qualifying_start, 109 std::string qualifying_separator, std::string default_extension) 110 : parser_(parser), 111 path_(path), 112 file_name_(file_name), 113 qualifying_start_(qualifying_start), 114 qualifying_separator_(qualifying_separator), 115 default_extension_(default_extension) {} ~BaseGenerator()116 virtual ~BaseGenerator() {} 117 118 // No copy/assign. 119 BaseGenerator &operator=(const BaseGenerator &); 120 BaseGenerator(const BaseGenerator &); 121 122 std::string NamespaceDir(const Namespace &ns, 123 const bool dasherize = false) const; 124 125 static const char *FlatBuffersGeneratedWarning(); 126 127 static std::string FullNamespace(const char *separator, const Namespace &ns); 128 129 static std::string LastNamespacePart(const Namespace &ns); 130 131 // tracks the current namespace for early exit in WrapInNameSpace 132 // c++, java and csharp returns a different namespace from 133 // the following default (no early exit, always fully qualify), 134 // which works for js and php CurrentNameSpace()135 virtual const Namespace *CurrentNameSpace() const { return nullptr; } 136 137 // Ensure that a type is prefixed with its namespace even within 138 // its own namespace to avoid conflict between generated method 139 // names and similarly named classes or structs 140 std::string WrapInNameSpace(const Namespace *ns, 141 const std::string &name) const; 142 143 std::string WrapInNameSpace(const Definition &def) const; 144 145 std::string GetNameSpace(const Definition &def) const; 146 147 const Parser &parser_; 148 const std::string &path_; 149 const std::string &file_name_; 150 const std::string qualifying_start_; 151 const std::string qualifying_separator_; 152 const std::string default_extension_; 153 }; 154 155 struct CommentConfig { 156 const char *first_line; 157 const char *content_line_prefix; 158 const char *last_line; 159 }; 160 161 extern void GenComment(const std::vector<std::string> &dc, 162 std::string *code_ptr, const CommentConfig *config, 163 const char *prefix = ""); 164 165 class FloatConstantGenerator { 166 public: ~FloatConstantGenerator()167 virtual ~FloatConstantGenerator() {} 168 std::string GenFloatConstant(const FieldDef &field) const; 169 170 private: 171 virtual std::string Value(double v, const std::string &src) const = 0; 172 virtual std::string Inf(double v) const = 0; 173 virtual std::string NaN(double v) const = 0; 174 175 virtual std::string Value(float v, const std::string &src) const = 0; 176 virtual std::string Inf(float v) const = 0; 177 virtual std::string NaN(float v) const = 0; 178 179 template<typename T> 180 std::string GenFloatConstantImpl(const FieldDef &field) const; 181 }; 182 183 class SimpleFloatConstantGenerator : public FloatConstantGenerator { 184 public: 185 SimpleFloatConstantGenerator(const char *nan_number, 186 const char *pos_inf_number, 187 const char *neg_inf_number); 188 189 private: 190 std::string Value(double v, 191 const std::string &src) const FLATBUFFERS_OVERRIDE; 192 std::string Inf(double v) const FLATBUFFERS_OVERRIDE; 193 std::string NaN(double v) const FLATBUFFERS_OVERRIDE; 194 195 std::string Value(float v, const std::string &src) const FLATBUFFERS_OVERRIDE; 196 std::string Inf(float v) const FLATBUFFERS_OVERRIDE; 197 std::string NaN(float v) const FLATBUFFERS_OVERRIDE; 198 199 const std::string nan_number_; 200 const std::string pos_inf_number_; 201 const std::string neg_inf_number_; 202 }; 203 204 // C++, C#, Java like generator. 205 class TypedFloatConstantGenerator : public FloatConstantGenerator { 206 public: 207 TypedFloatConstantGenerator(const char *double_prefix, 208 const char *single_prefix, const char *nan_number, 209 const char *pos_inf_number, 210 const char *neg_inf_number = ""); 211 212 private: 213 std::string Value(double v, 214 const std::string &src) const FLATBUFFERS_OVERRIDE; 215 std::string Inf(double v) const FLATBUFFERS_OVERRIDE; 216 217 std::string NaN(double v) const FLATBUFFERS_OVERRIDE; 218 219 std::string Value(float v, const std::string &src) const FLATBUFFERS_OVERRIDE; 220 std::string Inf(float v) const FLATBUFFERS_OVERRIDE; 221 std::string NaN(float v) const FLATBUFFERS_OVERRIDE; 222 223 std::string MakeNaN(const std::string &prefix) const; 224 std::string MakeInf(bool neg, const std::string &prefix) const; 225 226 const std::string double_prefix_; 227 const std::string single_prefix_; 228 const std::string nan_number_; 229 const std::string pos_inf_number_; 230 const std::string neg_inf_number_; 231 }; 232 233 } // namespace flatbuffers 234 235 #endif // FLATBUFFERS_CODE_GENERATORS_H_ 236