| 30 |
ashish |
1 |
/*
|
|
|
2 |
* Licensed to the Apache Software Foundation (ASF) under one
|
|
|
3 |
* or more contributor license agreements. See the NOTICE file
|
|
|
4 |
* distributed with this work for additional information
|
|
|
5 |
* regarding copyright ownership. The ASF licenses this file
|
|
|
6 |
* to you under the Apache License, Version 2.0 (the
|
|
|
7 |
* "License"); you may not use this file except in compliance
|
|
|
8 |
* with the License. You may obtain a copy of the License at
|
|
|
9 |
*
|
|
|
10 |
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
11 |
*
|
|
|
12 |
* Unless required by applicable law or agreed to in writing,
|
|
|
13 |
* software distributed under the License is distributed on an
|
|
|
14 |
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
|
15 |
* KIND, either express or implied. See the License for the
|
|
|
16 |
* specific language governing permissions and limitations
|
|
|
17 |
* under the License.
|
|
|
18 |
*/
|
|
|
19 |
|
|
|
20 |
#ifndef T_GENERATOR_H
|
|
|
21 |
#define T_GENERATOR_H
|
|
|
22 |
|
|
|
23 |
#include <string>
|
|
|
24 |
#include <iostream>
|
|
|
25 |
#include <fstream>
|
|
|
26 |
#include <sstream>
|
|
|
27 |
#include "parse/t_program.h"
|
|
|
28 |
#include "globals.h"
|
|
|
29 |
|
|
|
30 |
/**
|
|
|
31 |
* Base class for a thrift code generator. This class defines the basic
|
|
|
32 |
* routines for code generation and contains the top level method that
|
|
|
33 |
* dispatches code generation across various components.
|
|
|
34 |
*
|
|
|
35 |
*/
|
|
|
36 |
class t_generator {
|
|
|
37 |
public:
|
|
|
38 |
t_generator(t_program* program) {
|
|
|
39 |
tmp_ = 0;
|
|
|
40 |
indent_ = 0;
|
|
|
41 |
program_ = program;
|
|
|
42 |
program_name_ = get_program_name(program);
|
|
|
43 |
escape_['\n'] = "\\n";
|
|
|
44 |
escape_['\r'] = "\\r";
|
|
|
45 |
escape_['\t'] = "\\t";
|
|
|
46 |
escape_['"'] = "\\\"";
|
|
|
47 |
escape_['\\'] = "\\\\";
|
|
|
48 |
}
|
|
|
49 |
|
|
|
50 |
virtual ~t_generator() {}
|
|
|
51 |
|
|
|
52 |
/**
|
|
|
53 |
* Framework generator method that iterates over all the parts of a program
|
|
|
54 |
* and performs general actions. This is implemented by the base class and
|
|
|
55 |
* should not normally be overwritten in the subclasses.
|
|
|
56 |
*/
|
|
|
57 |
virtual void generate_program();
|
|
|
58 |
|
|
|
59 |
const t_program* get_program() const { return program_; }
|
|
|
60 |
|
|
|
61 |
void generate_docstring_comment(std::ofstream& out,
|
|
|
62 |
const std::string& comment_start,
|
|
|
63 |
const std::string& line_prefix,
|
|
|
64 |
const std::string& contents,
|
|
|
65 |
const std::string& comment_end);
|
|
|
66 |
|
|
|
67 |
/**
|
|
|
68 |
* Escape string to use one in generated sources.
|
|
|
69 |
*/
|
|
|
70 |
virtual std::string escape_string(const std::string &in) const;
|
|
|
71 |
|
|
|
72 |
std::string get_escaped_string(t_const_value* constval) {
|
|
|
73 |
return escape_string(constval->get_string());
|
|
|
74 |
}
|
|
|
75 |
|
|
|
76 |
protected:
|
|
|
77 |
|
|
|
78 |
/**
|
|
|
79 |
* Optional methods that may be imlemented by subclasses to take necessary
|
|
|
80 |
* steps at the beginning or end of code generation.
|
|
|
81 |
*/
|
|
|
82 |
|
|
|
83 |
virtual void init_generator() {}
|
|
|
84 |
virtual void close_generator() {}
|
|
|
85 |
|
|
|
86 |
virtual void generate_consts(std::vector<t_const*> consts);
|
|
|
87 |
|
|
|
88 |
/**
|
|
|
89 |
* Pure virtual methods implemented by the generator subclasses.
|
|
|
90 |
*/
|
|
|
91 |
|
|
|
92 |
virtual void generate_typedef (t_typedef* ttypedef) = 0;
|
|
|
93 |
virtual void generate_enum (t_enum* tenum) = 0;
|
|
|
94 |
virtual void generate_const (t_const* tconst) {}
|
|
|
95 |
virtual void generate_struct (t_struct* tstruct) = 0;
|
|
|
96 |
virtual void generate_service (t_service* tservice) = 0;
|
|
|
97 |
virtual void generate_xception (t_struct* txception) {
|
|
|
98 |
// By default exceptions are the same as structs
|
|
|
99 |
generate_struct(txception);
|
|
|
100 |
}
|
|
|
101 |
|
|
|
102 |
/**
|
|
|
103 |
* Method to get the program name, may be overridden
|
|
|
104 |
*/
|
|
|
105 |
virtual std::string get_program_name(t_program* tprogram) {
|
|
|
106 |
return tprogram->get_name();
|
|
|
107 |
}
|
|
|
108 |
|
|
|
109 |
/**
|
|
|
110 |
* Method to get the service name, may be overridden
|
|
|
111 |
*/
|
|
|
112 |
virtual std::string get_service_name(t_service* tservice) {
|
|
|
113 |
return tservice->get_name();
|
|
|
114 |
}
|
|
|
115 |
|
|
|
116 |
/**
|
|
|
117 |
* Get the current output directory
|
|
|
118 |
*/
|
|
|
119 |
virtual std::string get_out_dir() const {
|
|
|
120 |
return program_->get_out_path() + out_dir_base_ + "/";
|
|
|
121 |
}
|
|
|
122 |
|
|
|
123 |
/**
|
|
|
124 |
* Creates a unique temporary variable name, which is just "name" with a
|
|
|
125 |
* number appended to it (i.e. name35)
|
|
|
126 |
*/
|
|
|
127 |
std::string tmp(std::string name) {
|
|
|
128 |
std::ostringstream out;
|
|
|
129 |
out << name << tmp_++;
|
|
|
130 |
return out.str();
|
|
|
131 |
}
|
|
|
132 |
|
|
|
133 |
/**
|
|
|
134 |
* Indentation level modifiers
|
|
|
135 |
*/
|
|
|
136 |
|
|
|
137 |
void indent_up(){
|
|
|
138 |
++indent_;
|
|
|
139 |
}
|
|
|
140 |
|
|
|
141 |
void indent_down() {
|
|
|
142 |
--indent_;
|
|
|
143 |
}
|
|
|
144 |
|
|
|
145 |
/**
|
|
|
146 |
* Indentation print function
|
|
|
147 |
*/
|
|
|
148 |
std::string indent() {
|
|
|
149 |
std::string ind = "";
|
|
|
150 |
int i;
|
|
|
151 |
for (i = 0; i < indent_; ++i) {
|
|
|
152 |
ind += " ";
|
|
|
153 |
}
|
|
|
154 |
return ind;
|
|
|
155 |
}
|
|
|
156 |
|
|
|
157 |
/**
|
|
|
158 |
* Indentation utility wrapper
|
|
|
159 |
*/
|
|
|
160 |
std::ostream& indent(std::ostream &os) {
|
|
|
161 |
return os << indent();
|
|
|
162 |
}
|
|
|
163 |
|
|
|
164 |
/**
|
|
|
165 |
* Capitalization helpers
|
|
|
166 |
*/
|
|
|
167 |
std::string capitalize(std::string in) {
|
|
|
168 |
in[0] = toupper(in[0]);
|
|
|
169 |
return in;
|
|
|
170 |
}
|
|
|
171 |
std::string decapitalize(std::string in) {
|
|
|
172 |
in[0] = tolower(in[0]);
|
|
|
173 |
return in;
|
|
|
174 |
}
|
|
|
175 |
std::string lowercase(std::string in) {
|
|
|
176 |
for (size_t i = 0; i < in.size(); ++i) {
|
|
|
177 |
in[i] = tolower(in[i]);
|
|
|
178 |
}
|
|
|
179 |
return in;
|
|
|
180 |
}
|
|
|
181 |
std::string underscore(std::string in) {
|
|
|
182 |
in[0] = tolower(in[0]);
|
|
|
183 |
for (size_t i = 1; i < in.size(); ++i) {
|
|
|
184 |
if (isupper(in[i])) {
|
|
|
185 |
in[i] = tolower(in[i]);
|
|
|
186 |
in.insert(i, "_");
|
|
|
187 |
}
|
|
|
188 |
}
|
|
|
189 |
return in;
|
|
|
190 |
}
|
|
|
191 |
|
|
|
192 |
/**
|
|
|
193 |
* Get the true type behind a series of typedefs.
|
|
|
194 |
*/
|
|
|
195 |
static t_type* get_true_type(t_type* type) {
|
|
|
196 |
while (type->is_typedef()) {
|
|
|
197 |
type = ((t_typedef*)type)->get_type();
|
|
|
198 |
}
|
|
|
199 |
return type;
|
|
|
200 |
}
|
|
|
201 |
|
|
|
202 |
protected:
|
|
|
203 |
/**
|
|
|
204 |
* The program being generated
|
|
|
205 |
*/
|
|
|
206 |
t_program* program_;
|
|
|
207 |
|
|
|
208 |
/**
|
|
|
209 |
* Quick accessor for formatted program name that is currently being
|
|
|
210 |
* generated.
|
|
|
211 |
*/
|
|
|
212 |
std::string program_name_;
|
|
|
213 |
|
|
|
214 |
/**
|
|
|
215 |
* Quick accessor for formatted service name that is currently being
|
|
|
216 |
* generated.
|
|
|
217 |
*/
|
|
|
218 |
std::string service_name_;
|
|
|
219 |
|
|
|
220 |
/**
|
|
|
221 |
* Output type-specifc directory name ("gen-*")
|
|
|
222 |
*/
|
|
|
223 |
std::string out_dir_base_;
|
|
|
224 |
|
|
|
225 |
/**
|
|
|
226 |
* Map of characters to escape in string literals.
|
|
|
227 |
*/
|
|
|
228 |
std::map<char, std::string> escape_;
|
|
|
229 |
|
|
|
230 |
private:
|
|
|
231 |
/**
|
|
|
232 |
* Current code indentation level
|
|
|
233 |
*/
|
|
|
234 |
int indent_;
|
|
|
235 |
|
|
|
236 |
/**
|
|
|
237 |
* Temporary variable counter, for making unique variable names
|
|
|
238 |
*/
|
|
|
239 |
int tmp_;
|
|
|
240 |
};
|
|
|
241 |
|
|
|
242 |
|
|
|
243 |
/**
|
|
|
244 |
* A factory for producing generator classes of a particular language.
|
|
|
245 |
*
|
|
|
246 |
* This class is also responsible for:
|
|
|
247 |
* - Registering itself with the generator registry.
|
|
|
248 |
* - Providing documentation for the generators it produces.
|
|
|
249 |
*/
|
|
|
250 |
class t_generator_factory {
|
|
|
251 |
public:
|
|
|
252 |
t_generator_factory(const std::string& short_name,
|
|
|
253 |
const std::string& long_name,
|
|
|
254 |
const std::string& documentation);
|
|
|
255 |
|
|
|
256 |
virtual ~t_generator_factory() {}
|
|
|
257 |
|
|
|
258 |
virtual t_generator* get_generator(
|
|
|
259 |
// The program to generate.
|
|
|
260 |
t_program* program,
|
|
|
261 |
// Note: parsed_options will not exist beyond the call to get_generator.
|
|
|
262 |
const std::map<std::string, std::string>& parsed_options,
|
|
|
263 |
// Note: option_string might not exist beyond the call to get_generator.
|
|
|
264 |
const std::string& option_string)
|
|
|
265 |
= 0;
|
|
|
266 |
|
|
|
267 |
std::string get_short_name() { return short_name_; }
|
|
|
268 |
std::string get_long_name() { return long_name_; }
|
|
|
269 |
std::string get_documentation() { return documentation_; }
|
|
|
270 |
|
|
|
271 |
private:
|
|
|
272 |
std::string short_name_;
|
|
|
273 |
std::string long_name_;
|
|
|
274 |
std::string documentation_;
|
|
|
275 |
};
|
|
|
276 |
|
|
|
277 |
template <typename generator>
|
|
|
278 |
class t_generator_factory_impl : public t_generator_factory {
|
|
|
279 |
public:
|
|
|
280 |
t_generator_factory_impl(const std::string& short_name,
|
|
|
281 |
const std::string& long_name,
|
|
|
282 |
const std::string& documentation)
|
|
|
283 |
: t_generator_factory(short_name, long_name, documentation)
|
|
|
284 |
{}
|
|
|
285 |
|
|
|
286 |
virtual t_generator* get_generator(
|
|
|
287 |
t_program* program,
|
|
|
288 |
const std::map<std::string, std::string>& parsed_options,
|
|
|
289 |
const std::string& option_string) {
|
|
|
290 |
return new generator(program, parsed_options, option_string);
|
|
|
291 |
}
|
|
|
292 |
};
|
|
|
293 |
|
|
|
294 |
class t_generator_registry {
|
|
|
295 |
public:
|
|
|
296 |
static void register_generator(t_generator_factory* factory);
|
|
|
297 |
|
|
|
298 |
static t_generator* get_generator(t_program* program,
|
|
|
299 |
const std::string& options);
|
|
|
300 |
|
|
|
301 |
typedef std::map<std::string, t_generator_factory*> gen_map_t;
|
|
|
302 |
static gen_map_t& get_generator_map();
|
|
|
303 |
|
|
|
304 |
private:
|
|
|
305 |
t_generator_registry();
|
|
|
306 |
t_generator_registry(const t_generator_registry&);
|
|
|
307 |
};
|
|
|
308 |
|
|
|
309 |
#define THRIFT_REGISTER_GENERATOR(language, long_name, doc) \
|
|
|
310 |
class t_##language##_generator_factory_impl \
|
|
|
311 |
: public t_generator_factory_impl<t_##language##_generator> \
|
|
|
312 |
{ \
|
|
|
313 |
public: \
|
|
|
314 |
t_##language##_generator_factory_impl() \
|
|
|
315 |
: t_generator_factory_impl<t_##language##_generator>( \
|
|
|
316 |
#language, long_name, doc) \
|
|
|
317 |
{} \
|
|
|
318 |
}; \
|
|
|
319 |
static t_##language##_generator_factory_impl _registerer;
|
|
|
320 |
|
|
|
321 |
#endif
|