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 }} delimeters 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 79 private: 80 std::map<std::string, std::string> value_map_; 81 std::stringstream stream_; 82 std::string pad_; 83 int cur_ident_lvl_; 84 bool ignore_ident_; 85 86 // Add ident padding (tab or space) based on ident level 87 void AppendIdent(std::stringstream &stream); 88 }; 89 90 class BaseGenerator { 91 public: 92 virtual bool generate() = 0; 93 94 static std::string NamespaceDir(const Parser &parser, const std::string &path, 95 const Namespace &ns); 96 97 std::string GeneratedFileName(const std::string &path, 98 const std::string &file_name, 99 const IDLOptions &options) const; 100 101 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)102 BaseGenerator(const Parser &parser, const std::string &path, 103 const std::string &file_name, std::string qualifying_start, 104 std::string qualifying_separator, std::string default_extension) 105 : parser_(parser), 106 path_(path), 107 file_name_(file_name), 108 qualifying_start_(qualifying_start), 109 qualifying_separator_(qualifying_separator), 110 default_extension_(default_extension) {} ~BaseGenerator()111 virtual ~BaseGenerator() {} 112 113 // No copy/assign. 114 BaseGenerator &operator=(const BaseGenerator &); 115 BaseGenerator(const BaseGenerator &); 116 117 std::string NamespaceDir(const Namespace &ns) const; 118 119 static const char *FlatBuffersGeneratedWarning(); 120 121 static std::string FullNamespace(const char *separator, const Namespace &ns); 122 123 static std::string LastNamespacePart(const Namespace &ns); 124 125 // tracks the current namespace for early exit in WrapInNameSpace 126 // c++, java and csharp returns a different namespace from 127 // the following default (no early exit, always fully qualify), 128 // which works for js and php CurrentNameSpace()129 virtual const Namespace *CurrentNameSpace() const { return nullptr; } 130 131 // Ensure that a type is prefixed with its namespace even within 132 // its own namespace to avoid conflict between generated method 133 // names and similarly named classes or structs 134 std::string WrapInNameSpace(const Namespace *ns, 135 const std::string &name) const; 136 137 std::string WrapInNameSpace(const Definition &def) const; 138 139 std::string GetNameSpace(const Definition &def) const; 140 141 const Parser &parser_; 142 const std::string &path_; 143 const std::string &file_name_; 144 const std::string qualifying_start_; 145 const std::string qualifying_separator_; 146 const std::string default_extension_; 147 }; 148 149 struct CommentConfig { 150 const char *first_line; 151 const char *content_line_prefix; 152 const char *last_line; 153 }; 154 155 extern void GenComment(const std::vector<std::string> &dc, 156 std::string *code_ptr, const CommentConfig *config, 157 const char *prefix = ""); 158 159 class FloatConstantGenerator { 160 public: ~FloatConstantGenerator()161 virtual ~FloatConstantGenerator() {} 162 std::string GenFloatConstant(const FieldDef &field) const; 163 164 private: 165 virtual std::string Value(double v, const std::string &src) const = 0; 166 virtual std::string Inf(double v) const = 0; 167 virtual std::string NaN(double v) const = 0; 168 169 virtual std::string Value(float v, const std::string &src) const = 0; 170 virtual std::string Inf(float v) const = 0; 171 virtual std::string NaN(float v) const = 0; 172 173 template<typename T> 174 std::string GenFloatConstantImpl(const FieldDef &field) const; 175 }; 176 177 class SimpleFloatConstantGenerator : public FloatConstantGenerator { 178 public: 179 SimpleFloatConstantGenerator(const char *nan_number, 180 const char *pos_inf_number, 181 const char *neg_inf_number); 182 183 private: 184 std::string Value(double v, 185 const std::string &src) const FLATBUFFERS_OVERRIDE; 186 std::string Inf(double v) const FLATBUFFERS_OVERRIDE; 187 std::string NaN(double v) const FLATBUFFERS_OVERRIDE; 188 189 std::string Value(float v, const std::string &src) const FLATBUFFERS_OVERRIDE; 190 std::string Inf(float v) const FLATBUFFERS_OVERRIDE; 191 std::string NaN(float v) const FLATBUFFERS_OVERRIDE; 192 193 const std::string nan_number_; 194 const std::string pos_inf_number_; 195 const std::string neg_inf_number_; 196 }; 197 198 // C++, C#, Java like generator. 199 class TypedFloatConstantGenerator : public FloatConstantGenerator { 200 public: 201 TypedFloatConstantGenerator(const char *double_prefix, 202 const char *single_prefix, const char *nan_number, 203 const char *pos_inf_number, 204 const char *neg_inf_number = ""); 205 206 private: 207 std::string Value(double v, 208 const std::string &src) const FLATBUFFERS_OVERRIDE; 209 std::string Inf(double v) const FLATBUFFERS_OVERRIDE; 210 211 std::string NaN(double v) const FLATBUFFERS_OVERRIDE; 212 213 std::string Value(float v, const std::string &src) const FLATBUFFERS_OVERRIDE; 214 std::string Inf(float v) const FLATBUFFERS_OVERRIDE; 215 std::string NaN(float v) const FLATBUFFERS_OVERRIDE; 216 217 std::string MakeNaN(const std::string &prefix) const; 218 std::string MakeInf(bool neg, const std::string &prefix) const; 219 220 const std::string double_prefix_; 221 const std::string single_prefix_; 222 const std::string nan_number_; 223 const std::string pos_inf_number_; 224 const std::string neg_inf_number_; 225 }; 226 227 } // namespace flatbuffers 228 229 #endif // FLATBUFFERS_CODE_GENERATORS_H_ 230