blob: f8f2a1ce67baa4de916c9d0f4ea5d909b12b927f [file] [log] [blame]
Jake Farrell7ae13e12011-10-18 14:35:26 +00001/*
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 * Contains some contributions under the Thrift Software License.
20 * Please see doc/old-thrift-license.txt in the Thrift distribution for
21 * details.
22 */
23
Jens Geyerec8744c2013-09-06 21:08:24 +020024#include <cassert>
25
Jake Farrell7ae13e12011-10-18 14:35:26 +000026#include <string>
27#include <fstream>
28#include <iostream>
29#include <vector>
Jake Farrelld11c8bc2012-05-21 00:07:14 +000030#include <list>
Jake Farrell7ae13e12011-10-18 14:35:26 +000031
32#include <stdlib.h>
33#include <sys/stat.h>
34#include <sstream>
Roger Meier9212e792012-06-12 21:01:06 +000035#include <cctype>
Jake Farrell7ae13e12011-10-18 14:35:26 +000036
Jake Farrell7ae13e12011-10-18 14:35:26 +000037#include "platform.h"
38#include "t_oop_generator.h"
39
Jens Geyer945537c2013-01-04 19:33:29 +010040using std::map;
41using std::ofstream;
42using std::ostream;
43using std::ostringstream;
44using std::string;
45using std::stringstream;
46using std::vector;
Jake Farrell7ae13e12011-10-18 14:35:26 +000047
Jens Geyer945537c2013-01-04 19:33:29 +010048static const string endl = "\n"; // avoid ostream << std::endl flushes
Jake Farrell7ae13e12011-10-18 14:35:26 +000049
50class t_delphi_generator : public t_oop_generator
51{
52 public:
53 t_delphi_generator(
54 t_program* program,
55 const std::map<std::string, std::string>& parsed_options,
56 const std::string& option_string)
57 : t_oop_generator(program)
58 {
59 (void) option_string;
60
61 std::map<std::string, std::string>::const_iterator iter;
62
63 iter = parsed_options.find("ansistr_binary");
64 ansistr_binary_ = (iter != parsed_options.end());
Jens Geyerc2c4d722013-06-04 21:43:40 +020065 iter = parsed_options.find("register_types");
66 register_types_ = (iter != parsed_options.end());
Jens Geyerec8744c2013-09-06 21:08:24 +020067 iter = parsed_options.find("constprefix");
68 constprefix_ = (iter != parsed_options.end());
69
Jake Farrell7ae13e12011-10-18 14:35:26 +000070
Jake Farrell7ae13e12011-10-18 14:35:26 +000071 out_dir_base_ = "gen-delphi";
72 escape_.clear();
73 escape_['\''] = "''";
74 }
75
76
77 void init_generator();
78 void close_generator();
79
80 void generate_consts(std::vector<t_const*> consts);
81
82 void generate_typedef (t_typedef* ttypedef);
83 void generate_enum (t_enum* tenum);
84 void generate_struct (t_struct* tstruct);
85 void generate_xception (t_struct* txception);
86 void generate_service (t_service* tservice);
87 void generate_property(ostream& out, t_field* tfield, bool isPublic, bool is_xception);
88 void generate_property_writer_(ostream& out, t_field* tfield, bool isPublic);
89
90 void generate_delphi_property(ostream& out, bool struct_is_exception, t_field* tfield, bool isPublic, std::string fieldPrefix = "");
Jake Farrell85147552011-10-20 13:30:08 +000091 void generate_delphi_isset_reader_definition(ostream& out, t_field* tfield, bool is_xception);
92 void generate_delphi_property_reader_definition(ostream& out, t_field* tfield, bool is_xception_class);
93 void generate_delphi_property_writer_definition(ostream& out, t_field* tfield, bool is_xception_class);
94 void generate_delphi_property_reader_impl(ostream& out, std::string cls_prefix, std::string name, t_type* type, t_field* tfield, std::string fieldPrefix, bool is_xception_class);
Jens Geyera58a9cb2012-12-17 23:24:13 +010095 void generate_delphi_property_writer_impl(ostream& out, std::string cls_prefix, std::string name, t_type* type, t_field* tfield, std::string fieldPrefix, bool is_xception_class, bool is_union, bool is_xception_factory, std::string xception_factroy_name);
96 void generate_delphi_clear_union_value(ostream& out, std::string cls_prefix, std::string name, t_type* type, t_field* tfield, std::string fieldPrefix, bool is_xception_class, bool is_union, bool is_xception_factory, std::string xception_factroy_name);
Jake Farrell85147552011-10-20 13:30:08 +000097 void generate_delphi_isset_reader_impl(ostream& out, std::string cls_prefix, std::string name, t_type* type, t_field* tfield, std::string fieldPrefix, bool is_xception);
Jake Farrell7ae13e12011-10-18 14:35:26 +000098 void generate_delphi_struct_writer_impl(ostream& out, std::string cls_prefix, t_struct* tstruct, bool is_exception);
99 void generate_delphi_struct_result_writer_impl(ostream& out, std::string cls_prefix, t_struct* tstruct, bool is_exception);
100
Jake Farrellac102562011-11-23 14:30:41 +0000101 void generate_delphi_struct_tostring_impl(ostream& out, std::string cls_prefix, t_struct* tstruct, bool is_exception, bool is_x_factory);
Jake Farrell7ae13e12011-10-18 14:35:26 +0000102
103 void add_delphi_uses_list( string unitname);
104
105 void generate_delphi_struct_reader_impl(ostream& out, std::string cls_prefix, t_struct* tstruct, bool is_exception);
106 void generate_delphi_create_exception_impl(ostream& out, string cls_prefix, t_struct* tstruct, bool is_exception);
107
108 void print_const_prop(std::ostream& out, string name, t_type* type, t_const_value* value);
109 void print_private_field(std::ostream& out, string name, t_type* type, t_const_value* value);
110 void print_const_value ( std::ostream& vars, std::ostream& out, std::string name, t_type* type, t_const_value* value);
Jake Farrell6fa2b302011-12-06 00:59:30 +0000111 void initialize_field(std::ostream& vars, std::ostream& out, std::string name, t_type* type, t_const_value* value);
Jake Farrell7ae13e12011-10-18 14:35:26 +0000112 void finalize_field(std::ostream& out, std::string name, t_type* type, t_const_value* value, std::string cls_nm = "");
113 std::string render_const_value( std::ostream& local_vars, std::ostream& out, std::string name, t_type* type, t_const_value* value);
114 void print_const_def_value( std::ostream& vars, std::ostream& out, std::string name, t_type* type, t_const_value* value, std::string cls_nm = "");
Jens Geyerec8744c2013-09-06 21:08:24 +0200115 std::string make_constants_classname();
Jake Farrell7ae13e12011-10-18 14:35:26 +0000116
117 void generate_delphi_struct(t_struct* tstruct, bool is_exception);
118 void generate_delphi_struct_impl( ostream& out, std::string cls_prefix, t_struct* tstruct, bool is_exception, bool is_result = false, bool is_x_factory = false);
Jens Geyerc2c4d722013-06-04 21:43:40 +0200119 void print_delphi_struct_type_factory_func( ostream& out, t_struct* tstruct);
120 void generate_delphi_struct_type_factory( ostream& out, std::string cls_prefix, t_struct* tstruct, bool is_exception, bool is_result = false, bool is_x_factory = false);
121 void generate_delphi_struct_type_factory_registration( ostream& out, std::string cls_prefix, t_struct* tstruct, bool is_exception, bool is_result = false, bool is_x_factory = false);
Jake Farrell7ae13e12011-10-18 14:35:26 +0000122 void generate_delphi_struct_definition(std::ostream& out, t_struct* tstruct, bool is_xception=false, bool in_class=false, bool is_result=false, bool is_x_factory = false);
123 void generate_delphi_struct_reader(std::ostream& out, t_struct* tstruct);
124 void generate_delphi_struct_result_writer(std::ostream& out, t_struct* tstruct);
125 void generate_delphi_struct_writer(std::ostream& out, t_struct* tstruct);
126 void generate_delphi_struct_tostring(std::ostream& out, t_struct* tstruct);
127
128 void generate_function_helpers(t_function* tfunction);
129 void generate_service_interface (t_service* tservice);
130 void generate_service_helpers (t_service* tservice);
131 void generate_service_client (t_service* tservice);
132 void generate_service_server (t_service* tservice);
133 void generate_process_function (t_service* tservice, t_function* function);
134
135 void generate_deserialize_field (std::ostream& out, bool is_xception, t_field* tfield, std::string prefix, std::ostream& local_vars);
136 void generate_deserialize_struct (std::ostream& out, t_struct* tstruct, std::string name, std::string prefix);
137 void generate_deserialize_container(ostream& out, bool is_xception, t_type* ttype, string name, std::ostream& local_vars);
138
139 void generate_deserialize_set_element (std::ostream& out, bool is_xception, t_set* tset, std::string prefix, std::ostream& local_vars);
140 void generate_deserialize_map_element (std::ostream& out, bool is_xception, t_map* tmap, std::string prefix, std::ostream& local_vars);
141 void generate_deserialize_list_element (std::ostream& out, bool is_xception, t_list* list, std::string prefix, std::ostream& local_vars);
142
143 void generate_serialize_field (std::ostream& out, bool is_xception, t_field* tfield, std::string prefix, std::ostream& local_vars);
144 void generate_serialize_struct (std::ostream& out, t_struct* tstruct, std::string prefix, std::ostream& local_vars);
145 void generate_serialize_container (std::ostream& out, bool is_xception, t_type* ttype, std::string prefix, std::ostream& local_vars);
146 void generate_serialize_map_element (std::ostream& out, bool is_xception, t_map* tmap, std::string iter, std::string map, std::ostream& local_vars);
147 void generate_serialize_set_element (std::ostream& out, bool is_xception, t_set* tmap, std::string iter, std::ostream& local_vars);
148 void generate_serialize_list_element (std::ostream& out, bool is_xception, t_list* tlist, std::string iter, std::ostream& local_vars);
149
150 void delphi_type_usings(std::ostream& out);
151 std::string delphi_thrift_usings();
152
153 std::string type_name( t_type* ttype, bool b_cls=false, bool b_no_postfix=false, bool b_exception_factory=false, bool b_full_exception_factory = false);
154 std::string normalize_clsnm(std::string name, std::string prefix, bool b_no_check_keyword = false);
Jens Geyerec8744c2013-09-06 21:08:24 +0200155 std::string make_valid_delphi_identifier( std::string const & fromName);
Roger Meier333bbf32012-01-08 21:51:08 +0000156 std::string input_arg_prefix( t_type* ttype);
157
Jake Farrell7ae13e12011-10-18 14:35:26 +0000158 std::string base_type_name(t_base_type* tbase);
Jake Farrell85147552011-10-20 13:30:08 +0000159 std::string declare_field(t_field* tfield, bool init=false, std::string prefix="", bool is_xception_class = false);
Roger Meier333bbf32012-01-08 21:51:08 +0000160 std::string function_signature(t_function* tfunction, std::string full_cls="", bool is_xception = false);
Jake Farrell7ae13e12011-10-18 14:35:26 +0000161 std::string argument_list(t_struct* tstruct);
Jake Farrell343c61d2011-12-09 02:29:56 +0000162 std::string constructor_argument_list(t_struct* tstruct, std::string current_indent);
Jake Farrell7ae13e12011-10-18 14:35:26 +0000163 std::string type_to_enum(t_type* ttype);
164 std::string prop_name(t_field* tfield, bool is_xception = false);
165 std::string prop_name(std::string name, bool is_xception = false);
Jake Farrell343c61d2011-12-09 02:29:56 +0000166 std::string constructor_param_name(string name);
Jake Farrell7ae13e12011-10-18 14:35:26 +0000167
168 void write_enum(std::string line);
169 void write_forward_decr(std::string line);
170 void write_const(std::string line);
171 void write_struct(std::string line);
172 void write_service(std::string line);
173
174 virtual std::string autogen_comment() {
175 return
176 std::string("(**\n") +
Jake Farrell28459dc2011-11-05 13:36:27 +0000177 " * Autogenerated by Thrift Compiler (" + THRIFT_VERSION + ")\n" +
Jake Farrell7ae13e12011-10-18 14:35:26 +0000178 " *\n" +
179 " * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n" +
180 " *)\n";
181 }
182
183 bool type_can_be_null(t_type* ttype) {
184 while (ttype->is_typedef()) {
185 ttype = ((t_typedef*)ttype)->get_type();
186 }
187
188 return ttype->is_container() ||
189 ttype->is_struct() ||
190 ttype->is_xception();
191 }
192
193 private:
194 std::string namespace_name_;
195 std::ostringstream s_forward_decr;
196 std::ostringstream s_enum;
197 std::ostringstream s_const;
198 std::ostringstream s_struct;
199 std::ostringstream s_service;
200 std::ostringstream s_const_impl;
201 std::ostringstream s_struct_impl;
202 std::ostringstream s_service_impl;
Jens Geyerc2c4d722013-06-04 21:43:40 +0200203 std::ostringstream s_type_factory_registration;
204 std::ostringstream s_type_factory_funcs;
Jake Farrell7ae13e12011-10-18 14:35:26 +0000205 bool has_enum;
206 bool has_const;
207 std::string namespace_dir_;
208 std::map<std::string, int> delphi_keywords;
209 std::map<std::string, int> delphi_reserved_method;
210 std::map<std::string, int> delphi_reserved_method_exception;
Jake Farrelld11c8bc2012-05-21 00:07:14 +0000211 std::map<std::string, int> types_known;
212 std::list<t_typedef*> typedefs_pending;
Jake Farrell7ae13e12011-10-18 14:35:26 +0000213 std::vector<std::string> uses_list;
214 void create_keywords();
215 bool find_keyword( std::map<std::string, int>& keyword_map, std::string name);
216 std::string normalize_name( std::string name, bool b_method = false, bool b_exception_method = false);
217 std::string empty_value(t_type* type);
Jake Farrelld11c8bc2012-05-21 00:07:14 +0000218 bool is_fully_defined_type( t_type* ttype);
219 void add_defined_type( t_type* ttype);
220 void init_known_types_list();
Jake Farrell7ae13e12011-10-18 14:35:26 +0000221 bool is_void( t_type* type );
222 int indent_impl_;
223 bool ansistr_binary_;
Jens Geyerc2c4d722013-06-04 21:43:40 +0200224 bool register_types_;
Jens Geyerec8744c2013-09-06 21:08:24 +0200225 bool constprefix_;
Jake Farrell7ae13e12011-10-18 14:35:26 +0000226 void indent_up_impl(){
227 ++indent_impl_;
228 };
229 void indent_down_impl() {
230 --indent_impl_;
231 };
232 std::string indent_impl() {
233 std::string ind = "";
234 int i;
235 for (i = 0; i < indent_impl_; ++i) {
236 ind += " ";
237 }
238 return ind;
239 };
240 std::ostream& indent_impl(std::ostream &os) {
241 return os << indent_impl();
242 };
243};
244
Jake Farrell7ae13e12011-10-18 14:35:26 +0000245bool t_delphi_generator::find_keyword( std::map<std::string, int>& keyword_map, std::string name) {
246 int len = name.length();
247
248 if ( len <= 0 ) {
249 return false;
250 }
251
252 int nlast = name.find_last_of('_');
253
254 if ( nlast >= 1) {
255 if (nlast == (len - 1)) {
256 string new_name( name, 0, nlast);
257 return find_keyword( keyword_map, new_name);
258 }
259 }
260 return (keyword_map[name] == 1);
261}
262
263std::string t_delphi_generator::normalize_name( std::string name, bool b_method, bool b_exception_method) {
264 string tmp( name );
265 std::transform(tmp.begin(), tmp.end(), tmp.begin(), static_cast<int (*)(int)>(std::tolower));
266
267 bool b_found = false;
268
269 if ( find_keyword( delphi_keywords, tmp) ) {
270 b_found = true;
271 } else if ( b_method && find_keyword( delphi_reserved_method, tmp)) {
272 b_found = true;
Jake Farrell85147552011-10-20 13:30:08 +0000273 } else if ( b_exception_method && find_keyword( delphi_reserved_method_exception, tmp)) {
Jake Farrell7ae13e12011-10-18 14:35:26 +0000274 b_found = true;
275 }
276
277 if (b_found) {
278 return name + "_";
279 } else {
280 return name;
281 }
282}
283
284void t_delphi_generator::create_keywords() {
285 delphi_keywords["and"] = 1;
286 delphi_keywords["end"] = 1;
287 delphi_keywords["interface"] = 1;
288 delphi_keywords["raise"] = 1;
289 delphi_keywords["uses"] = 1;
290 delphi_keywords["array"] = 1;
291 delphi_keywords["except"] = 1;
292 delphi_keywords["is"] = 1;
293 delphi_keywords["record"] = 1;
294 delphi_keywords["var"] = 1;
295 delphi_keywords["as"] = 1;
296 delphi_keywords["exports"] = 1;
297 delphi_keywords["label"] = 1;
298 delphi_keywords["repeat"] = 1;
299 delphi_keywords["while"] = 1;
300 delphi_keywords["asm"] = 1;
301 delphi_keywords["file"] = 1;
302 delphi_keywords["library"] = 1;
303 delphi_keywords["resourcestring"] = 1;
304 delphi_keywords["with"] = 1;
305 delphi_keywords["begin"] = 1;
306 delphi_keywords["finalization"] = 1;
307 delphi_keywords["mod"] = 1;
308 delphi_keywords["set"] = 1;
309 delphi_keywords["xor"] = 1;
310 delphi_keywords["case"] = 1;
311 delphi_keywords["finally"] = 1;
312 delphi_keywords["nil"] = 1;
313 delphi_keywords["shl"] = 1;
314 delphi_keywords["class"] = 1;
315 delphi_keywords["for"] = 1;
316 delphi_keywords["not"] = 1;
317 delphi_keywords["shr"] = 1;
318 delphi_keywords["const"] = 1;
319 delphi_keywords["function"] = 1;
320 delphi_keywords["object"] = 1;
321 delphi_keywords["string"] = 1;
322 delphi_keywords["constructor"] = 1;
323 delphi_keywords["goto"] = 1;
324 delphi_keywords["of"] = 1;
325 delphi_keywords["then"] = 1;
326 delphi_keywords["destructor"] = 1;
327 delphi_keywords["if"] = 1;
328 delphi_keywords["or"] = 1;
329 delphi_keywords["threadvar"] = 1;
330 delphi_keywords["dispinterface"] = 1;
331 delphi_keywords["implementation"] = 1;
332 delphi_keywords["out"] = 1;
333 delphi_keywords["to"] = 1;
334 delphi_keywords["div"] = 1;
335 delphi_keywords["in"] = 1;
336 delphi_keywords["packed"] = 1;
337 delphi_keywords["try"] = 1;
338 delphi_keywords["do"] = 1;
339 delphi_keywords["inherited"] = 1;
340 delphi_keywords["procedure"] = 1;
341 delphi_keywords["type"] = 1;
342 delphi_keywords["downto"] = 1;
343 delphi_keywords["initialization"] = 1;
344 delphi_keywords["program"] = 1;
345 delphi_keywords["unit"] = 1;
346 delphi_keywords["else"] = 1;
347 delphi_keywords["inline"] = 1;
348 delphi_keywords["property"] = 1;
349 delphi_keywords["until"] = 1;
350 delphi_keywords["private"] = 1;
351 delphi_keywords["protected"] = 1;
352 delphi_keywords["public"] = 1;
353 delphi_keywords["published"] = 1;
354 delphi_keywords["automated"] = 1;
355 delphi_keywords["at"] = 1;
356 delphi_keywords["on"] = 1;
Jens Geyer7af58682013-03-21 19:59:05 +0200357 delphi_keywords["result"] = 1;
Jake Farrell7ae13e12011-10-18 14:35:26 +0000358
359 delphi_reserved_method["create"] = 1;
360 delphi_reserved_method["free"] = 1;
361 delphi_reserved_method["initinstance"] = 1;
362 delphi_reserved_method["cleanupinstance"] = 1;
363 delphi_reserved_method["classtype"] = 1;
364 delphi_reserved_method["classname"] = 1;
365 delphi_reserved_method["classnameis"] = 1;
366 delphi_reserved_method["classparent"] = 1;
367 delphi_reserved_method["classinfo"] = 1;
368 delphi_reserved_method["instancesize"] = 1;
369 delphi_reserved_method["inheritsfrom"] = 1;
370 delphi_reserved_method["methodaddress"] = 1;
371 delphi_reserved_method["methodaddress"] = 1;
372 delphi_reserved_method["methodname"] = 1;
373 delphi_reserved_method["fieldaddress"] = 1;
374 delphi_reserved_method["fieldaddress"] = 1;
375 delphi_reserved_method["getinterface"] = 1;
376 delphi_reserved_method["getinterfaceentry"] = 1;
377 delphi_reserved_method["getinterfacetable"] = 1;
378 delphi_reserved_method["unitname"] = 1;
379 delphi_reserved_method["equals"] = 1;
380 delphi_reserved_method["gethashcode"] = 1;
381 delphi_reserved_method["tostring"] = 1;
382 delphi_reserved_method["safecallexception"] = 1;
383 delphi_reserved_method["afterconstruction"] = 1;
384 delphi_reserved_method["beforedestruction"] = 1;
385 delphi_reserved_method["dispatch"] = 1;
386 delphi_reserved_method["defaulthandler"] = 1;
387 delphi_reserved_method["newinstance"] = 1;
388 delphi_reserved_method["freeinstance"] = 1;
389 delphi_reserved_method["destroy"] = 1;
390 delphi_reserved_method["read"] = 1;
391 delphi_reserved_method["write"] = 1;
392
393 delphi_reserved_method_exception["setinnerexception"] = 1;
394 delphi_reserved_method_exception["setstackinfo"] = 1;
395 delphi_reserved_method_exception["getstacktrace"] = 1;
396 delphi_reserved_method_exception["raisingexception"] = 1;
397 delphi_reserved_method_exception["createfmt"] = 1;
398 delphi_reserved_method_exception["createres"] = 1;
399 delphi_reserved_method_exception["createresfmt"] = 1;
400 delphi_reserved_method_exception["createhelp"] = 1;
401 delphi_reserved_method_exception["createfmthelp"] = 1;
402 delphi_reserved_method_exception["createreshelp"] = 1;
403 delphi_reserved_method_exception["createresfmthelp"] = 1;
404 delphi_reserved_method_exception["getbaseexception"] = 1;
405 delphi_reserved_method_exception["baseexception"] = 1;
406 delphi_reserved_method_exception["helpcontext"] = 1;
407 delphi_reserved_method_exception["innerexception"] = 1;
408 delphi_reserved_method_exception["message"] = 1;
409 delphi_reserved_method_exception["stacktrace"] = 1;
410 delphi_reserved_method_exception["stackinfo"] = 1;
411 delphi_reserved_method_exception["getexceptionstackinfoproc"] = 1;
412 delphi_reserved_method_exception["getstackinfostringproc"] = 1;
413 delphi_reserved_method_exception["cleanupstackinfoproc"] = 1;
414 delphi_reserved_method_exception["raiseouterexception"] = 1;
415 delphi_reserved_method_exception["throwouterexception"] = 1;
416}
417
418void t_delphi_generator::add_delphi_uses_list( string unitname){
419 vector<std::string>::const_iterator s_iter;
420 bool found = false;
421 for (s_iter = uses_list.begin(); s_iter != uses_list.end(); ++s_iter) {
422 if ((*s_iter) == unitname ) {
423 found = true;
424 break;
425 }
426 }
427 if (! found) {
428 uses_list.push_back( unitname );
429 }
430}
431
432void t_delphi_generator::init_generator() {
433 indent_impl_ = 0;
434 namespace_name_ = program_->get_namespace("delphi");
435 has_enum = false;
436 has_const = false;
437 create_keywords();
438 add_delphi_uses_list("Classes");
439 add_delphi_uses_list("SysUtils");
440 add_delphi_uses_list("Generics.Collections");
441 add_delphi_uses_list("Thrift");
442 add_delphi_uses_list("Thrift.Utils");
443 add_delphi_uses_list("Thrift.Collections");
444 add_delphi_uses_list("Thrift.Protocol");
445 add_delphi_uses_list("Thrift.Transport");
446
Jens Geyerc2c4d722013-06-04 21:43:40 +0200447 if (register_types_)
448 {
449 add_delphi_uses_list("Thrift.TypeRegistry");
450 }
451
Jake Farrelld11c8bc2012-05-21 00:07:14 +0000452 init_known_types_list();
453
Jake Farrell7ae13e12011-10-18 14:35:26 +0000454 string unitname, nsname;
455 const vector<t_program*>& includes = program_->get_includes();
456 for (size_t i = 0; i < includes.size(); ++i) {
457 unitname = includes[i]->get_name();
458 nsname = includes[i]->get_namespace("delphi");
459 if ( "" != nsname) {
460 unitname = nsname;
461 }
462 add_delphi_uses_list(unitname);
463 }
464
465
466 MKDIR(get_out_dir().c_str());
467}
468
469void t_delphi_generator::close_generator() {
470 std::string unitname = program_name_;
471 if( "" != namespace_name_) {
472 unitname = namespace_name_;
473 }
474
475 for ( int i = 0; i < (int)unitname.size(); i++) {
476 if ( unitname[i] == ' ' ) {
477 unitname.replace( i, 1, "_" );
478 }
479 }
480
481 std::string f_name = get_out_dir() + "/" + unitname + ".pas";
482 std::ofstream f_all;
483
484 f_all.open( f_name.c_str() );
485
486 f_all << autogen_comment() << endl;
487 f_all << "unit " << unitname << ";" << endl << endl;
488 f_all << "interface" << endl << endl;
489 f_all << "uses" << endl;
490
491 indent_up();
492
493 vector<std::string>::const_iterator s_iter;
494 for (s_iter = uses_list.begin(); s_iter != uses_list.end(); ++s_iter) {
495 if (s_iter != uses_list.begin()) {
496 f_all << ",";
497 f_all << endl;
498 }
499 indent(f_all) << *s_iter;
500 }
501
502 f_all << ";" << endl << endl;
503
504 indent_down();
505
506 string tmp_unit( unitname );
507 for ( int i = 0; i < (int)tmp_unit.size(); i++) {
508 if ( tmp_unit[i] == '.' ) {
509 tmp_unit.replace( i, 1, "_" );
510 }
511 }
512
513 f_all << "const" << endl;
514 indent_up();
515 indent(f_all) << "c" << tmp_unit << "_Option_AnsiStr_Binary = " << ( ansistr_binary_ ? "True" : "False") << ";" << endl;
Jake Farrell7ae13e12011-10-18 14:35:26 +0000516 indent_down();
517
518 f_all << "type" << endl;
519 f_all << s_forward_decr.str();
520 if (has_enum) {
521 indent(f_all) << endl;
522 indent(f_all) << "{$SCOPEDENUMS ON}" << endl << endl;
523 f_all << s_enum.str();
524 indent(f_all) << "{$SCOPEDENUMS OFF}" << endl << endl;
525 }
526 f_all << s_struct.str();
527 f_all << s_service.str();
528 f_all << s_const.str();
529 f_all << "implementation" << endl << endl;
530 f_all << s_struct_impl.str();
531 f_all << s_service_impl.str();
532 f_all << s_const_impl.str();
Jens Geyerc2c4d722013-06-04 21:43:40 +0200533
534
535 if (register_types_)
536 {
537 f_all << endl;
538 f_all << "// Type factory methods and registration" << endl;
539 f_all << s_type_factory_funcs.str();
540 f_all << "procedure RegisterTypeFactories;" << endl;
541 f_all << "begin" << endl;
542 f_all << s_type_factory_registration.str();
543 f_all << "end;" << endl;
Jake Farrell7ae13e12011-10-18 14:35:26 +0000544 }
Jens Geyerc2c4d722013-06-04 21:43:40 +0200545 f_all << endl;
546
Jens Geyerec8744c2013-09-06 21:08:24 +0200547 string constants_class = make_constants_classname();
548
Jens Geyerc2c4d722013-06-04 21:43:40 +0200549 f_all << "initialization" << endl;
550 if ( has_const ) {
551 f_all << "{$IF CompilerVersion < 21.0}" << endl;
Jens Geyerec8744c2013-09-06 21:08:24 +0200552 f_all << " " << constants_class.c_str() << "_Initialize;" << endl;
Jens Geyerc2c4d722013-06-04 21:43:40 +0200553 f_all << "{$IFEND}" << endl;
554 }
555 if (register_types_) {
556 f_all << " RegisterTypeFactories;" << endl;
557 }
558 f_all << endl;
559
560 f_all << "finalization" << endl;
561 if ( has_const ) {
562 f_all << "{$IF CompilerVersion < 21.0}" << endl;
Jens Geyerec8744c2013-09-06 21:08:24 +0200563 f_all << " " << constants_class.c_str() << "_Finalize;" << endl;
Jens Geyerc2c4d722013-06-04 21:43:40 +0200564 f_all << "{$IFEND}" << endl;
565 }
566 f_all << endl << endl;
567
Jake Farrell7ae13e12011-10-18 14:35:26 +0000568 f_all << "end." << endl;
569 f_all.close();
Jake Farrelld11c8bc2012-05-21 00:07:14 +0000570
Jens Geyer45766042013-03-27 20:32:41 +0200571 if( ! typedefs_pending.empty()) {
Jens Geyer1bd94242013-04-19 20:15:05 +0200572 pwarning(0, "%d typedefs with unresolved type references left:\n", typedefs_pending.size());
Jens Geyer45766042013-03-27 20:32:41 +0200573 for( std::list<t_typedef*>::iterator iter = typedefs_pending.begin(); typedefs_pending.end() != iter; ++iter) {
Jens Geyer1bd94242013-04-19 20:15:05 +0200574 pwarning(0, "- %s\n", (*iter)->get_symbolic().c_str());
Jens Geyer45766042013-03-27 20:32:41 +0200575 }
576 }
Jake Farrell7ae13e12011-10-18 14:35:26 +0000577}
578
579void t_delphi_generator::delphi_type_usings( ostream& out) {
580 indent_up();
581 indent(out) << "Classes, SysUtils, Generics.Collections, Thrift.Collections, Thrift.Protocol," << endl;
582 indent(out) << "Thrift.Transport;" << endl << endl;
583 indent_down();
584}
585
586void t_delphi_generator::generate_typedef(t_typedef* ttypedef) {
Jake Farrelld11c8bc2012-05-21 00:07:14 +0000587 t_type* type = ttypedef->get_type();
588
589 // write now or save for later?
590 if( ! is_fully_defined_type( type)) {
Jens Geyer1bd94242013-04-19 20:15:05 +0200591 pverbose("typedef %s: unresolved dependencies found\n", type_name(ttypedef).c_str());
Jake Farrelld11c8bc2012-05-21 00:07:14 +0000592 typedefs_pending.push_back( ttypedef);
593 return;
594 }
595
596 indent_up();
597 indent(s_struct) <<
598 type_name(ttypedef) << " = ";
599
600 bool container = type->is_list() || type->is_map() || type->is_set();
601
602 // commented out: the benefit is not big enough to risk breaking existing code
603 //if( ! container)
604 // s_struct << "type "; //the "type A = type B" syntax leads to E2574 with generics
605
606 s_struct << type_name(ttypedef->get_type(), ! container) << ";" << endl <<
607 endl;
608 indent_down();
609
610 add_defined_type( ttypedef);
611}
612
613bool t_delphi_generator::is_fully_defined_type( t_type* ttype) {
Jens Geyer1bd94242013-04-19 20:15:05 +0200614 if( (NULL != ttype->get_program()) && (ttype->get_program() != program_)) {
615 t_scope* scope = ttype->get_program()->scope();
616 if( NULL != scope->get_type( ttype->get_name())) {
617 //printf("type %s found in included scope %s\n", ttype->get_name().c_str(), ttype->get_program()->get_name().c_str());
618 return true;
619 }
620 }
621
Jake Farrelld11c8bc2012-05-21 00:07:14 +0000622 if (ttype->is_typedef()) {
623 return (1 == types_known[ type_name(ttype)]);
624 }
625
626 if (ttype->is_base_type()) {
627 return (1 == types_known[ base_type_name((t_base_type*)ttype)]);
628 } else if (ttype->is_enum()) {
629 return true; // enums are written first, before all other types
630 } else if (ttype->is_map()) {
631 t_map *tmap = (t_map*) ttype;
632 return is_fully_defined_type( tmap->get_key_type()) &&
633 is_fully_defined_type( tmap->get_val_type());
634 } else if (ttype->is_set()) {
635 t_set* tset = (t_set*) ttype;
636 return is_fully_defined_type( tset->get_elem_type());
637 } else if (ttype->is_list()) {
638 t_list* tlist = (t_list*) ttype;
639 return is_fully_defined_type( tlist->get_elem_type());
640 }
641
642 return (1 == types_known[ type_name(ttype)]);
643}
644
645void t_delphi_generator::add_defined_type( t_type* ttype) {
646 // mark as known type
647 types_known[ type_name(ttype)] = 1;
648
649 // check all pending typedefs
650 std::list<t_typedef*>::iterator iter;
651 bool more = true;
652 while( more && (! typedefs_pending.empty()))
653 {
654 more = false;
655
656 for( iter = typedefs_pending.begin(); typedefs_pending.end() != iter; ++iter)
657 {
658 t_typedef* ttypedef = (*iter);
659 if( is_fully_defined_type( ttypedef->get_type()))
Jens Geyer1bd94242013-04-19 20:15:05 +0200660 {
661 pverbose("typedef %s: all pending references are now resolved\n", type_name(ttypedef).c_str());
Jake Farrelld11c8bc2012-05-21 00:07:14 +0000662 typedefs_pending.erase( iter);
663 generate_typedef( ttypedef);
664 more = true;
665 break;
666 }
667 }
668 }
669}
670
671void t_delphi_generator::init_known_types_list() {
672 // known base types
673 types_known[ type_name( g_type_string)] = 1;
674 types_known[ type_name( g_type_binary)] = 1;
675 types_known[ type_name( g_type_bool)] = 1;
676 types_known[ type_name( g_type_byte)] = 1;
677 types_known[ type_name( g_type_i16)] = 1;
678 types_known[ type_name( g_type_i32)] = 1;
679 types_known[ type_name( g_type_i64)] = 1;
680 types_known[ type_name( g_type_double)] = 1;
Jake Farrell7ae13e12011-10-18 14:35:26 +0000681}
682
683void t_delphi_generator::generate_enum(t_enum* tenum) {
684 has_enum = true;
685 indent_up();
686 indent(s_enum) <<
687 type_name(tenum,true,true) << " = " << "(" << endl;
688 indent_up();
689 vector<t_enum_value*> constants = tenum->get_constants();
690 vector<t_enum_value*>::iterator c_iter;
691 for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
692 int value = (*c_iter)->get_value();
693 if (c_iter != constants.begin()) {
694 s_enum << ",";
695 s_enum << endl;
696 }
697 indent(s_enum) << normalize_name((*c_iter)->get_name()) << " = " << value;
698 }
699 s_enum << endl;
700 indent_down();
701 indent(s_enum) << ");" << endl << endl;
702 indent_down();
703}
704
Jens Geyerec8744c2013-09-06 21:08:24 +0200705
706std::string t_delphi_generator::make_valid_delphi_identifier( std::string const & fromName) {
707 std::string str = fromName;
708 if( str.empty()) {
709 return str;
710 }
711
712 // tests rely on this
713 assert( ('A' < 'Z') && ('a' < 'z') && ('0' < '9'));
714
715 // if the first letter is a number, we add an additional underscore in front of it
716 char c = str.at(0);
717 if( ('0' <= c) && (c <= '9')) {
718 str = "_" + str;
719 }
720
721 // following chars: letter, number or underscore
722 for( size_t i = 0; i < str.size(); ++i) {
723 c = str.at(i);
724 if( (('A' > c) || (c > 'Z')) &&
725 (('a' > c) || (c > 'z')) &&
726 (('0' > c) || (c > '9')) &&
727 ('_' != c) ) {
728 str.replace( i, 1, "_");
729 }
730 }
731
732 return str;
733}
734
735
736std::string t_delphi_generator::make_constants_classname() {
737 if( constprefix_) {
738 return make_valid_delphi_identifier( "T" + program_name_ + "Constants");
739 } else {
740 return "TConstants"; // compatibility
741 }
742}
743
744
Jake Farrell7ae13e12011-10-18 14:35:26 +0000745void t_delphi_generator::generate_consts(std::vector<t_const*> consts) {
746 if (consts.empty()){
747 return;
748 }
749
750 has_const = true;
Jens Geyerec8744c2013-09-06 21:08:24 +0200751 string constants_class = make_constants_classname();
Jake Farrell7ae13e12011-10-18 14:35:26 +0000752
753 indent_up();
754 indent(s_const) <<
Jens Geyerec8744c2013-09-06 21:08:24 +0200755 constants_class.c_str() << " = class" << endl;
Jake Farrell7ae13e12011-10-18 14:35:26 +0000756 indent(s_const) << "private" << endl;
757 indent_up();
758 vector<t_const*>::iterator c_iter;
759 for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
760 print_private_field(s_const, normalize_name((*c_iter)->get_name()),
761 (*c_iter)->get_type(), (*c_iter)->get_value());
762 }
763 indent_down();
764 indent(s_const) << "public" << endl;
765 indent_up();
766 for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
767 print_const_prop(s_const, normalize_name((*c_iter)->get_name()),
768 (*c_iter)->get_type(), (*c_iter)->get_value());
769 }
770 indent(s_const) << "{$IF CompilerVersion >= 21.0}" << endl;
771 indent(s_const) << "class constructor Create;" << endl;
772 indent(s_const) << "class destructor Destroy;" << endl;
773 indent(s_const) << "{$IFEND}" << endl;
774 indent_down();
775 indent(s_const) << "end;" << endl << endl;
776 indent_down();
777
778 std::ostringstream vars, code;
779
780 indent_up_impl();
781 for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
782 initialize_field(vars, code, "F" + prop_name( (*c_iter)->get_name()),
783 (*c_iter)->get_type(), (*c_iter)->get_value());
784 }
785 indent_down_impl();
786
787 indent_impl(s_const_impl) << "{$IF CompilerVersion >= 21.0}" << endl;
Jens Geyerec8744c2013-09-06 21:08:24 +0200788 indent_impl(s_const_impl) << "class constructor " << constants_class.c_str() << ".Create;" << endl;
Jake Farrell7ae13e12011-10-18 14:35:26 +0000789
790 if ( ! vars.str().empty() ) {
791 indent_impl(s_const_impl) << "var" << endl;
792 s_const_impl << vars.str();
793 }
794 indent_impl(s_const_impl) << "begin" << endl;
795 if ( ! code.str().empty() ) {
796 s_const_impl << code.str();
797 }
798 indent_impl(s_const_impl) << "end;" << endl << endl;
Jens Geyerec8744c2013-09-06 21:08:24 +0200799 indent_impl(s_const_impl) << "class destructor " << constants_class.c_str() << ".Destroy;" << endl;
Jake Farrell7ae13e12011-10-18 14:35:26 +0000800 indent_impl(s_const_impl) << "begin" << endl;
801 indent_up_impl();
802 for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
803 finalize_field(s_const_impl, normalize_name( (*c_iter)->get_name()),
804 (*c_iter)->get_type(), (*c_iter)->get_value());
805 }
806 indent_impl(s_const_impl) << "inherited;" << endl;
807 indent_down_impl();
808 indent_impl(s_const_impl) << "end;" << endl;
809 indent_impl(s_const_impl) << "{$ELSE}" << endl;
810
811 vars.str("");
812 code.str("");
813
814 indent_up_impl();
815 for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
Jens Geyerec8744c2013-09-06 21:08:24 +0200816 initialize_field( vars, code, constants_class + ".F" + prop_name( (*c_iter)->get_name()),
Jake Farrell6fa2b302011-12-06 00:59:30 +0000817 (*c_iter)->get_type(), (*c_iter)->get_value());
Jake Farrell7ae13e12011-10-18 14:35:26 +0000818 }
819 indent_down_impl();
820
Jens Geyerec8744c2013-09-06 21:08:24 +0200821 indent_impl(s_const_impl) << "procedure " << constants_class.c_str() << "_Initialize;" << endl;
Jake Farrell7ae13e12011-10-18 14:35:26 +0000822 if ( ! vars.str().empty() ) {
823 indent_impl(s_const_impl) << "var" << endl;
824 s_const_impl << vars.str();
825 }
826 indent_impl(s_const_impl) << "begin" << endl;
827 if ( ! code.str().empty() ) {
828 s_const_impl << code.str();
829 }
830 indent_impl(s_const_impl) << "end;" << endl << endl;
831
Jens Geyerec8744c2013-09-06 21:08:24 +0200832 indent_impl(s_const_impl) << "procedure " << constants_class.c_str() << "_Finalize;" << endl;
Jake Farrell7ae13e12011-10-18 14:35:26 +0000833 indent_impl(s_const_impl) << "begin" << endl;
834 indent_up_impl();
835 for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
836 finalize_field(s_const_impl, normalize_name( (*c_iter)->get_name()),
Jens Geyerec8744c2013-09-06 21:08:24 +0200837 (*c_iter)->get_type(), (*c_iter)->get_value(), constants_class);
Jake Farrell7ae13e12011-10-18 14:35:26 +0000838 }
839 indent_down_impl();
840 indent_impl(s_const_impl) << "end;" << endl;
841 indent_impl(s_const_impl) << "{$IFEND}" << endl << endl;
842}
843
844void t_delphi_generator::print_const_def_value(std::ostream& vars, std::ostream& out, string name, t_type* type, t_const_value* value, string cls_nm)
845{
846
847 string cls_prefix;
848
849 if (cls_nm == "") {
850 cls_prefix = "";
851 } else {
852 cls_prefix = cls_nm + ".";
853 }
854
855 if (type->is_struct() || type->is_xception()) {
856 const vector<t_field*>& fields = ((t_struct*)type)->get_members();
857 vector<t_field*>::const_iterator f_iter;
858 const map<t_const_value*, t_const_value*>& val = value->get_map();
859 map<t_const_value*, t_const_value*>::const_iterator v_iter;
860 for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
861 t_type* field_type = NULL;
862 for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
863 if ((*f_iter)->get_name() == v_iter->first->get_string()) {
864 field_type = (*f_iter)->get_type();
865 }
866 }
867 if (field_type == NULL) {
868 throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string();
869 }
870 string val = render_const_value( vars, out, name, field_type, v_iter->second);
Jake Farrell343c61d2011-12-09 02:29:56 +0000871 indent_impl(out) << cls_prefix << normalize_name(name) << "." << prop_name( v_iter->first->get_string(), type->is_xception()) << " := " << val << ";" << endl;
Jake Farrell7ae13e12011-10-18 14:35:26 +0000872 }
873 } else if (type->is_map()) {
874 t_type* ktype = ((t_map*)type)->get_key_type();
875 t_type* vtype = ((t_map*)type)->get_val_type();
876 const map<t_const_value*, t_const_value*>& val = value->get_map();
877 map<t_const_value*, t_const_value*>::const_iterator v_iter;
878 for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
879 string key = render_const_value( vars, out, name, ktype, v_iter->first);
880 string val = render_const_value( vars, out, name, vtype, v_iter->second);
881 indent_impl(out) << cls_prefix << normalize_name(name) << "[" << key << "]" << " := " << val << ";" << endl;
882 }
883 } else if (type->is_list() || type->is_set()) {
884 t_type* etype;
885 if (type->is_list()) {
886 etype = ((t_list*)type)->get_elem_type();
887 } else {
888 etype = ((t_set*)type)->get_elem_type();
889 }
890
891 const vector<t_const_value*>& val = value->get_list();
892 vector<t_const_value*>::const_iterator v_iter;
893 for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
894 string val = render_const_value( vars, out, name, etype, *v_iter);
895 indent_impl(out) << cls_prefix << normalize_name(name) << ".Add(" << val << ");" << endl;
896 }
897 }
898}
899
900void t_delphi_generator::print_private_field(std::ostream& out, string name, t_type* type, t_const_value* value) {
Jake Farrell85147552011-10-20 13:30:08 +0000901 (void) value;
Jake Farrell7ae13e12011-10-18 14:35:26 +0000902 indent(out) << "class var F" << name << ": " << type_name(type) << ";" << endl;
903}
904
905void t_delphi_generator::print_const_prop(std::ostream& out, string name, t_type* type, t_const_value* value) {
Jake Farrell85147552011-10-20 13:30:08 +0000906 (void) value;
Jake Farrell7ae13e12011-10-18 14:35:26 +0000907 indent(out) << "class property " << name << ": " << type_name(type) << " read F" << name << ";" << endl;
908}
909
910void t_delphi_generator::print_const_value( std::ostream& vars, std::ostream& out, string name, t_type* type, t_const_value* value) {
911 t_type* truetype = type;
912 while (truetype->is_typedef()) {
913 truetype = ((t_typedef*)truetype)->get_type();
914 }
915
916 if (truetype->is_base_type()) {
917 string v2 = render_const_value( vars, out, name, type, value);
918 indent_impl(out) << name << " := " << v2 << ";" << endl;
919 } else if (truetype->is_enum()) {
Jens Geyer19251ad2013-03-10 22:51:14 +0200920 indent_impl(out) << name << " := " << type_name(type) << "." << value->get_identifier_name() << ";" << endl;
Jake Farrell7ae13e12011-10-18 14:35:26 +0000921 } else {
922 string typname;
Jens Geyerd21fa6e2013-09-06 21:05:20 +0200923 typname = type_name( truetype, true, false, type->is_xception(), type->is_xception());
Jake Farrell7ae13e12011-10-18 14:35:26 +0000924 indent_impl(out) << name << " := " << typname << ".Create;" << endl;
Jens Geyerd21fa6e2013-09-06 21:05:20 +0200925 print_const_def_value( vars, out, name, truetype, value);
Jake Farrell7ae13e12011-10-18 14:35:26 +0000926 }
Jake Farrell7ae13e12011-10-18 14:35:26 +0000927}
928
Jake Farrell6fa2b302011-12-06 00:59:30 +0000929void t_delphi_generator::initialize_field(std::ostream& vars, std::ostream& out, string name, t_type* type, t_const_value* value) {
Jake Farrell7ae13e12011-10-18 14:35:26 +0000930 print_const_value( vars, out, name, type, value );
931}
932
933void t_delphi_generator::finalize_field(std::ostream& out, string name, t_type* type, t_const_value* value , string cls_nm) {
Jake Farrell85147552011-10-20 13:30:08 +0000934 (void) out;
935 (void) name;
936 (void) type;
937 (void) value;
938 (void) cls_nm;
Jake Farrell7ae13e12011-10-18 14:35:26 +0000939}
940
941string t_delphi_generator::render_const_value(ostream& vars, ostream& out, string name, t_type* type, t_const_value* value) {
Jake Farrell85147552011-10-20 13:30:08 +0000942 (void) name;
Jake Farrell7ae13e12011-10-18 14:35:26 +0000943
944 t_type* truetype = type;
945 while (truetype->is_typedef()) {
946 truetype = ((t_typedef*)truetype)->get_type();
947 }
948
949 std::ostringstream render;
950
951 if (truetype->is_base_type()) {
952 t_base_type::t_base tbase = ((t_base_type*)truetype)->get_base();
953 switch (tbase) {
954 case t_base_type::TYPE_STRING:
955 render << "'" << get_escaped_string(value) << "'";
956 break;
957 case t_base_type::TYPE_BOOL:
958 render << ((value->get_integer() > 0) ? "True" : "False");
959 break;
960 case t_base_type::TYPE_BYTE:
Jake Farrelld2b3bb42011-10-26 02:29:48 +0000961 render << "ShortInt( " << value->get_integer() << ")";
Jake Farrell0c0f6512011-10-25 02:20:26 +0000962 break;
Jake Farrell7ae13e12011-10-18 14:35:26 +0000963 case t_base_type::TYPE_I16:
Jake Farrelld2b3bb42011-10-26 02:29:48 +0000964 render << "SmallInt( " << value->get_integer() << ")";
Jake Farrell0c0f6512011-10-25 02:20:26 +0000965 break;
Jake Farrell7ae13e12011-10-18 14:35:26 +0000966 case t_base_type::TYPE_I32:
Jake Farrelld2b3bb42011-10-26 02:29:48 +0000967 render << "LongInt( " << value->get_integer() << ")";
Jake Farrell0c0f6512011-10-25 02:20:26 +0000968 break;
Jake Farrell7ae13e12011-10-18 14:35:26 +0000969 case t_base_type::TYPE_I64:
Jake Farrelld2b3bb42011-10-26 02:29:48 +0000970 render << "Int64( " << value->get_integer() << ")";
Jake Farrell7ae13e12011-10-18 14:35:26 +0000971 break;
972 case t_base_type::TYPE_DOUBLE:
973 if (value->get_type() == t_const_value::CV_INTEGER) {
974 render << value->get_integer();
975 } else {
976 render << value->get_double();
977 }
978 break;
979 default:
980 render << "";
981 }
982 } else if (truetype->is_enum()) {
Jens Geyer19251ad2013-03-10 22:51:14 +0200983 render << type_name( type, false) << "." << value->get_identifier_name();
Jake Farrell7ae13e12011-10-18 14:35:26 +0000984 } else {
985 string t = tmp("tmp");
986 vars << " " << t << " : " << type_name(type) << ";" << endl;
987 print_const_value( vars, out, t, type, value);
988 render << t;
989 }
990
991 return render.str();
992}
993
994void t_delphi_generator::generate_struct(t_struct* tstruct) {
995 generate_delphi_struct(tstruct, false);
996}
997
998void t_delphi_generator::generate_xception(t_struct* txception) {
999 generate_delphi_struct(txception, true);
1000}
1001
1002void t_delphi_generator::generate_delphi_struct(t_struct* tstruct, bool is_exception) {
1003 indent_up();
1004 generate_delphi_struct_definition(s_struct, tstruct, is_exception);
1005 indent_down();
Jake Farrelld11c8bc2012-05-21 00:07:14 +00001006
1007 add_defined_type( tstruct);
Jake Farrell7ae13e12011-10-18 14:35:26 +00001008
1009 generate_delphi_struct_impl(s_struct_impl, "", tstruct, is_exception);
Jens Geyerc2c4d722013-06-04 21:43:40 +02001010 if (register_types_) {
1011 generate_delphi_struct_type_factory(s_type_factory_funcs, "", tstruct, is_exception);
1012 generate_delphi_struct_type_factory_registration(s_type_factory_registration, "", tstruct, is_exception);
1013 }
Jake Farrell7ae13e12011-10-18 14:35:26 +00001014}
1015
1016void t_delphi_generator::generate_delphi_struct_impl( ostream& out, string cls_prefix, t_struct* tstruct, bool is_exception, bool is_result, bool is_x_factory) {
1017
1018 if (is_exception && (! is_x_factory)) {
1019 generate_delphi_struct_impl( out, cls_prefix, tstruct, is_exception, is_result, true);
1020 }
1021
1022 string cls_nm;
1023
1024 string exception_factory_name;
1025
1026 if (is_exception) {
1027 exception_factory_name = normalize_clsnm( tstruct->get_name(), "", true ) + "Factory";
1028 }
1029
1030 if (is_exception) {
1031 cls_nm = type_name(tstruct,true,(! is_x_factory),is_x_factory,true);
1032 }
1033 else {
1034 cls_nm = type_name(tstruct,true,false);
1035 }
1036
1037 std::ostringstream vars, code;
1038
1039 const vector<t_field*>& members = tstruct->get_members();
1040 vector<t_field*>::const_iterator m_iter;
1041
1042 indent_up_impl();
1043 for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
1044 t_type* t = (*m_iter)->get_type();
1045 while (t->is_typedef()) {
1046 t = ((t_typedef*)t)->get_type();
1047 }
1048 if ((*m_iter)->get_value() != NULL) {
1049 initialize_field( vars, code, "F" + prop_name( (*m_iter)->get_name(), is_exception), t, (*m_iter)->get_value());
Jens Geyer0f8acc52013-04-24 21:53:39 +02001050 if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
1051 indent_impl(code) << "F__isset_" << prop_name((*m_iter), is_exception) << " := True;" << endl;
1052 }
Jake Farrell7ae13e12011-10-18 14:35:26 +00001053 }
1054 }
1055 indent_down_impl();
1056
Jake Farrell7ae13e12011-10-18 14:35:26 +00001057 indent_impl(out) << "constructor " << cls_prefix << cls_nm << "." << "Create;" << endl;
1058
1059 if ( ! vars.str().empty()) {
Jake Farrell343c61d2011-12-09 02:29:56 +00001060 out << "var" << endl;
Jake Farrell7ae13e12011-10-18 14:35:26 +00001061 out << vars.str();
1062 }
1063
1064 indent_impl(out) << "begin" << endl;
1065 indent_up_impl();
1066 if (is_exception && (! is_x_factory)) {
1067 indent_impl(out) << "inherited Create('');" << endl;
1068 indent_impl(out) << "F" << exception_factory_name << " := T" << exception_factory_name << "Impl.Create;" << endl;
1069 } else {
1070 indent_impl(out) << "inherited;" << endl;
1071 }
1072
1073 if ( ! code.str().empty()) {
1074 out << code.str();
1075 }
1076
1077 indent_down_impl();
1078 indent_impl(out) << "end;" << endl << endl;
1079
Jake Farrell343c61d2011-12-09 02:29:56 +00001080 if ((members.size() > 0) && is_exception && (!is_x_factory)) {
1081 indent_impl(out) << "constructor " << cls_prefix << cls_nm << "." << "Create(" << constructor_argument_list( tstruct, indent_impl()) << ");" << endl;
1082 indent_impl(out) << "begin" << endl;
1083 indent_up_impl();
1084 indent_impl(out) << "Create;" << endl;
1085 for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
1086 string propname = prop_name((*m_iter)->get_name(), is_exception);
1087 string param_name = constructor_param_name( (*m_iter)->get_name());
1088 indent_impl(out) << propname << " := " << param_name << ";" << endl;
1089 }
1090 indent_impl(out) << "UpdateMessageProperty;" << endl;
1091 indent_down_impl();
1092 indent_impl(out) << "end;" << endl << endl;
1093 }
1094
Jake Farrell7ae13e12011-10-18 14:35:26 +00001095 indent_impl(out) << "destructor " << cls_prefix << cls_nm << "." << "Destroy;" << endl;
1096 indent_impl(out) << "begin" << endl;
1097 indent_up_impl();
1098
1099 for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
1100 t_type* t = (*m_iter)->get_type();
1101 while (t->is_typedef()) {
1102 t = ((t_typedef*)t)->get_type();
1103 }
1104 finalize_field( out, prop_name(*m_iter, is_exception), t, (*m_iter)->get_value());
1105 }
1106
1107 indent_impl(out) << "inherited;" << endl;
1108 indent_down_impl();
1109 indent_impl(out) << "end;" << endl << endl;
1110
Jens Geyera58a9cb2012-12-17 23:24:13 +01001111 if ( tstruct->is_union() ) {
1112 indent_impl(out) << "procedure " << cls_prefix << cls_nm << "." << "ClearUnionValues;" << endl;
1113 indent_impl(out) << "begin" << endl;
1114 indent_up_impl();
1115 for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
1116 t_type* t = (*m_iter)->get_type();
1117 while (t->is_typedef()) {
1118 t = ((t_typedef*)t)->get_type();
1119 }
1120
1121 generate_delphi_clear_union_value( out, cls_prefix, cls_nm, t, *m_iter, "F", is_exception, tstruct->is_union(), is_x_factory, exception_factory_name);
1122 }
1123 indent_down_impl();
1124 indent_impl(out) << "end;" << endl << endl;
1125 }
1126
Jake Farrell7ae13e12011-10-18 14:35:26 +00001127 for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
1128 t_type* t = (*m_iter)->get_type();
1129 while (t->is_typedef()) {
1130 t = ((t_typedef*)t)->get_type();
1131 }
Jake Farrell85147552011-10-20 13:30:08 +00001132 generate_delphi_property_reader_impl( out, cls_prefix, cls_nm, t, *m_iter, "F", is_exception);
Jens Geyera58a9cb2012-12-17 23:24:13 +01001133 generate_delphi_property_writer_impl( out, cls_prefix, cls_nm, t, *m_iter, "F", is_exception, tstruct->is_union(), is_x_factory, exception_factory_name);
Jake Farrell17515db2012-03-08 04:05:58 +00001134 if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
1135 generate_delphi_isset_reader_impl( out, cls_prefix, cls_nm, t, *m_iter, "F", is_exception);
1136 }
Jake Farrell7ae13e12011-10-18 14:35:26 +00001137 }
1138
1139 if ((! is_exception) || is_x_factory) {
1140 generate_delphi_struct_reader_impl( out, cls_prefix, tstruct, is_exception);
1141 if ( is_result ) {
1142 generate_delphi_struct_result_writer_impl( out, cls_prefix, tstruct, is_exception);
1143 } else {
1144 generate_delphi_struct_writer_impl( out, cls_prefix, tstruct, is_exception);
1145 }
Jake Farrell7ae13e12011-10-18 14:35:26 +00001146 }
Jake Farrellac102562011-11-23 14:30:41 +00001147 generate_delphi_struct_tostring_impl( out, cls_prefix, tstruct, is_exception, is_x_factory);
Jake Farrell7ae13e12011-10-18 14:35:26 +00001148
1149 if (is_exception && is_x_factory) {
1150 generate_delphi_create_exception_impl( out, cls_prefix, tstruct, is_exception);
1151 }
1152}
1153
Jens Geyerc2c4d722013-06-04 21:43:40 +02001154void t_delphi_generator::print_delphi_struct_type_factory_func( ostream& out, t_struct* tstruct) {
1155 string struct_intf_name = type_name(tstruct);
1156 out << "Create_";
1157 out << struct_intf_name;
1158 out << "_Impl";
1159}
1160
1161
1162void t_delphi_generator::generate_delphi_struct_type_factory( ostream& out, string cls_prefix, t_struct* tstruct, bool is_exception, bool is_result, bool is_x_factory) {
1163
1164 if (is_exception)
1165 return;
1166 if (is_result)
1167 return;
1168 if (is_x_factory)
1169 return;
1170
1171 string struct_intf_name = type_name(tstruct);
1172 string cls_nm = type_name(tstruct,true,false);
1173
1174 out << "function ";
1175 print_delphi_struct_type_factory_func(out, tstruct);
1176 out << ": ";
1177 out << struct_intf_name;
1178 out << ";" << endl;
1179 out << "begin" << endl;
1180 indent_up();
1181 indent(out) << "Result := " << cls_nm << ".Create;" << endl;
1182 indent_down();
1183 out << "end;" << endl << endl;
1184}
1185
1186void t_delphi_generator::generate_delphi_struct_type_factory_registration( ostream& out, string cls_prefix, t_struct* tstruct, bool is_exception, bool is_result, bool is_x_factory) {
1187 if (is_exception)
1188 return;
1189 if (is_result)
1190 return;
1191 if (is_x_factory)
1192 return;
1193
1194 string struct_intf_name = type_name(tstruct);
1195
1196 indent(out) << " TypeRegistry.RegisterTypeFactory<" << struct_intf_name << ">(";
1197 print_delphi_struct_type_factory_func(out, tstruct);
1198 out << ");";
1199 out << endl;
1200}
1201
Jake Farrell7ae13e12011-10-18 14:35:26 +00001202void t_delphi_generator::generate_delphi_struct_definition(ostream &out, t_struct* tstruct, bool is_exception, bool in_class, bool is_result, bool is_x_factory) {
1203 bool is_final = (tstruct->annotations_.find("final") != tstruct->annotations_.end());
1204 string struct_intf_name;
1205 string struct_name;
1206 string isset_name;
1207 const vector<t_field*>& members = tstruct->get_members();
1208 vector<t_field*>::const_iterator m_iter;
1209
1210 string exception_factory_name = normalize_clsnm( tstruct->get_name(), "", true ) + "Factory";
1211
1212 if (is_exception) {
1213 struct_intf_name = type_name(tstruct,false,false,true);
1214 }
1215 else {
1216 struct_intf_name = type_name(tstruct);
1217 }
1218
1219
1220 if (is_exception) {
1221 struct_name = type_name(tstruct, true, (! is_x_factory), is_x_factory);
1222 }
1223 else {
1224 struct_name = type_name(tstruct,true);
1225 }
1226
1227 if ((! is_exception) || is_x_factory) {
1228
1229 indent(out) << struct_intf_name << " = interface(IBase)" << endl;
1230 indent_up();
1231
Jake Farrell7ae13e12011-10-18 14:35:26 +00001232 for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
Jake Farrell85147552011-10-20 13:30:08 +00001233 generate_delphi_property_reader_definition( out, *m_iter, is_exception);
1234 generate_delphi_property_writer_definition( out, *m_iter, is_exception);
Jake Farrell7ae13e12011-10-18 14:35:26 +00001235 }
1236
1237 if (is_x_factory) {
1238 out << endl;
1239 indent(out) << "// Create Exception Object" << endl;
1240 indent(out) << "function CreateException: " << type_name(tstruct,true,true) << ";" << endl;
1241 }
1242
1243 if (members.size() > 0) {
1244 out << endl;
1245 for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
1246 generate_property(out, *m_iter, true, is_exception);
1247 }
1248 }
1249
1250 if (members.size() > 0) {
1251 out << endl;
1252 for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
Jake Farrell17515db2012-03-08 04:05:58 +00001253 if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
1254 generate_delphi_isset_reader_definition( out, *m_iter, is_exception);
1255 }
Jake Farrell7ae13e12011-10-18 14:35:26 +00001256 }
1257 }
1258
1259 if (members.size() > 0) {
1260 out << endl;
1261 for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
Jake Farrell17515db2012-03-08 04:05:58 +00001262 if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
1263 isset_name = "__isset_" + prop_name(*m_iter, is_exception);
1264 indent(out) << "property " << isset_name << ": Boolean read Get" << isset_name << ";" << endl;
1265 }
Jake Farrell7ae13e12011-10-18 14:35:26 +00001266 }
1267 }
1268
1269 indent_down();
1270 indent(out) << "end;" << endl << endl;
1271 }
1272
1273 indent(out) << struct_name << " = ";
1274 if (is_final) {
1275 out << "sealed ";
1276 }
1277 out << "class(";
1278 if ( is_exception && (! is_x_factory)) {
Jake Farrell73a921f2011-10-31 14:07:14 +00001279 out << "TException";
Jake Farrell7ae13e12011-10-18 14:35:26 +00001280 } else {
1281 out << "TInterfacedObject, IBase, " << struct_intf_name;
1282 }
1283 out << ")" << endl;
1284
1285 if (is_exception && (! is_x_factory)) {
1286 indent(out) << "public" << endl;
1287 indent_up();
1288 indent(out) << "type" << endl;
1289 indent_up();
1290 generate_delphi_struct_definition( out, tstruct, is_exception, in_class, is_result, true);
1291 indent_down();
1292 indent_down();
1293 }
1294
1295 indent(out) << "private" << endl;
1296 indent_up();
1297
1298 if (is_exception && (! is_x_factory)) {
1299 indent(out) << "F" << exception_factory_name << " :" << struct_intf_name << ";" << endl << endl;
1300 }
1301
1302 for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
Jake Farrell85147552011-10-20 13:30:08 +00001303 indent(out) << declare_field(*m_iter, false, "F", is_exception) << endl;
Jake Farrell7ae13e12011-10-18 14:35:26 +00001304 }
1305
1306 if (members.size() > 0) {
1307 indent(out) << endl;
1308 for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
Jake Farrell17515db2012-03-08 04:05:58 +00001309 if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
1310 isset_name = "F__isset_" + prop_name(*m_iter, is_exception);
1311 indent(out) << isset_name << ": Boolean;" << endl;
1312 }
Jake Farrell7ae13e12011-10-18 14:35:26 +00001313 }
1314 }
1315
1316 indent(out) << endl;
1317
1318 for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
Jake Farrell85147552011-10-20 13:30:08 +00001319 generate_delphi_property_reader_definition( out, *m_iter, is_exception);
1320 generate_delphi_property_writer_definition( out, *m_iter, is_exception);
Jake Farrell7ae13e12011-10-18 14:35:26 +00001321 }
1322
Jens Geyera58a9cb2012-12-17 23:24:13 +01001323 if (tstruct->is_union()) {
1324 out << endl;
1325 indent(out) << "// Clear values(for union's property setter)" << endl;
1326 indent(out) << "procedure ClearUnionValues;" << endl;
1327 }
1328
Jake Farrell7ae13e12011-10-18 14:35:26 +00001329 if (members.size() > 0) {
1330 out << endl;
1331 for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
Jake Farrell17515db2012-03-08 04:05:58 +00001332 if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
1333 isset_name = "__isset_" + prop_name(*m_iter, is_exception);
1334 indent(out) << "function Get" << isset_name << ": Boolean;" << endl;
1335 }
Jake Farrell7ae13e12011-10-18 14:35:26 +00001336 }
1337 }
1338
1339 indent_down();
1340
1341 indent(out) << "public" << endl;
1342 indent_up();
1343
Jake Farrell343c61d2011-12-09 02:29:56 +00001344 if ((members.size() > 0) && is_exception && (! is_x_factory)) {
1345 indent(out) << "constructor Create; overload;" << endl;
1346 indent(out) << "constructor Create(" << constructor_argument_list( tstruct, indent()) << "); overload;" << endl;
1347 } else {
1348 indent(out) << "constructor Create;" << endl;
1349 }
1350
Jake Farrell7ae13e12011-10-18 14:35:26 +00001351 indent(out) << "destructor Destroy; override;" << endl;
1352
Jake Farrellac102562011-11-23 14:30:41 +00001353 out << endl;
1354 indent(out) << "function ToString: string; override;" << endl;
Jake Farrell7ae13e12011-10-18 14:35:26 +00001355
1356 if (is_exception && (! is_x_factory)) {
1357 out << endl;
1358 indent(out) << "// Exception Factory" << endl;
1359 indent(out) << "property " << exception_factory_name << ": " << struct_intf_name << " read F" << exception_factory_name << " write F" << exception_factory_name << ";" << endl;
1360 }
1361
1362 if ((! is_exception) || is_x_factory) {
1363 out << endl;
1364 indent(out) << "// IBase" << endl;
Roger Meier333bbf32012-01-08 21:51:08 +00001365 indent(out) << "procedure Read( const iprot: IProtocol);" << endl;
1366 indent(out) << "procedure Write( const oprot: IProtocol);" << endl;
Jake Farrell7ae13e12011-10-18 14:35:26 +00001367 }
1368
1369 if (is_exception && is_x_factory) {
1370 out << endl;
1371 indent(out) << "// Create Exception Object" << endl;
1372 indent(out) << "function CreateException: " << type_name(tstruct,true,true) << ";" << endl;
1373 }
1374
1375 if (members.size() > 0) {
1376 out << endl;
1377 indent(out) << "// Properties" << endl;
1378 for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
1379 generate_property(out, *m_iter, true, is_exception);
1380 }
1381 }
1382
1383 if (members.size() > 0) {
1384 out << endl;
1385 indent(out) << "// isset" << endl;
1386 for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
Jake Farrell17515db2012-03-08 04:05:58 +00001387 if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
1388 isset_name = "__isset_" + prop_name(*m_iter, is_exception);
1389 indent(out) << "property " << isset_name << ": Boolean read Get" << isset_name << ";" << endl;
1390 }
Jake Farrell7ae13e12011-10-18 14:35:26 +00001391 }
1392 }
1393
1394 indent_down();
Jake Farrell343c61d2011-12-09 02:29:56 +00001395 indent(out) << "end;" << endl << endl;
Jake Farrell7ae13e12011-10-18 14:35:26 +00001396}
1397
1398void t_delphi_generator::generate_service(t_service* tservice) {
1399 indent_up();
1400 indent(s_service) << normalize_clsnm(service_name_, "T") << " = class" << endl;
1401 indent(s_service) << "public" << endl;
1402 indent_up();
1403 indent(s_service) << "type" << endl;
1404 generate_service_interface(tservice);
1405 generate_service_client(tservice);
1406 generate_service_server(tservice);
1407 generate_service_helpers(tservice);
1408 indent_down();
1409 indent_down();
1410 indent(s_service) << "end;" << endl;
1411 indent(s_service) << endl;
1412 indent_down();
1413}
1414
1415void t_delphi_generator::generate_service_interface(t_service* tservice) {
1416 string extends = "";
1417 string extends_iface = "";
1418
1419 indent_up();
1420
1421 if (tservice->get_extends() != NULL) {
1422 extends = type_name(tservice->get_extends(), true, true);
1423 extends_iface = extends + ".Iface";
1424 indent(s_service) <<
1425 "Iface = interface(" << extends_iface << ")" << endl;
1426 } else {
1427 indent(s_service) <<
1428 "Iface = interface" << endl;
1429 }
1430
1431 indent_up();
Jake Farrell7ae13e12011-10-18 14:35:26 +00001432 vector<t_function*> functions = tservice->get_functions();
1433 vector<t_function*>::iterator f_iter;
1434 for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter)
1435 {
1436 indent(s_service) <<
1437 function_signature(*f_iter) << endl;
1438 }
1439 indent_down();
1440 indent(s_service) << "end;" << endl << endl;
1441
1442 indent_down();
1443}
1444
1445void t_delphi_generator::generate_service_helpers(t_service* tservice) {
1446 vector<t_function*> functions = tservice->get_functions();
1447 vector<t_function*>::iterator f_iter;
1448
1449 for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
1450 t_struct* ts = (*f_iter)->get_arglist();
1451 generate_delphi_struct_definition(s_service, ts, false, true);
1452 generate_delphi_struct_impl(s_service_impl, normalize_clsnm( service_name_, "T") + ".", ts, false);
1453 generate_function_helpers(*f_iter);
1454 }
1455}
1456
1457void t_delphi_generator::generate_service_client(t_service* tservice) {
1458 indent_up();
1459 string extends = "";
1460 string extends_client = "";
1461 if (tservice->get_extends() != NULL) {
1462 extends = type_name(tservice->get_extends());
1463 extends_client = extends + ".Client, ";
1464 }
1465
1466 if (tservice->get_extends() != NULL) {
1467 extends = type_name(tservice->get_extends(), true, true);
1468 extends_client = extends + ".TClient";
1469 indent(s_service) <<
1470 "TClient = class(" << extends_client << ", Iface)" << endl;
1471 } else {
1472 indent(s_service) <<
1473 "TClient = class( TInterfacedObject, Iface)" << endl;
1474 }
1475
1476 indent(s_service) << "public" << endl;
1477 indent_up();
1478
1479 indent(s_service) << "constructor Create( prot: IProtocol); overload;" << endl;
1480
1481 indent_impl(s_service_impl) << "constructor " << normalize_clsnm( service_name_, "T") << ".TClient.Create( prot: IProtocol);" << endl;
1482 indent_impl(s_service_impl) << "begin" << endl;
1483 indent_up_impl();
1484 indent_impl(s_service_impl) << "Create( prot, prot );" << endl;
1485 indent_down_impl();
1486 indent_impl(s_service_impl) << "end;" << endl << endl;
1487
Roger Meier333bbf32012-01-08 21:51:08 +00001488 indent(s_service) << "constructor Create( const iprot: IProtocol; const oprot: IProtocol); overload;" << endl;
Jake Farrell7ae13e12011-10-18 14:35:26 +00001489
Roger Meier333bbf32012-01-08 21:51:08 +00001490 indent_impl(s_service_impl) <<
1491 "constructor " << normalize_clsnm( service_name_, "T") <<
1492 ".TClient.Create( const iprot: IProtocol; const oprot: IProtocol);" << endl;
Jake Farrell7ae13e12011-10-18 14:35:26 +00001493 indent_impl(s_service_impl) << "begin" << endl;
1494 indent_up_impl();
Jens Geyer718f6ee2013-09-06 21:02:34 +02001495 indent_impl(s_service_impl) << "inherited Create;" << endl;
Jake Farrell7ae13e12011-10-18 14:35:26 +00001496 indent_impl(s_service_impl) << "iprot_ := iprot;" << endl;
1497 indent_impl(s_service_impl) << "oprot_ := oprot;" << endl;
1498 indent_down_impl();
1499 indent_impl(s_service_impl) << "end;" << endl << endl;
1500
1501 indent_down();
1502
1503 if (extends.empty()) {
1504 indent(s_service) << "protected" << endl;
1505 indent_up();
1506 indent(s_service) << "iprot_: IProtocol;" << endl;
1507 indent(s_service) << "oprot_: IProtocol;" << endl;
1508 indent(s_service) << "seqid_: Integer;" << endl;
1509 indent_down();
1510
1511 indent(s_service) << "public" << endl;
1512 indent_up();
1513 indent(s_service) << "property InputProtocol: IProtocol read iprot_;" << endl;
1514 indent(s_service) << "property OutputProtocol: IProtocol read oprot_;" << endl;
1515 indent_down();
1516 }
1517
1518 vector<t_function*> functions = tservice->get_functions();
1519 vector<t_function*>::const_iterator f_iter;
1520
1521 indent(s_service) << "protected" << endl;
1522 indent_up();
1523 indent(s_service) << "// Iface" << endl;
1524 for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
1525 string funname = (*f_iter)->get_name();
1526 indent(s_service) << function_signature(*f_iter) << endl;
1527 }
1528 indent_down();
1529
1530 indent(s_service) << "public" << endl;
1531 indent_up();
1532
1533 string full_cls = normalize_clsnm(service_name_,"T") + ".TClient";
1534
1535 for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
1536 string funname = (*f_iter)->get_name();
1537
1538 indent_impl(s_service_impl) << function_signature(*f_iter, full_cls) << endl;
1539 indent_impl(s_service_impl) << "begin" << endl;
1540 indent_up_impl();
1541 indent_impl(s_service_impl) << "send_" << funname << "(";
1542
1543 t_struct* arg_struct = (*f_iter)->get_arglist();
1544
1545 const vector<t_field*>& fields = arg_struct->get_members();
1546 vector<t_field*>::const_iterator fld_iter;
1547 bool first = true;
1548 for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
1549 if (first) {
1550 first = false;
1551 } else {
1552 s_service_impl << ", ";
1553 }
1554 s_service_impl << normalize_name( (*fld_iter)->get_name());
1555 }
1556 s_service_impl << ");" << endl;
1557
1558 if (!(*f_iter)->is_oneway()) {
1559 s_service_impl << indent_impl();
1560 if (!(*f_iter)->get_returntype()->is_void()) {
1561 s_service_impl << "Result := ";
1562 }
1563 s_service_impl <<
1564 "recv_" << funname << "();" << endl;
1565 }
1566
1567 indent_down_impl();
1568 indent_impl(s_service_impl) << "end;" << endl << endl;
1569
1570 t_function send_function(g_type_void,
1571 string("send_") + (*f_iter)->get_name(),
1572 (*f_iter)->get_arglist());
1573
1574 string argsname = (*f_iter)->get_name() + "_args";
1575 string args_clsnm = normalize_clsnm( argsname, "T");
1576 string args_intfnm= normalize_clsnm( argsname, "I");
1577
1578 indent(s_service) << function_signature(&send_function) << endl;
1579 indent_impl(s_service_impl) << function_signature(&send_function, full_cls) << endl;
1580 indent_impl(s_service_impl) << "var" << endl;
1581 indent_up_impl();
1582 indent_impl(s_service_impl) << "args : " << args_intfnm << ";" << endl;
1583 indent_impl(s_service_impl) << "msg : IMessage;" << endl;
1584 indent_down_impl();
1585 indent_impl(s_service_impl) << "begin" << endl;
1586 indent_up_impl();
1587
1588 indent_impl(s_service_impl) <<
1589 "seqid_ := seqid_ + 1;" << endl;
1590 indent_impl(s_service_impl) <<
1591 "msg := TMessageImpl.Create('" << funname << "', TMessageType.Call, seqid_);" << endl;
1592
1593 indent_impl(s_service_impl) <<
1594 "oprot_.WriteMessageBegin( msg );" << endl;
1595 indent_impl(s_service_impl) <<
1596 "args := " << args_clsnm << "Impl.Create();" << endl;
1597
1598 for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
1599 indent_impl(s_service_impl) <<
1600 "args." << prop_name(*fld_iter) << " := " << normalize_name( (*fld_iter)->get_name()) << ";" << endl;
1601 }
1602 indent_impl(s_service_impl) << "args.Write(oprot_);" << endl;
1603 for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
1604 indent_impl(s_service_impl) <<
1605 "args." << prop_name(*fld_iter) << " := " << empty_value((*fld_iter)->get_type()) << ";" << endl;
1606 }
1607
1608 indent_impl(s_service_impl) << "oprot_.WriteMessageEnd();" << endl;
1609 indent_impl(s_service_impl) << "oprot_.Transport.Flush();" << endl;
1610
1611 indent_down_impl();
1612 indent_impl(s_service_impl) << "end;" << endl << endl;
1613
1614 if (!(*f_iter)->is_oneway()) {
1615 string org_resultname = (*f_iter)->get_name() + "_result" ;
1616 string result_clsnm = normalize_clsnm( org_resultname, "T");
1617 string result_intfnm = normalize_clsnm( org_resultname, "I");
1618
1619 t_struct noargs(program_);
1620 t_function recv_function((*f_iter)->get_returntype(),
1621 string("recv_") + (*f_iter)->get_name(),
1622 &noargs,
1623 (*f_iter)->get_xceptions());
1624
1625 t_struct *xs = (*f_iter)->get_xceptions();
1626 const std::vector<t_field*>& xceptions = xs->get_members();
1627
1628 indent(s_service) << function_signature(&recv_function) << endl;
1629 indent_impl(s_service_impl) << function_signature(&recv_function, full_cls) << endl;
1630 indent_impl(s_service_impl) << "var" << endl;
1631 indent_up_impl();
1632 indent_impl(s_service_impl) << "msg : IMessage;" << endl;
1633 if ( xceptions.size() > 0) {
1634 indent_impl(s_service_impl) << "ex : Exception;" << endl;
1635 }
1636 indent_impl(s_service_impl) << "x : TApplicationException;" << endl;
1637 indent_impl(s_service_impl) << "ret : " << result_intfnm << ";" << endl;
1638
1639 indent_down_impl();
1640 indent_impl(s_service_impl) << "begin" << endl;
1641 indent_up_impl();
1642 indent_impl(s_service_impl) << "msg := iprot_.ReadMessageBegin();" << endl;
1643 indent_impl(s_service_impl) << "if (msg.Type_ = TMessageType.Exception) then" << endl;
1644 indent_impl(s_service_impl) << "begin" << endl;
1645 indent_up_impl();
1646 indent_impl(s_service_impl) << "x := TApplicationException.Read(iprot_);" << endl;
1647 indent_impl(s_service_impl) << "iprot_.ReadMessageEnd();" << endl;
1648 indent_impl(s_service_impl) << "raise x;" << endl;
1649 indent_down_impl();
1650 indent_impl(s_service_impl) << "end;" << endl;
1651
1652 indent_impl(s_service_impl) << "ret := " << result_clsnm << "Impl.Create();" << endl;
1653 indent_impl(s_service_impl) << "ret.Read(iprot_);" << endl;
1654 indent_impl(s_service_impl) << "iprot_.ReadMessageEnd();" << endl;
1655
1656 if (!(*f_iter)->get_returntype()->is_void()) {
1657 indent_impl(s_service_impl) << "if (ret.__isset_success) then" << endl;
1658 indent_impl(s_service_impl) << "begin" << endl;
1659 indent_up_impl();
1660 indent_impl(s_service_impl) << "Result := ret.Success;" << endl;
1661 t_type *type = (*f_iter)->get_returntype();
1662 if (type->is_struct() || type->is_xception() || type->is_map() || type->is_list() || type->is_set()) {
1663 indent_impl(s_service_impl) << "ret.Success := nil;" << endl;
1664 }
1665 indent_impl(s_service_impl) << "Exit;" << endl;
1666 indent_down_impl();
1667 indent_impl(s_service_impl) << "end;" << endl;
1668 }
1669
1670 vector<t_field*>::const_iterator x_iter;
1671 for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
1672 indent_impl(s_service_impl) << "if (ret.__isset_" << prop_name(*x_iter) << ") then" << endl;
1673 indent_impl(s_service_impl) << "begin" << endl;
1674 indent_up_impl();
1675 indent_impl(s_service_impl) << "ex := ret." << prop_name(*x_iter) << ".CreateException;" << endl;
1676 indent_impl(s_service_impl) << "raise ex;" << endl;
1677 indent_down_impl();
1678 indent_impl(s_service_impl) << "end;" << endl;
1679 }
1680
1681 if (!(*f_iter)->get_returntype()->is_void()) {
1682 indent_impl(s_service_impl) <<
1683 "raise TApplicationException.Create(TApplicationException.TExceptionType.MissingResult, '" << (*f_iter)->get_name() << " failed: unknown result');" << endl;
1684 }
1685
1686 indent_down_impl();
1687 indent_impl(s_service_impl) << "end;" << endl << endl;
1688 }
1689 }
1690
1691 indent_down();
1692 indent(s_service) << "end;" << endl << endl;
1693}
1694
1695void t_delphi_generator::generate_service_server(t_service* tservice) {
1696 vector<t_function*> functions = tservice->get_functions();
1697 vector<t_function*>::iterator f_iter;
1698
1699 string extends = "";
1700 string extends_processor = "";
1701
1702 string full_cls = normalize_clsnm( service_name_, "T") + ".TProcessorImpl";
1703
1704 if (tservice->get_extends() != NULL) {
1705 extends = type_name(tservice->get_extends(), true, true);
1706 extends_processor = extends + ".TProcessorImpl";
1707 indent(s_service) <<
1708 "TProcessorImpl = class(" << extends_processor << ", IProcessor)" << endl;
1709 } else {
1710 indent(s_service) <<
1711 "TProcessorImpl = class( TInterfacedObject, IProcessor)" << endl;
1712 }
1713
1714 indent(s_service) << "public" << endl;
1715 indent_up();
1716 indent(s_service) << "constructor Create( iface_: Iface );" << endl;
1717 indent(s_service) << "destructor Destroy; override;" << endl;
1718 indent_down();
1719
1720 indent_impl(s_service_impl) << "constructor " << full_cls << ".Create( iface_: Iface );" << endl;
1721 indent_impl(s_service_impl) << "begin" << endl;
1722 indent_up_impl();
Roger Meier380e9192012-04-09 16:25:47 +00001723 if (tservice->get_extends() != NULL)
1724 {
1725 indent_impl(s_service_impl) << "inherited Create( iface_);" << endl;
1726 } else {
1727 indent_impl(s_service_impl) << "inherited Create;" << endl;
1728 }
Jake Farrell7ae13e12011-10-18 14:35:26 +00001729 indent_impl(s_service_impl) << "Self.iface_ := iface_;" << endl;
Roger Meier380e9192012-04-09 16:25:47 +00001730 if (tservice->get_extends() != NULL)
1731 {
1732 indent_impl(s_service_impl) << "ASSERT( processMap_ <> nil); // inherited" << endl;
1733 } else {
1734 indent_impl(s_service_impl) << "processMap_ := TThriftDictionaryImpl<string, TProcessFunction>.Create;" << endl;
1735 }
Jake Farrell7ae13e12011-10-18 14:35:26 +00001736
1737 for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
1738 indent_impl(s_service_impl) <<
1739 "processMap_.AddOrSetValue( '" << (*f_iter)->get_name() << "', " << (*f_iter)->get_name() << "_Process);" << endl;
1740 }
1741 indent_down_impl();
1742 indent_impl(s_service_impl) << "end;" << endl << endl;
1743
1744 indent_impl(s_service_impl) << "destructor " << full_cls << ".Destroy;" << endl;
Roger Meier380e9192012-04-09 16:25:47 +00001745 indent_impl(s_service_impl) << "begin" << endl;
Jake Farrell7ae13e12011-10-18 14:35:26 +00001746 indent_up_impl();
1747 indent_impl(s_service_impl) << "inherited;" << endl;
1748 indent_down_impl();
1749 indent_impl(s_service_impl) << "end;" << endl << endl;
1750
Jake Farrell7ae13e12011-10-18 14:35:26 +00001751 indent(s_service) << "private" << endl;
1752 indent_up();
1753 indent(s_service) << "iface_: Iface;" << endl;
1754 indent_down();
Roger Meier380e9192012-04-09 16:25:47 +00001755
1756 if (tservice->get_extends() == NULL)
1757 {
1758 indent(s_service) << "protected" << endl;
1759 indent_up();
1760 indent(s_service) << "type" << endl;
1761 indent_up();
1762 indent(s_service) << "TProcessFunction = reference to procedure( seqid: Integer; const iprot: IProtocol; const oprot: IProtocol);" << endl;
1763 indent_down();
1764 indent_down();
1765 indent(s_service) << "protected" << endl;
1766 indent_up();
1767 indent(s_service) << "processMap_: IThriftDictionary<string, TProcessFunction>;" << endl;
1768 indent_down();
1769 }
1770
Jake Farrell7ae13e12011-10-18 14:35:26 +00001771 indent(s_service) << "public" << endl;
1772 indent_up();
1773 if (extends.empty()) {
Roger Meier333bbf32012-01-08 21:51:08 +00001774 indent(s_service) << "function Process( const iprot: IProtocol; const oprot: IProtocol): Boolean;" << endl;
Jake Farrell7ae13e12011-10-18 14:35:26 +00001775 } else {
Roger Meier333bbf32012-01-08 21:51:08 +00001776 indent(s_service) << "function Process( const iprot: IProtocol; const oprot: IProtocol): Boolean; reintroduce;" << endl;
Jake Farrell7ae13e12011-10-18 14:35:26 +00001777 }
1778
Roger Meier333bbf32012-01-08 21:51:08 +00001779 indent_impl(s_service_impl) << "function " << full_cls << ".Process( const iprot: IProtocol; const oprot: IProtocol): Boolean;" << endl;;
Jake Farrell7ae13e12011-10-18 14:35:26 +00001780 indent_impl(s_service_impl) << "var" << endl;
1781 indent_up_impl();
1782 indent_impl(s_service_impl) << "msg : IMessage;" << endl;
1783 indent_impl(s_service_impl) << "fn : TProcessFunction;" << endl;
1784 indent_impl(s_service_impl) << "x : TApplicationException;" << endl;
1785 indent_down_impl();
1786 indent_impl(s_service_impl) << "begin" << endl;
1787 indent_up_impl();
1788 indent_impl(s_service_impl) << "try" << endl;
1789 indent_up_impl();
1790 indent_impl(s_service_impl) << "msg := iprot.ReadMessageBegin();" << endl;
1791 indent_impl(s_service_impl) << "fn := nil;" << endl;
Roger Meier380e9192012-04-09 16:25:47 +00001792 indent_impl(s_service_impl) << "if not processMap_.TryGetValue(msg.Name, fn)" << endl;
1793 indent_impl(s_service_impl) << "or not Assigned(fn) then" << endl;
Jake Farrell7ae13e12011-10-18 14:35:26 +00001794 indent_impl(s_service_impl) << "begin" << endl;
1795 indent_up_impl();
1796 indent_impl(s_service_impl) << "TProtocolUtil.Skip(iprot, TType.Struct);" << endl;
1797 indent_impl(s_service_impl) << "iprot.ReadMessageEnd();" << endl;
1798 indent_impl(s_service_impl) << "x := TApplicationException.Create(TApplicationException.TExceptionType.UnknownMethod, 'Invalid method name: ''' + msg.Name + '''');" << endl;
Roger Meierfebe8452012-06-06 10:32:24 +00001799 indent_impl(s_service_impl) << "msg := TMessageImpl.Create(msg.Name, TMessageType.Exception, msg.SeqID);" << endl;
1800 indent_impl(s_service_impl) << "oprot.WriteMessageBegin( msg);" << endl;
Jake Farrell7ae13e12011-10-18 14:35:26 +00001801 indent_impl(s_service_impl) << "x.Write(oprot);" << endl;
1802 indent_impl(s_service_impl) << "oprot.WriteMessageEnd();" << endl;
1803 indent_impl(s_service_impl) << "oprot.Transport.Flush();" << endl;
1804 indent_impl(s_service_impl) << "Result := True;" << endl;
1805 indent_impl(s_service_impl) << "Exit;" << endl;
1806 indent_down_impl();
1807 indent_impl(s_service_impl) << "end;" << endl;
1808 indent_impl(s_service_impl) << "fn(msg.SeqID, iprot, oprot);" << endl;
1809 indent_down_impl();
1810 indent_impl(s_service_impl) << "except" << endl;
1811 indent_up_impl();
1812 indent_impl(s_service_impl) << "Result := False;" << endl;
1813 indent_impl(s_service_impl) << "Exit;" << endl;
1814 indent_down_impl();
1815 indent_impl(s_service_impl) << "end;" << endl;
1816 indent_impl(s_service_impl) << "Result := True;" << endl;
1817 indent_down_impl();
1818 indent_impl(s_service_impl) << "end;" << endl << endl;
1819
1820 for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter)
1821 {
1822 generate_process_function(tservice, *f_iter);
1823 }
1824
1825 indent_down();
1826 indent(s_service) << "end;" << endl << endl;
1827
1828}
1829
1830void t_delphi_generator::generate_function_helpers(t_function* tfunction) {
1831 if (tfunction->is_oneway()) {
1832 return;
1833 }
1834
1835 t_struct result(program_, tfunction->get_name() + "_result");
1836 t_field success(tfunction->get_returntype(), "Success", 0);
1837 if (!tfunction->get_returntype()->is_void()) {
1838 result.append(&success);
1839 }
1840
1841 t_struct *xs = tfunction->get_xceptions();
1842 const vector<t_field*>& fields = xs->get_members();
1843 vector<t_field*>::const_iterator f_iter;
1844 for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
1845 result.append(*f_iter);
1846 }
1847
1848 generate_delphi_struct_definition(s_service, &result, false, true, true);
1849 generate_delphi_struct_impl(s_service_impl, normalize_clsnm( service_name_, "T") + ".", &result, false);
1850}
1851
1852void t_delphi_generator::generate_process_function(t_service* tservice, t_function* tfunction) {
1853 (void) tservice;
1854 string funcname = tfunction->get_name();
1855 string full_cls = normalize_clsnm( service_name_, "T") + ".TProcessorImpl";
1856
1857 string org_argsname = funcname + "_args";
1858 string args_clsnm = normalize_clsnm(org_argsname, "T");
1859 string args_intfnm = normalize_clsnm(org_argsname, "I");
1860
1861 string org_resultname = funcname + "_result";
1862 string result_clsnm = normalize_clsnm(org_resultname, "T");
1863 string result_intfnm = normalize_clsnm(org_resultname, "I");
1864
1865 indent(s_service) <<
Roger Meier333bbf32012-01-08 21:51:08 +00001866 "procedure " << funcname << "_Process( seqid: Integer; const iprot: IProtocol; const oprot: IProtocol);" << endl;
Jake Farrell7ae13e12011-10-18 14:35:26 +00001867
1868 if (tfunction->is_oneway()) {
1869 indent_impl(s_service_impl) << "// one way processor" << endl;
1870 } else {
1871 indent_impl(s_service_impl) << "// both way processor" << endl;
1872 }
1873
1874 indent_impl(s_service_impl) <<
Roger Meier333bbf32012-01-08 21:51:08 +00001875 "procedure " << full_cls << "." << funcname << "_Process( seqid: Integer; const iprot: IProtocol; const oprot: IProtocol);" << endl;
Jake Farrell7ae13e12011-10-18 14:35:26 +00001876 indent_impl(s_service_impl) << "var" << endl;
1877 indent_up_impl();
1878 indent_impl(s_service_impl) << "args: " << args_intfnm << ";" << endl;
1879 if (!tfunction->is_oneway()) {
Roger Meierfebe8452012-06-06 10:32:24 +00001880 indent_impl(s_service_impl) << "msg: IMessage;" << endl;
Jake Farrell7ae13e12011-10-18 14:35:26 +00001881 indent_impl(s_service_impl) << "ret: " << result_intfnm << ";" << endl;
1882 }
1883
1884 indent_down_impl();
1885 indent_impl(s_service_impl) << "begin" << endl;
1886 indent_up_impl();
1887 indent_impl(s_service_impl) << "args := " << args_clsnm << "Impl.Create;" << endl;
1888 indent_impl(s_service_impl) << "args.Read(iprot);" << endl;
1889 indent_impl(s_service_impl) << "iprot.ReadMessageEnd();" << endl;
1890
1891 t_struct* xs = tfunction->get_xceptions();
1892 const std::vector<t_field*>& xceptions = xs->get_members();
1893 vector<t_field*>::const_iterator x_iter;
1894
1895 if (!tfunction->is_oneway()) {
1896 indent_impl(s_service_impl) << "ret := " << result_clsnm << "Impl.Create;" << endl;
1897 }
1898
1899 if (!tfunction->is_oneway() && xceptions.size() > 0) {
1900 indent_impl(s_service_impl) << "try" << endl;
1901 indent_up_impl();
1902 }
1903
1904 t_struct* arg_struct = tfunction->get_arglist();
1905 const std::vector<t_field*>& fields = arg_struct->get_members();
1906 vector<t_field*>::const_iterator f_iter;
1907
1908 s_service_impl << indent_impl();
1909 if (!tfunction->is_oneway() && !tfunction->get_returntype()->is_void()) {
1910 s_service_impl << "ret.Success := ";
1911 }
1912 s_service_impl << "iface_." << normalize_name( tfunction->get_name(), true) << "(";
1913 bool first = true;
1914 for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
1915 if (first) {
1916 first = false;
1917 } else {
1918 s_service_impl << ", ";
1919 }
1920 s_service_impl << "args." << prop_name(*f_iter);
1921 }
1922 s_service_impl << ");" << endl;
1923
1924 for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
1925 indent_impl(s_service_impl) <<
1926 "args." << prop_name(*f_iter) << " := " << empty_value((*f_iter)->get_type()) << ";" << endl;
1927 }
1928
1929 if (!tfunction->is_oneway() && xceptions.size() > 0) {
1930 indent_down_impl();
1931 indent_impl(s_service_impl) << "except" << endl;
1932 indent_up_impl();
1933 for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
1934 indent_impl(s_service_impl) << "on E: " << type_name((*x_iter)->get_type(),true,true) << " do" << endl;
1935 indent_impl(s_service_impl) << "begin" << endl;
1936 indent_up_impl();
1937 if (!tfunction->is_oneway()) {
1938 string factory_name = normalize_clsnm((*x_iter)->get_type()->get_name(),"",true) + "Factory";
1939 indent_impl(s_service_impl) <<
1940 "ret." << prop_name(*x_iter) << " := E." << factory_name << ";" << endl;
1941 }
1942 indent_down_impl();
1943 indent_impl(s_service_impl) << "end;" << endl;
1944 }
1945 indent_down_impl();
1946 indent_impl(s_service_impl) << "end;" << endl;
1947 }
1948
1949 if (! tfunction->is_oneway()) {
Roger Meierfebe8452012-06-06 10:32:24 +00001950 indent_impl(s_service_impl) << "msg := TMessageImpl.Create('" << tfunction->get_name() << "', TMessageType.Reply, seqid); " << endl;
1951 indent_impl(s_service_impl) << "oprot.WriteMessageBegin( msg); " << endl;
Jake Farrell7ae13e12011-10-18 14:35:26 +00001952 indent_impl(s_service_impl) << "ret.Write(oprot);" << endl;
1953 indent_impl(s_service_impl) << "oprot.WriteMessageEnd();" << endl;
1954 indent_impl(s_service_impl) << "oprot.Transport.Flush();" << endl;
1955 }
1956
1957 indent_down_impl();
1958 indent_impl(s_service_impl) << "end;" << endl << endl;
1959}
1960
1961void t_delphi_generator::generate_deserialize_field(ostream& out, bool is_xception, t_field* tfield, string prefix, ostream& local_vars) {
1962 t_type* type = tfield->get_type();
1963 while(type->is_typedef()) {
1964 type = ((t_typedef*)type)->get_type();
1965 }
1966
1967 if (type->is_void()) {
1968 throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name();
1969 }
1970
1971 string name = prefix + prop_name(tfield,is_xception);
1972
1973 if (type->is_struct() || type->is_xception()) {
1974 generate_deserialize_struct(out, (t_struct*)type, name, "");
1975 } else if (type->is_container()) {
1976 generate_deserialize_container(out, is_xception, type, name, local_vars);
1977 } else if (type->is_base_type() || type->is_enum()) {
1978 indent_impl(out) <<
1979 name << " := ";
1980
1981 if (type->is_enum())
1982 {
1983 out << type_name(type, false) << "(";
1984 }
1985
1986 out << "iprot.";
1987
1988 if (type->is_base_type()) {
1989 t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
1990 switch (tbase) {
1991 case t_base_type::TYPE_VOID:
1992 throw "compiler error: cannot serialize void field in a struct: " + name;
1993 break;
1994 case t_base_type::TYPE_STRING:
1995 if (((t_base_type*)type)->is_binary()) {
1996 if (ansistr_binary_) {
1997 out << "ReadAnsiString();";
1998 } else {
1999 out << "ReadBinary();";
2000 }
2001 } else {
2002 out << "ReadString();";
2003 }
2004 break;
2005 case t_base_type::TYPE_BOOL:
2006 out << "ReadBool();";
2007 break;
2008 case t_base_type::TYPE_BYTE:
2009 out << "ReadByte();";
2010 break;
2011 case t_base_type::TYPE_I16:
2012 out << "ReadI16();";
2013 break;
2014 case t_base_type::TYPE_I32:
2015 out << "ReadI32();";
2016 break;
2017 case t_base_type::TYPE_I64:
2018 out << "ReadI64();";
2019 break;
2020 case t_base_type::TYPE_DOUBLE:
2021 out << "ReadDouble();";
2022 break;
2023 default:
2024 throw "compiler error: no C# name for base type " + tbase;
2025 }
2026 } else if (type->is_enum()) {
2027 out << "ReadI32()";
2028 out << ");";
2029 }
2030 out << endl;
2031 } else {
2032 printf("DO NOT KNOW HOW TO DESERIALIZE FIELD '%s' TYPE '%s'\n", tfield->get_name().c_str(), type_name(type).c_str());
2033 }
2034}
2035
2036void t_delphi_generator::generate_deserialize_struct(ostream& out, t_struct* tstruct, string name, string prefix) {
2037 string typ_name;
2038
2039 if (tstruct->is_xception()) {
2040 typ_name = type_name(tstruct,true,false,true,true);
2041 } else {
2042 typ_name = type_name(tstruct,true,false);
2043 }
2044
2045 indent_impl(out) << prefix << name << " := " << typ_name << ".Create;" << endl;
2046 indent_impl(out) << prefix << name << ".Read(iprot);" << endl;
2047}
2048
2049void t_delphi_generator::generate_deserialize_container(ostream& out, bool is_xception, t_type* ttype, string name, std::ostream& local_vars) {
2050
2051 string obj;
2052 string counter;
2053 string local_var;
2054
2055 if (ttype->is_map()) {
2056 obj = tmp("_map");
2057 } else if (ttype->is_set()) {
2058 obj = tmp("_set");
2059 } else if (ttype->is_list()) {
2060 obj = tmp("_list");
2061 }
2062
2063 if (ttype->is_map()) {
2064 local_var = obj + ": IMap;";
2065 } else if (ttype->is_set()) {
2066 local_var = obj + ": ISet;";
2067 } else if (ttype->is_list()) {
2068 local_var = obj + ": IList;";
2069 }
2070 local_vars << " " << local_var << endl;
2071 counter = tmp("_i");
2072 local_var = counter + ": Integer;";
2073 local_vars << " " << local_var << endl;
2074
2075 indent_impl(out) << name << " := " << type_name(ttype, true) << ".Create;" << endl;
2076
2077 if (ttype->is_map()) {
2078 indent_impl(out) << obj << " := iprot.ReadMapBegin();" << endl;
2079 } else if (ttype->is_set()) {
2080 indent_impl(out) << obj << " := iprot.ReadSetBegin();" << endl;
2081 } else if (ttype->is_list()) {
2082 indent_impl(out) << obj << " := iprot.ReadListBegin();" << endl;
2083 }
2084
2085 indent_impl(out) <<
2086 "for " << counter << " := 0 to " << obj << ".Count - 1 do" << endl;
2087 indent_impl(out) << "begin" << endl;
2088 indent_up_impl();
2089 if (ttype->is_map()) {
2090 generate_deserialize_map_element(out, is_xception, (t_map*)ttype, name, local_vars);
2091 } else if (ttype->is_set()) {
2092 generate_deserialize_set_element(out, is_xception, (t_set*)ttype, name, local_vars);
2093 } else if (ttype->is_list()) {
2094 generate_deserialize_list_element(out, is_xception, (t_list*)ttype, name, local_vars);
2095 }
2096 indent_down_impl();
2097 indent_impl(out) << "end;" << endl;
Jake Farrell601bb5e2011-10-31 14:13:13 +00002098
2099 if (ttype->is_map()) {
2100 indent_impl(out) << "iprot.ReadMapEnd();" << endl;
2101 } else if (ttype->is_set()) {
2102 indent_impl(out) << "iprot.ReadSetEnd();" << endl;
2103 } else if (ttype->is_list()) {
2104 indent_impl(out) << "iprot.ReadListEnd();" << endl;
2105 }
Jake Farrell7ae13e12011-10-18 14:35:26 +00002106}
2107
2108void t_delphi_generator::generate_deserialize_map_element(ostream& out, bool is_xception, t_map* tmap, string prefix, ostream& local_vars) {
2109
2110 string key = tmp("_key");
2111 string val = tmp("_val");
2112 string local_var;
2113
2114 t_field fkey(tmap->get_key_type(), key);
2115 t_field fval(tmap->get_val_type(), val);
2116
2117 local_vars << " " << declare_field(&fkey) << endl;
2118 local_vars << " " << declare_field(&fval) << endl;
2119
2120 generate_deserialize_field(out, is_xception, &fkey, "", local_vars);
2121 generate_deserialize_field(out, is_xception, &fval, "", local_vars);
2122
2123 indent_impl(out) <<
2124 prefix << ".AddOrSetValue( " << key << ", " << val << ");" << endl;
2125
2126}
2127
2128void t_delphi_generator::generate_deserialize_set_element(ostream& out, bool is_xception, t_set* tset, string prefix, ostream& local_vars) {
2129 string elem = tmp("_elem");
2130 t_field felem(tset->get_elem_type(), elem);
Jake Farrell85147552011-10-20 13:30:08 +00002131 local_vars << " " << declare_field(&felem) << endl;
Jake Farrell7ae13e12011-10-18 14:35:26 +00002132 generate_deserialize_field(out, is_xception, &felem, "", local_vars);
2133 indent_impl(out) <<
2134 prefix << ".Add(" << elem << ");" << endl;
2135}
2136
2137void t_delphi_generator::generate_deserialize_list_element(ostream& out, bool is_xception, t_list* tlist, string prefix, ostream& local_vars) {
2138 string elem = tmp("_elem");
2139 t_field felem(tlist->get_elem_type(), elem);
Jake Farrell85147552011-10-20 13:30:08 +00002140 local_vars << " " << declare_field(&felem) << endl;
Jake Farrell7ae13e12011-10-18 14:35:26 +00002141 generate_deserialize_field(out, is_xception, &felem, "", local_vars);
2142 indent_impl(out) <<
2143 prefix << ".Add(" << elem << ");" << endl;
2144}
2145
2146void t_delphi_generator::generate_serialize_field(ostream& out, bool is_xception, t_field* tfield, string prefix, ostream& local_vars) {
Jake Farrell85147552011-10-20 13:30:08 +00002147 (void) local_vars;
2148
Jake Farrell7ae13e12011-10-18 14:35:26 +00002149 t_type* type = tfield->get_type();
2150 while (type->is_typedef()) {
2151 type = ((t_typedef*)type)->get_type();
2152 }
2153
2154 string name = prefix + prop_name(tfield, is_xception);
2155
2156 if (type->is_void()) {
2157 throw "CANNOT GENERATE SERIALIZE CODE FOR void TYPE: " + name;
2158 }
2159
2160 if (type->is_struct() || type->is_xception()) {
2161 generate_serialize_struct(out, (t_struct*)type, name, local_vars);
2162 } else if (type->is_container()) {
2163 generate_serialize_container(out, is_xception, type, name, local_vars);
2164 } else if (type->is_base_type() || type->is_enum()) {
2165
2166 indent_impl(out) <<
2167 "oprot.";
2168
2169 if (type->is_base_type()) {
2170 t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
2171
2172 switch(tbase) {
2173 case t_base_type::TYPE_VOID:
2174 throw "compiler error: cannot serialize void field in a struct: " + name;
2175 break;
2176 case t_base_type::TYPE_STRING:
2177 if (((t_base_type*)type)->is_binary()) {
2178 if (ansistr_binary_) {
2179 out << "WriteAnsiString(";
2180 } else {
2181 out << "WriteBinary(";
2182 }
2183 } else {
2184 out << "WriteString(";
2185 }
2186 out << name << ");";
2187 break;
2188 case t_base_type::TYPE_BOOL:
2189 out << "WriteBool(" << name << ");";
2190 break;
2191 case t_base_type::TYPE_BYTE:
2192 out << "WriteByte(" << name << ");";
2193 break;
2194 case t_base_type::TYPE_I16:
2195 out << "WriteI16(" << name << ");";
2196 break;
2197 case t_base_type::TYPE_I32:
2198 out << "WriteI32(" << name << ");";
2199 break;
2200 case t_base_type::TYPE_I64:
2201 out << "WriteI64(" << name << ");";
2202 break;
2203 case t_base_type::TYPE_DOUBLE:
2204 out << "WriteDouble(" << name << ");";
2205 break;
2206 default:
2207 throw "compiler error: no Delphi name for base type " + tbase;
2208 }
2209 } else if (type->is_enum()) {
2210 out << "WriteI32(Integer(" << name << "));";
2211 }
2212 out << endl;
2213 } else {
2214 printf("DO NOT KNOW HOW TO SERIALIZE '%s%s' TYPE '%s'\n",
2215 prefix.c_str(),
2216 tfield->get_name().c_str(),
2217 type_name(type).c_str());
2218 }
2219}
2220
2221void t_delphi_generator::generate_serialize_struct(ostream& out, t_struct* tstruct, string prefix, ostream& local_vars) {
Jake Farrell85147552011-10-20 13:30:08 +00002222 (void) local_vars;
Jake Farrell7ae13e12011-10-18 14:35:26 +00002223 (void) tstruct;
2224 out <<
2225 indent_impl() << prefix << ".Write(oprot);" << endl;
2226}
2227
2228void t_delphi_generator::generate_serialize_container(ostream& out, bool is_xception, t_type* ttype, string prefix, ostream& local_vars) {
2229 string obj;
2230 if (ttype->is_map()) {
2231 obj = tmp("map");
2232 local_vars << " " << obj << " : IMap;" << endl;
2233 indent_impl(out) << obj << " := TMapImpl.Create( " <<
2234 type_to_enum(((t_map*)ttype)->get_key_type()) << ", " <<
2235 type_to_enum(((t_map*)ttype)->get_val_type()) << ", " <<
2236 prefix << ".Count);" << endl;
2237 indent_impl(out) << "oprot.WriteMapBegin( " << obj << ");" << endl;
2238 } else if (ttype->is_set()) {
2239 obj = tmp("set_");
2240 local_vars << " " << obj << " : ISet;" << endl;
2241 indent_impl(out) << obj << " := TSetImpl.Create(" <<
2242 type_to_enum(((t_set*)ttype)->get_elem_type()) << ", " <<
2243 prefix << ".Count);" << endl;
2244 indent_impl(out) <<
2245 "oprot.WriteSetBegin( " << obj << ");" << endl;
2246 } else if (ttype->is_list()) {
2247 obj = tmp("list_");
2248 local_vars << " " << obj << " : IList;" << endl;
2249 indent_impl(out) << obj << " := TListImpl.Create(" <<
2250 type_to_enum(((t_list*)ttype)->get_elem_type()) << ", " <<
2251 prefix << ".Count);" << endl;
2252 indent_impl(out) <<
2253 "oprot.WriteListBegin( " << obj << ");" << endl;
2254 }
2255
2256 string iter = tmp("_iter");
2257 if (ttype->is_map()) {
2258 local_vars << " " << iter << ": " << type_name(((t_map*)ttype)->get_key_type()) << ";" << endl;
2259 indent_impl(out) << "for " << iter << " in " << prefix << ".Keys do" << endl;
2260 indent_impl(out) << "begin" << endl;
2261 indent_up_impl();
2262 } else if (ttype->is_set()) {
2263 local_vars << " " << iter << ": " << type_name(((t_set*)ttype)->get_elem_type()) << ";" << endl;
2264 indent_impl(out) << "for " << iter << " in " << prefix << " do" << endl;
2265 indent_impl(out) << "begin" << endl;
2266 indent_up_impl();
2267 } else if (ttype->is_list()) {
2268 local_vars << " " << iter << ": " << type_name(((t_list*)ttype)->get_elem_type()) << ";" << endl;
2269 indent_impl(out) << "for " << iter << " in " << prefix << " do" << endl;
2270 indent_impl(out) << "begin" << endl;
2271 indent_up_impl();
2272 }
2273
2274 if (ttype->is_map()) {
2275 generate_serialize_map_element(out, is_xception, (t_map*)ttype, iter, prefix, local_vars);
2276 } else if (ttype->is_set()) {
2277 generate_serialize_set_element(out, is_xception, (t_set*)ttype, iter, local_vars);
2278 } else if (ttype->is_list()) {
2279 generate_serialize_list_element(out, is_xception, (t_list*)ttype, iter, local_vars);
2280 }
2281
Jake Farrellf55f33b2011-10-26 02:40:14 +00002282 indent_down_impl();
2283 indent_impl(out) << "end;" << endl;
2284
Jake Farrell7ae13e12011-10-18 14:35:26 +00002285 if (ttype->is_map()) {
2286 indent_impl(out) << "oprot.WriteMapEnd();" << endl;
2287 } else if (ttype->is_set()) {
2288 indent_impl(out) << "oprot.WriteSetEnd();" << endl;
2289 } else if (ttype->is_list()) {
2290 indent_impl(out) << "oprot.WriteListEnd();" << endl;
2291 }
Jake Farrell7ae13e12011-10-18 14:35:26 +00002292}
2293
2294void t_delphi_generator::generate_serialize_map_element(ostream& out, bool is_xception, t_map* tmap, string iter, string map, ostream& local_vars) {
2295 t_field kfield(tmap->get_key_type(), iter);
2296 generate_serialize_field(out, is_xception, &kfield, "", local_vars);
2297 t_field vfield(tmap->get_val_type(), map + "[" + iter + "]");
2298 generate_serialize_field(out, is_xception, &vfield, "", local_vars);
2299}
2300
2301void t_delphi_generator::generate_serialize_set_element(ostream& out, bool is_xception, t_set* tset, string iter, ostream& local_vars) {
2302 t_field efield(tset->get_elem_type(), iter);
2303 generate_serialize_field(out, is_xception, &efield, "", local_vars);
2304}
2305
2306void t_delphi_generator::generate_serialize_list_element(ostream& out, bool is_xception, t_list* tlist, string iter, ostream& local_vars) {
2307 t_field efield(tlist->get_elem_type(), iter);
2308 generate_serialize_field(out, is_xception, &efield, "", local_vars);
2309}
2310
2311void t_delphi_generator::generate_property(ostream& out, t_field* tfield, bool isPublic, bool is_xception) {
2312 generate_delphi_property(out, is_xception, tfield, isPublic, "Get");
2313}
2314
2315void t_delphi_generator::generate_delphi_property(ostream& out, bool struct_is_xception, t_field* tfield, bool isPublic, std::string fieldPrefix) {
Jake Farrell85147552011-10-20 13:30:08 +00002316 (void) isPublic;
2317
Jake Farrell7ae13e12011-10-18 14:35:26 +00002318 t_type* ftype = tfield->get_type();
2319 bool is_xception = ftype->is_xception();
Jake Farrell85147552011-10-20 13:30:08 +00002320 indent(out) << "property " << prop_name(tfield, struct_is_xception) << ": " << type_name(ftype, false, true, is_xception, true) << " read " << fieldPrefix + prop_name(tfield, struct_is_xception)
2321 << " write Set" << prop_name(tfield, struct_is_xception) << ";" << endl;
Jake Farrell7ae13e12011-10-18 14:35:26 +00002322}
2323
2324std::string t_delphi_generator::prop_name(t_field* tfield, bool is_xception) {
2325 return prop_name(tfield->get_name(), is_xception);
2326}
2327
2328std::string t_delphi_generator::prop_name(string name, bool is_xception) {
2329 string ret = name;
2330 ret[0] = toupper(ret[0]);
2331 return normalize_name( ret, true, is_xception);
2332}
2333
Jake Farrell343c61d2011-12-09 02:29:56 +00002334std::string t_delphi_generator::constructor_param_name(string name) {
2335 string ret = name;
2336 ret[0] = toupper(ret[0]);
2337 ret = "A" + ret;
2338 return normalize_name( ret, false, false);
2339}
2340
Jake Farrell7ae13e12011-10-18 14:35:26 +00002341string t_delphi_generator::normalize_clsnm(string clsnm, string prefix, bool b_no_check_keyword) {
Jake Farrell85147552011-10-20 13:30:08 +00002342 if (clsnm.size() > 0) {
Jake Farrell7ae13e12011-10-18 14:35:26 +00002343 clsnm[0] = toupper(clsnm[0]);
2344 }
2345 if (b_no_check_keyword) {
2346 return prefix + clsnm;
2347 } else {
2348 return normalize_name( prefix + clsnm);
2349 }
2350}
2351
2352string t_delphi_generator::type_name( t_type* ttype, bool b_cls, bool b_no_postfix, bool b_exception_factory, bool b_full_exception_factory) {
Jake Farrelld11c8bc2012-05-21 00:07:14 +00002353
2354 if (ttype->is_typedef()) {
2355 return normalize_name( "T"+((t_typedef*)ttype)->get_symbolic());
Jake Farrell7ae13e12011-10-18 14:35:26 +00002356 }
Jake Farrelld11c8bc2012-05-21 00:07:14 +00002357
Jake Farrell7ae13e12011-10-18 14:35:26 +00002358 string typ_nm;
2359
2360 string s_factory;
2361
2362 if (ttype->is_base_type()) {
2363 return base_type_name((t_base_type*)ttype);
2364 } else if (ttype->is_enum()) {
2365 b_cls = true;
2366 b_no_postfix = true;
2367 } else if (ttype->is_map()) {
2368 t_map *tmap = (t_map*) ttype;
2369 if (b_cls) {
2370 typ_nm = "TThriftDictionaryImpl";
2371 } else {
2372 typ_nm = "IThriftDictionary";
2373 }
2374 return typ_nm + "<" + type_name(tmap->get_key_type()) +
2375 ", " + type_name(tmap->get_val_type()) + ">";
2376 } else if (ttype->is_set()) {
2377 t_set* tset = (t_set*) ttype;
2378 if (b_cls) {
2379 typ_nm = "THashSetImpl";
2380 } else {
2381 typ_nm = "IHashSet";
2382 }
2383 return typ_nm + "<" + type_name(tset->get_elem_type()) + ">";
2384 } else if (ttype->is_list()) {
2385 t_list* tlist = (t_list*) ttype;
2386 if (b_cls) {
2387 typ_nm = "TThriftListImpl";
2388 } else {
2389 typ_nm = "IThriftList";
2390 }
2391 return typ_nm + "<" + type_name(tlist->get_elem_type()) + ">";
2392 }
2393
2394 string type_prefix;
2395
2396 if (b_cls) {
2397 type_prefix = "T";
2398 } else {
2399 type_prefix = "I";
2400 }
2401
2402 string nm = normalize_clsnm( ttype->get_name(), type_prefix);
2403
2404 if (b_exception_factory) {
2405 nm = nm + "Factory";
2406 }
2407
2408 if (b_cls) {
2409 if (! b_no_postfix) {
2410 nm = nm + "Impl";
2411 }
2412 }
2413
2414 if ( b_exception_factory && b_full_exception_factory) {
2415 return type_name( ttype, true, true, false, false ) + "." + nm;
2416 }
2417
2418 return nm;
2419}
2420
Roger Meier333bbf32012-01-08 21:51:08 +00002421// returns "const " for some argument types
2422string t_delphi_generator::input_arg_prefix( t_type* ttype) {
2423
2424 // base types
2425 if (ttype->is_base_type()) {
2426 switch (((t_base_type*)ttype)->get_base()) {
2427
2428 // these should be const'ed for optimal performamce
2429 case t_base_type::TYPE_STRING: // refcounted pointer
2430 case t_base_type::TYPE_I64: // larger than 32 bit
2431 case t_base_type::TYPE_DOUBLE: // larger than 32 bit
2432 return "const ";
2433
2434 // all others don't need to be
2435 case t_base_type::TYPE_BYTE:
2436 case t_base_type::TYPE_I16:
2437 case t_base_type::TYPE_I32:
2438 case t_base_type::TYPE_BOOL:
2439 case t_base_type::TYPE_VOID:
2440 return "";
2441
2442 // we better always report any unknown types
2443 default:
2444 throw "compiler error: no input_arg_prefix() for base type " + (((t_base_type*)ttype)->get_base());
2445 }
2446
2447 // enums
2448 } else if (ttype->is_enum()) {
2449 return ""; // usually <= 32 bit
2450
2451 // containers
2452 } else if (ttype->is_map()) {
2453 return "const "; // refcounted pointer
2454
2455 } else if (ttype->is_set()) {
2456 return "const "; // refcounted pointer
2457
2458 } else if (ttype->is_list()) {
2459 return "const "; // refcounted pointer
2460
2461 }
2462
2463 // any other type, either TSomething or ISomething
2464 return "const "; // possibly refcounted pointer
2465}
2466
Jake Farrell7ae13e12011-10-18 14:35:26 +00002467string t_delphi_generator::base_type_name(t_base_type* tbase) {
2468 switch (tbase->get_base()) {
2469 case t_base_type::TYPE_VOID:
2470 // no "void" in Delphi language
2471 return "";
2472 case t_base_type::TYPE_STRING:
2473 if (tbase->is_binary()) {
2474 if ( ansistr_binary_) {
2475 return "AnsiString";
2476 } else {
2477 return "TBytes";
2478 }
2479 } else {
2480 return "string";
2481 }
2482 case t_base_type::TYPE_BOOL:
2483 return "Boolean";
2484 case t_base_type::TYPE_BYTE:
2485 return "ShortInt";
2486 case t_base_type::TYPE_I16:
2487 return "SmallInt";
2488 case t_base_type::TYPE_I32:
2489 return "Integer";
2490 case t_base_type::TYPE_I64:
2491 return "Int64";
2492 case t_base_type::TYPE_DOUBLE:
2493 return "Double";
2494 default:
2495 throw "compiler error: no Delphi name for base type " + tbase->get_base();
2496 }
2497}
2498
Jake Farrell85147552011-10-20 13:30:08 +00002499string t_delphi_generator::declare_field(t_field* tfield, bool init, std::string prefix, bool is_xception_class) {
2500 (void) init;
2501
Jake Farrell7ae13e12011-10-18 14:35:26 +00002502 t_type * ftype = tfield->get_type();
2503 bool is_xception = ftype->is_xception();
2504
Jake Farrell85147552011-10-20 13:30:08 +00002505 string result = prefix + prop_name(tfield, is_xception_class) + ": " + type_name(ftype,false,true,is_xception,true) + ";";
Jake Farrell7ae13e12011-10-18 14:35:26 +00002506 return result;
2507}
2508
2509string t_delphi_generator::function_signature(t_function* tfunction, std::string full_cls, bool is_xception) {
2510 t_type* ttype = tfunction->get_returntype();
2511 string prefix;
2512 if (full_cls == "") {
2513 prefix = "";
2514 } else {
2515 prefix = full_cls + ".";
2516 }
2517 if (is_void(ttype)) {
2518 return "procedure " + prefix + normalize_name(tfunction->get_name(), true, is_xception) + "(" + argument_list(tfunction->get_arglist()) + ");";
2519 } else {
2520 return "function " + prefix + normalize_name(tfunction->get_name(), true, is_xception) + "(" + argument_list(tfunction->get_arglist()) + "): " + type_name(ttype, false, true, is_xception, true) + ";";
2521 }
2522}
2523
2524string t_delphi_generator::argument_list(t_struct* tstruct) {
2525 string result = "";
2526 const vector<t_field*>& fields = tstruct->get_members();
2527 vector<t_field*>::const_iterator f_iter;
2528 bool first = true;
2529 t_type* tt;
2530
2531 for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
2532 if (first) {
2533 first = false;
2534 } else {
2535 result += "; ";
2536 }
2537
2538 tt = (*f_iter)->get_type();
Roger Meier333bbf32012-01-08 21:51:08 +00002539 result += input_arg_prefix(tt); // const?
2540 result += normalize_name((*f_iter)->get_name()) + ": " + type_name( tt, false, true, tt->is_xception(), true);
Jake Farrell7ae13e12011-10-18 14:35:26 +00002541 }
2542 return result;
2543}
2544
Jake Farrell343c61d2011-12-09 02:29:56 +00002545string t_delphi_generator::constructor_argument_list(t_struct* tstruct, string current_indent) {
2546 ostringstream result;
2547 const vector<t_field*>& fields = tstruct->get_members();
2548 vector<t_field*>::const_iterator f_iter;
2549 bool first = true;
2550 t_type* tt;
2551 string line = "";
2552 string newline_indent = current_indent + " ";
2553
2554 bool firstline = true;
2555
2556 for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
2557 if (first) {
2558 first = false;
2559 } else {
2560 line += ";";
2561 }
2562
2563 if (line.size() > 80) {
2564 if ( firstline ) {
2565 result << endl << newline_indent;
2566 firstline = false;
2567 }
2568 result << line << endl;
2569 line = newline_indent;
2570 } else if ( line.size() > 0) {
2571 line += " ";
2572 }
2573
2574 tt = (*f_iter)->get_type();
Roger Meier333bbf32012-01-08 21:51:08 +00002575 line += input_arg_prefix(tt); // const?
Jake Farrell343c61d2011-12-09 02:29:56 +00002576 line += constructor_param_name((*f_iter)->get_name()) + ": " + type_name( tt, false, true, tt->is_xception(), true);
2577 }
2578
2579 if ( line.size() > 0) {
2580 result << line;
2581 }
2582
2583 string result_str;
2584
2585 if (firstline) {
2586 result_str = " " + result.str();
2587 } else {
2588 result_str = result.str();
2589 }
2590
2591 return result_str;
2592}
2593
Jake Farrell7ae13e12011-10-18 14:35:26 +00002594string t_delphi_generator::type_to_enum(t_type* type) {
2595 while (type->is_typedef()) {
2596 type = ((t_typedef*)type)->get_type();
2597 }
2598
2599 if (type->is_base_type()) {
2600 t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
2601 switch (tbase) {
2602 case t_base_type::TYPE_VOID:
2603 throw "NO T_VOID CONSTRUCT";
2604 case t_base_type::TYPE_STRING:
2605 return "TType.String_";
2606 case t_base_type::TYPE_BOOL:
2607 return "TType.Bool_";
2608 case t_base_type::TYPE_BYTE:
2609 return "TType.Byte_";
2610 case t_base_type::TYPE_I16:
2611 return "TType.I16";
2612 case t_base_type::TYPE_I32:
2613 return "TType.I32";
2614 case t_base_type::TYPE_I64:
2615 return "TType.I64";
2616 case t_base_type::TYPE_DOUBLE:
2617 return "TType.Double_";
2618 }
2619 } else if (type->is_enum()) {
2620 return "TType.I32";
2621 } else if (type->is_struct() || type->is_xception()) {
2622 return "TType.Struct";
2623 } else if (type->is_map()) {
2624 return "TType.Map";
2625 } else if (type->is_set()) {
2626 return "TType.Set_";
2627 } else if (type->is_list()) {
2628 return "TType.List";
2629 }
2630
2631 throw "INVALID TYPE IN type_to_enum: " + type->get_name();
2632}
2633
2634string t_delphi_generator::empty_value(t_type* type) {
2635 while (type->is_typedef()) {
2636 type = ((t_typedef*)type)->get_type();
2637 }
2638
2639 if (type->is_base_type()) {
2640 t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
2641 switch (tbase) {
2642 case t_base_type::TYPE_VOID:
2643 return "0";
2644 case t_base_type::TYPE_STRING:
2645 if (((t_base_type*)type)->is_binary()) {
2646 if (ansistr_binary_) {
2647 return "''";
2648 } else {
2649 return "nil";
2650 }
2651 } else {
2652 return "''";
2653 }
2654 case t_base_type::TYPE_BOOL:
2655 return "False";
2656 case t_base_type::TYPE_BYTE:
2657 case t_base_type::TYPE_I16:
2658 case t_base_type::TYPE_I32:
2659 case t_base_type::TYPE_I64:
2660 return "0";
2661 case t_base_type::TYPE_DOUBLE:
2662 return "0.0";
2663 }
2664 } else if (type->is_enum()) {
2665 return "T" + type->get_name() + "(0)";
2666 } else if (type->is_struct() || type->is_xception()) {
2667 return "nil";
2668 } else if (type->is_map()) {
2669 return "nil";
2670 } else if (type->is_set()) {
2671 return "nil";
2672 } else if (type->is_list()) {
2673 return "nil";
2674 }
2675
2676 throw "INVALID TYPE IN type_to_enum: " + type->get_name();
2677}
2678
Jake Farrell85147552011-10-20 13:30:08 +00002679void t_delphi_generator::generate_delphi_property_writer_definition(ostream& out, t_field* tfield, bool is_xception_class) {
Jake Farrell7ae13e12011-10-18 14:35:26 +00002680 t_type * ftype = tfield->get_type();
2681 bool is_xception = ftype->is_xception();
2682
Jake Farrell85147552011-10-20 13:30:08 +00002683 indent(out) << "procedure Set" << prop_name(tfield, is_xception_class) << "( const Value: " << type_name(ftype,false,true,is_xception,true) << ");" << endl;
Jake Farrell7ae13e12011-10-18 14:35:26 +00002684}
2685
Jake Farrell85147552011-10-20 13:30:08 +00002686void t_delphi_generator::generate_delphi_property_reader_definition(ostream& out, t_field* tfield, bool is_xception_class) {
Jake Farrell7ae13e12011-10-18 14:35:26 +00002687 t_type * ftype = tfield->get_type();
2688 bool is_xception = ftype->is_xception();
2689
Jake Farrell85147552011-10-20 13:30:08 +00002690 indent(out) << "function Get" << prop_name(tfield, is_xception_class) << ": " << type_name(ftype,false,true,is_xception,true) << ";" << endl;
Jake Farrell7ae13e12011-10-18 14:35:26 +00002691}
2692
Jake Farrell85147552011-10-20 13:30:08 +00002693void t_delphi_generator::generate_delphi_isset_reader_definition(ostream& out, t_field* tfield, bool is_xception) {
2694 indent(out) << "function Get__isset_" << prop_name( tfield, is_xception) << ": Boolean;" << endl;
Jake Farrell7ae13e12011-10-18 14:35:26 +00002695}
2696
Jens Geyera58a9cb2012-12-17 23:24:13 +01002697void t_delphi_generator::generate_delphi_clear_union_value(ostream& out, std::string cls_prefix, std::string name, t_type* type, t_field* tfield, std::string fieldPrefix, bool is_xception_class, bool is_union, bool is_xception_factory, std::string xception_factroy_name) {
2698 (void) type;
2699
2700 t_type * ftype = tfield->get_type();
2701 bool is_xception = ftype->is_xception();
2702
2703 indent_impl(out) << "if F__isset_" << prop_name(tfield, is_xception_class) << " then begin" << endl;
2704 indent_up_impl();
2705 indent_impl(out) << "F__isset_" << prop_name(tfield, is_xception_class) << " := False;" << endl;
2706 indent_impl(out) << fieldPrefix << prop_name(tfield, is_xception_class) << " := " << "Default( " << type_name(ftype,false,true,is_xception,true) << ");" << endl;
2707 indent_down_impl();
2708 indent_impl(out) << "end;" << endl;
2709}
2710
2711void t_delphi_generator::generate_delphi_property_writer_impl(ostream& out, std::string cls_prefix, std::string name, t_type* type, t_field* tfield, std::string fieldPrefix, bool is_xception_class, bool is_union, bool is_xception_factory, std::string xception_factroy_name) {
Jake Farrell85147552011-10-20 13:30:08 +00002712 (void) type;
2713
Jake Farrell7ae13e12011-10-18 14:35:26 +00002714 t_type * ftype = tfield->get_type();
2715 bool is_xception = ftype->is_xception();
2716
Jake Farrell85147552011-10-20 13:30:08 +00002717 indent_impl(out) << "procedure " << cls_prefix << name << "." << "Set" << prop_name(tfield, is_xception_class) << "( const Value: " << type_name(ftype,false,true,is_xception,true) << ");" << endl;
Jake Farrell7ae13e12011-10-18 14:35:26 +00002718 indent_impl(out) << "begin" << endl;
2719 indent_up_impl();
Jens Geyera58a9cb2012-12-17 23:24:13 +01002720 if ( is_union ) {
2721 indent_impl(out) << "ClearUnionValues;" << endl;
2722 }
Jake Farrell17515db2012-03-08 04:05:58 +00002723 if (tfield->get_req() != t_field::T_REQUIRED) {
2724 indent_impl(out) << "F__isset_" << prop_name(tfield, is_xception_class) << " := True;" << endl;
2725 }
Jake Farrell85147552011-10-20 13:30:08 +00002726 indent_impl(out) << fieldPrefix << prop_name(tfield, is_xception_class) << " := Value;" << endl;
Jake Farrell7ae13e12011-10-18 14:35:26 +00002727
Jake Farrell85147552011-10-20 13:30:08 +00002728 if (is_xception_class && (! is_xception_factory) ) {
2729 indent_impl(out) << "F" << xception_factroy_name << "." << prop_name(tfield, is_xception_class) << " := Value;" << endl;
Jake Farrell7ae13e12011-10-18 14:35:26 +00002730 }
2731
2732 indent_down_impl();
2733 indent_impl(out) << "end;" << endl << endl;
2734}
2735
Jake Farrell85147552011-10-20 13:30:08 +00002736void t_delphi_generator::generate_delphi_property_reader_impl(ostream& out, std::string cls_prefix, std::string name, t_type* type, t_field* tfield, std::string fieldPrefix, bool is_xception_class) {
2737 (void) type;
2738
Jake Farrell7ae13e12011-10-18 14:35:26 +00002739 t_type * ftype = tfield->get_type();
2740 bool is_xception = ftype->is_xception();
2741
Jake Farrell85147552011-10-20 13:30:08 +00002742 indent_impl(out) << "function " << cls_prefix << name << "." << "Get" << prop_name( tfield, is_xception_class) << ": " << type_name(ftype,false,true,is_xception,true) << ";" << endl;
Jake Farrell7ae13e12011-10-18 14:35:26 +00002743 indent_impl(out) << "begin" << endl;
2744 indent_up_impl();
Jake Farrell85147552011-10-20 13:30:08 +00002745 indent_impl(out) << "Result := " << fieldPrefix << prop_name(tfield, is_xception_class) << ";" << endl;
Jake Farrell7ae13e12011-10-18 14:35:26 +00002746 indent_down_impl();
2747 indent_impl(out) << "end;" << endl << endl;
2748}
2749
Jake Farrell85147552011-10-20 13:30:08 +00002750void t_delphi_generator::generate_delphi_isset_reader_impl(ostream& out, std::string cls_prefix, std::string name, t_type* type, t_field* tfield, std::string fieldPrefix, bool is_xception) {
2751 (void) type;
2752
2753 string isset_name = "__isset_" + prop_name( tfield, is_xception);
Jake Farrell7ae13e12011-10-18 14:35:26 +00002754 indent_impl(out) << "function " << cls_prefix << name << "." << "Get" << isset_name << ": Boolean;" << endl;
2755 indent_impl(out) << "begin" << endl;
2756 indent_up_impl();
2757 indent_impl(out) << "Result := " << fieldPrefix << isset_name << ";" << endl;
2758 indent_down_impl();
2759 indent_impl(out) << "end;" << endl << endl;
2760}
2761
2762void t_delphi_generator::generate_delphi_create_exception_impl(ostream& out, string cls_prefix, t_struct* tstruct, bool is_exception) {
Jake Farrell85147552011-10-20 13:30:08 +00002763 (void) cls_prefix;
2764
Jake Farrell7ae13e12011-10-18 14:35:26 +00002765 string exception_cls_nm = type_name(tstruct,true,true);
2766 string cls_nm = type_name(tstruct,true,false,is_exception,is_exception);
2767
2768 indent_impl(out) << "function " << cls_nm << ".CreateException: " << exception_cls_nm << ";" << endl;
2769
2770 indent_impl(out) << "begin" << endl;
2771 indent_up_impl();
2772
2773
2774 indent_impl(out) << "Result := " << exception_cls_nm << ".Create;" << endl;
2775 string factory_name = normalize_clsnm(tstruct->get_name(),"",true) + "Factory";
2776 indent_impl(out) << "Result." << factory_name << " := Self;" << endl;
2777
2778 const vector<t_field*>& fields = tstruct->get_members();
2779 vector<t_field*>::const_iterator f_iter;
2780
2781 string propname;
2782
2783 for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
Jake Farrell85147552011-10-20 13:30:08 +00002784 propname = prop_name(*f_iter, is_exception);
Jake Farrell17515db2012-03-08 04:05:58 +00002785 if ((*f_iter)->get_req() != t_field::T_REQUIRED) {
2786 indent_impl(out) << "if __isset_" << propname << " then" << endl;
2787 indent_impl(out) << "begin" << endl;
2788 indent_up_impl();
2789 }
Jake Farrell7ae13e12011-10-18 14:35:26 +00002790 indent_impl(out) << "Result." << propname << " := " << propname << ";" << endl;
Jake Farrell17515db2012-03-08 04:05:58 +00002791 if ((*f_iter)->get_req() != t_field::T_REQUIRED) {
2792 indent_down_impl();
2793 indent_impl(out) << "end;" << endl;
2794 }
Jake Farrell7ae13e12011-10-18 14:35:26 +00002795 }
2796
Jake Farrellac102562011-11-23 14:30:41 +00002797 indent_impl(out) << "Result.UpdateMessageProperty;" << endl;
2798
Jake Farrell7ae13e12011-10-18 14:35:26 +00002799 indent_down_impl();
2800 indent_impl(out) << "end;" << endl << endl;
2801}
2802
2803void t_delphi_generator::generate_delphi_struct_reader_impl(ostream& out, string cls_prefix, t_struct* tstruct, bool is_exception) {
2804
2805 ostringstream local_vars;
2806 ostringstream code_block;
2807
2808 const vector<t_field*>& fields = tstruct->get_members();
2809 vector<t_field*>::const_iterator f_iter;
2810
2811
2812 indent_impl(code_block) << "begin" << endl;
2813 indent_up_impl();
2814
Jake Farrell17515db2012-03-08 04:05:58 +00002815 // local bools for required fields
2816 for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
2817 if ((*f_iter)->get_req() == t_field::T_REQUIRED) {
2818 indent_impl(local_vars) <<
2819 "_req_isset_" << prop_name(*f_iter, is_exception) << " : Boolean;" << endl;
2820 indent_impl(code_block) <<
2821 "_req_isset_" << prop_name(*f_iter, is_exception) << " := FALSE;" << endl;
2822 }
2823 }
2824
Jake Farrell7ae13e12011-10-18 14:35:26 +00002825 indent_impl(code_block) << "struc := iprot.ReadStructBegin;" << endl;
2826
2827 indent_impl(code_block) << "try" << endl;
2828 indent_up_impl();
2829
2830 indent_impl(code_block) << "while (true) do" << endl;
2831 indent_impl(code_block) << "begin" << endl;
2832 indent_up_impl();
2833
2834 indent_impl(code_block) << "field_ := iprot.ReadFieldBegin();" << endl;
2835
Jake Farrell7ae13e12011-10-18 14:35:26 +00002836 indent_impl(code_block) << "if (field_.Type_ = TType.Stop) then" << endl;
2837 indent_impl(code_block) << "begin" << endl;
2838 indent_up_impl();
Jake Farrelld09362c2011-10-26 02:25:07 +00002839 indent_impl(code_block) << "Break;" << endl;
Jake Farrell7ae13e12011-10-18 14:35:26 +00002840 indent_down_impl();
2841 indent_impl(code_block) << "end;" << endl;
2842
2843
2844 bool first = true;
2845
2846 for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
2847
2848 if (first) {
2849 indent_impl(code_block) << "case field_.ID of" << endl;
2850 indent_up_impl();
2851 }
2852
2853 first = false;
2854 if (f_iter != fields.begin()) {
2855 code_block << ";" << endl;
2856 }
2857 indent_impl(code_block) << (*f_iter)->get_key() << ": begin" << endl;
2858 indent_up_impl();
2859 indent_impl(code_block) << "if (field_.Type_ = " << type_to_enum((*f_iter)->get_type()) << ") then" << endl;
2860 indent_impl(code_block) << "begin" << endl;
2861 indent_up_impl();
2862
2863 generate_deserialize_field(code_block, is_exception, *f_iter, "", local_vars);
2864
Jake Farrell17515db2012-03-08 04:05:58 +00002865 // required field?
2866 if ((*f_iter)->get_req() == t_field::T_REQUIRED) {
2867 indent_impl(code_block) <<
2868 "_req_isset_" << prop_name(*f_iter, is_exception) << " := TRUE;" << endl;
2869 }
2870
Jake Farrell7ae13e12011-10-18 14:35:26 +00002871 indent_down_impl();
2872
2873 indent_impl(code_block) << "end else" << endl;
2874 indent_impl(code_block) << "begin" << endl;
2875 indent_up_impl();
2876 indent_impl(code_block) << "TProtocolUtil.Skip(iprot, field_.Type_);" << endl;
2877 indent_down_impl();
2878 indent_impl(code_block) << "end;" << endl;
2879 indent_down_impl();
2880 indent_impl(code_block) << "end";
2881
2882 }
2883
2884 if (! first) {
2885 code_block << endl;
2886 indent_impl(code_block) << "else begin" << endl;
2887 indent_up_impl();
2888 }
2889
2890 indent_impl(code_block) << "TProtocolUtil.Skip(iprot, field_.Type_);" << endl;
2891
2892 if (! first) {
2893 indent_down_impl();
2894 indent_impl(code_block) << "end;" << endl;
2895 indent_down_impl();
2896 indent_impl(code_block) << "end;" << endl;
2897 }
2898
Jake Farrell7ae13e12011-10-18 14:35:26 +00002899 indent_impl(code_block) << "iprot.ReadFieldEnd;" << endl;
Jake Farrell7ae13e12011-10-18 14:35:26 +00002900
2901 indent_down_impl();
2902
2903 indent_impl(code_block) << "end;" << endl;
2904 indent_down_impl();
2905
2906 indent_impl(code_block) << "finally" << endl;
2907 indent_up_impl();
2908 indent_impl(code_block) << "iprot.ReadStructEnd;" << endl;
2909 indent_down_impl();
2910 indent_impl(code_block) << "end;" << endl;
Jake Farrell17515db2012-03-08 04:05:58 +00002911
2912 // all required fields have been read?
2913 for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
2914 if ((*f_iter)->get_req() == t_field::T_REQUIRED) {
2915 indent_impl(code_block) <<
2916 "if not _req_isset_" << prop_name(*f_iter, is_exception) << endl;
2917 indent_impl(code_block) <<
2918 "then raise TProtocolException.Create( TProtocolException.INVALID_DATA, '" <<
2919 prop_name(*f_iter, is_exception) << "');" << endl;
2920 }
2921 }
2922
Jake Farrell7ae13e12011-10-18 14:35:26 +00002923 indent_down_impl();
2924 indent_impl(code_block) << "end;" << endl << endl;
2925
2926 string cls_nm;
2927
2928 cls_nm = type_name(tstruct,true,false,is_exception,is_exception);
2929
Roger Meier333bbf32012-01-08 21:51:08 +00002930 indent_impl(out) << "procedure " << cls_prefix << cls_nm << ".Read( const iprot: IProtocol);" << endl;
Jake Farrell7ae13e12011-10-18 14:35:26 +00002931 indent_impl(out) << "var" << endl;
2932 indent_up_impl();
2933 indent_impl(out) << "field_ : IField;" << endl;
2934 indent_impl(out) << "struc : IStruct;" << endl;
2935 indent_down_impl();
2936 out << local_vars.str() << endl;
2937 out << code_block.str();
2938}
2939
2940void t_delphi_generator::generate_delphi_struct_result_writer_impl(ostream& out, string cls_prefix, t_struct* tstruct, bool is_exception) {
2941
2942 ostringstream local_vars;
2943 ostringstream code_block;
2944
2945 string name = tstruct->get_name();
2946 const vector<t_field*>& fields = tstruct->get_sorted_members();
2947 vector<t_field*>::const_iterator f_iter;
2948
2949
2950 indent_impl(code_block) << "begin" << endl;
2951 indent_up_impl();
2952
2953 indent_impl(code_block) << "struc := TStructImpl.Create('" << name << "');" << endl;
2954
2955 indent_impl(code_block) << "oprot.WriteStructBegin(struc);" << endl;
2956
2957 if (fields.size() > 0) {
2958 indent_impl(code_block) << "field_ := TFieldImpl.Create;" << endl;
2959 bool first = true;
2960 for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
2961 if (! first) {
2962 indent_impl(code_block) << "end else" << endl;
2963 }
2964
Jake Farrell85147552011-10-20 13:30:08 +00002965 indent_impl(code_block) << "if (__isset_" << prop_name(*f_iter,is_exception) << ") then" << endl;
Jake Farrell7ae13e12011-10-18 14:35:26 +00002966 indent_impl(code_block) << "begin" << endl;
2967 indent_up_impl();
2968 indent_impl(code_block) <<
2969 "field_.Name := '" << (*f_iter)->get_name() << "';" << endl;
2970 indent_impl(code_block) <<
2971 "field_.Type_ := " << type_to_enum((*f_iter)->get_type()) << ";" << endl;
2972 indent_impl(code_block) <<
2973 "field_.ID := " << (*f_iter)->get_key() << ";" << endl;
2974 indent_impl(code_block) <<
2975 "oprot.WriteFieldBegin(field_);" << endl;
2976 generate_serialize_field(code_block, is_exception, *f_iter, "", local_vars);
2977 indent_impl(code_block) << "oprot.WriteFieldEnd();" << endl;
2978 indent_down_impl();
2979 }
2980
2981 if (! first) {
2982 indent_impl(code_block) << "end;" << endl;
2983 }
2984
2985 }
2986
2987
2988 indent_impl(code_block) << "oprot.WriteFieldStop();" << endl;
2989 indent_impl(code_block) << "oprot.WriteStructEnd();" << endl;
2990
2991 indent_down_impl();
2992 indent_impl(code_block) << "end;" << endl << endl;
2993
2994 string cls_nm;
2995
2996 cls_nm = type_name(tstruct,true,false,is_exception,is_exception);
2997
Roger Meier333bbf32012-01-08 21:51:08 +00002998 indent_impl(out) << "procedure " << cls_prefix << cls_nm << ".Write( const oprot: IProtocol);" << endl;
Jake Farrell7ae13e12011-10-18 14:35:26 +00002999 indent_impl(out) << "var" << endl;
3000 indent_up_impl();
3001 indent_impl(out) << "struc : IStruct;" << endl;
3002
3003 if (fields.size() > 0) {
3004 indent_impl(out) << "field_ : IField;" << endl;
3005 }
3006
3007 out << local_vars.str();
3008 indent_down_impl();
3009 out << code_block.str();
3010
3011}
3012
3013void t_delphi_generator::generate_delphi_struct_writer_impl(ostream& out, string cls_prefix, t_struct* tstruct, bool is_exception) {
3014
3015 ostringstream local_vars;
3016 ostringstream code_block;
3017
3018 string name = tstruct->get_name();
3019 const vector<t_field*>& fields = tstruct->get_sorted_members();
3020 vector<t_field*>::const_iterator f_iter;
3021
3022
3023 indent_impl(code_block) << "begin" << endl;
3024 indent_up_impl();
3025
3026 indent_impl(code_block) << "struc := TStructImpl.Create('" << name << "');" << endl;
3027
3028 indent_impl(code_block) << "oprot.WriteStructBegin(struc);" << endl;
3029
3030 if (fields.size() > 0) {
3031 indent_impl(code_block) << "field_ := TFieldImpl.Create;" << endl;
3032 }
3033
3034 for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
3035 bool null_allowed = type_can_be_null((*f_iter)->get_type());
Jake Farrell17515db2012-03-08 04:05:58 +00003036 bool is_optional = ((*f_iter)->get_req() != t_field::T_REQUIRED);
Jake Farrell7ae13e12011-10-18 14:35:26 +00003037 if (null_allowed) {
3038 indent_impl(code_block) <<
Jake Farrell17515db2012-03-08 04:05:58 +00003039 "if (" << prop_name((*f_iter), is_exception) << " <> nil)";
3040 if (is_optional) {
3041 code_block <<
3042 " and __isset_" << prop_name(*f_iter,is_exception);
3043 }
3044 code_block <<
3045 " then" << endl;
Jake Farrell7ae13e12011-10-18 14:35:26 +00003046 indent_impl(code_block) << "begin" << endl;
3047 indent_up_impl();
3048 } else {
Jake Farrell17515db2012-03-08 04:05:58 +00003049 if (is_optional) {
3050 indent_impl(code_block) << "if (__isset_" << prop_name(*f_iter,is_exception) << ") then" << endl;
3051 indent_impl(code_block) << "begin" << endl;
3052 indent_up_impl();
3053 } else {
3054 indent_impl(code_block) << "// required field" << endl;
3055 }
Jake Farrell7ae13e12011-10-18 14:35:26 +00003056 }
Jake Farrell17515db2012-03-08 04:05:58 +00003057 indent_impl(code_block) <<
Jake Farrell7ae13e12011-10-18 14:35:26 +00003058 "field_.Name := '" << (*f_iter)->get_name() << "';" << endl;
3059 indent_impl(code_block) <<
3060 "field_.Type_ := " << type_to_enum((*f_iter)->get_type()) << ";" << endl;
3061 indent_impl(code_block) <<
3062 "field_.ID := " << (*f_iter)->get_key() << ";" << endl;
3063 indent_impl(code_block) <<
3064 "oprot.WriteFieldBegin(field_);" << endl;
3065 generate_serialize_field(code_block, is_exception, *f_iter, "", local_vars);
3066 indent_impl(code_block) << "oprot.WriteFieldEnd();" << endl;
Jake Farrell17515db2012-03-08 04:05:58 +00003067 if (null_allowed || is_optional) {
3068 indent_down_impl();
3069 indent_impl(code_block) << "end;" << endl;
3070 }
Jake Farrell7ae13e12011-10-18 14:35:26 +00003071 }
3072
3073 indent_impl(code_block) << "oprot.WriteFieldStop();" << endl;
3074 indent_impl(code_block) << "oprot.WriteStructEnd();" << endl;
3075
3076 indent_down_impl();
3077 indent_impl(code_block) << "end;" << endl << endl;
3078
3079 string cls_nm;
3080
3081 cls_nm = type_name(tstruct,true,false,is_exception,is_exception);
3082
Roger Meier333bbf32012-01-08 21:51:08 +00003083 indent_impl(out) << "procedure " << cls_prefix << cls_nm << ".Write( const oprot: IProtocol);" << endl;
Jake Farrell7ae13e12011-10-18 14:35:26 +00003084 indent_impl(out) << "var" << endl;
3085 indent_up_impl();
3086 indent_impl(out) << "struc : IStruct;" << endl;
3087 if (fields.size() > 0) {
3088 indent_impl(out) << "field_ : IField;" << endl;
3089 }
3090 out << local_vars.str();
3091 indent_down_impl();
3092 out << code_block.str();
3093
3094}
3095
Jake Farrellac102562011-11-23 14:30:41 +00003096void t_delphi_generator::generate_delphi_struct_tostring_impl(ostream& out, string cls_prefix, t_struct* tstruct, bool is_exception, bool is_x_factory) {
Jake Farrell7ae13e12011-10-18 14:35:26 +00003097
3098 const vector<t_field*>& fields = tstruct->get_members();
3099 vector<t_field*>::const_iterator f_iter;
3100
3101 string cls_nm;
3102
3103 if (is_exception) {
Jake Farrellac102562011-11-23 14:30:41 +00003104 cls_nm = type_name(tstruct,true,(! is_x_factory),is_x_factory,true);
Jake Farrell7ae13e12011-10-18 14:35:26 +00003105 } else {
3106 cls_nm = type_name(tstruct,true,false);
3107 }
3108
3109 string tmp_sb = "sb";
3110
3111 indent_impl(out) << "function " << cls_prefix << cls_nm << ".ToString: string;" << endl;
3112 indent_impl(out) << "var" << endl;
3113 indent_up_impl();
3114 indent_impl(out) << tmp_sb << " : TThriftStringBuilder;" << endl;
3115 indent_down_impl();
3116 indent_impl(out) << "begin" << endl;
3117 indent_up_impl();
3118
3119 indent_impl(out) << tmp_sb << " := TThriftStringBuilder.Create('(');" << endl;
3120 indent_impl(out) << "try" << endl;
3121 indent_up_impl();
3122
3123 bool first = true;
3124
3125 for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
3126 if (first) {
3127 first = false;
3128 indent_impl(out) <<
Jake Farrell85147552011-10-20 13:30:08 +00003129 tmp_sb << ".Append('" << prop_name((*f_iter), is_exception) << ": ');" << endl;
Jake Farrell7ae13e12011-10-18 14:35:26 +00003130 } else {
3131 indent_impl(out) <<
Jake Farrell85147552011-10-20 13:30:08 +00003132 tmp_sb << ".Append('," << prop_name((*f_iter), is_exception) << ": ');" << endl;
Jake Farrell7ae13e12011-10-18 14:35:26 +00003133 }
3134 t_type* ttype = (*f_iter)->get_type();
3135 if (ttype->is_xception() || ttype->is_struct()) {
3136 indent_impl(out) <<
Jake Farrell85147552011-10-20 13:30:08 +00003137 "if (" << prop_name((*f_iter), is_exception) << " = nil) then " << tmp_sb << ".Append('<null>') else " << tmp_sb << ".Append("<< prop_name((*f_iter), is_exception) << ".ToString());" << endl;
Jake Farrell7ae13e12011-10-18 14:35:26 +00003138 } else if (ttype->is_enum()) {
3139 indent_impl(out) <<
Jake Farrell85147552011-10-20 13:30:08 +00003140 tmp_sb << ".Append(Integer(" << prop_name((*f_iter), is_exception) << "));" << endl;
Jake Farrell7ae13e12011-10-18 14:35:26 +00003141 } else {
3142 indent_impl(out) <<
Jake Farrell85147552011-10-20 13:30:08 +00003143 tmp_sb << ".Append(" << prop_name((*f_iter), is_exception) << ");" << endl;
Jake Farrell7ae13e12011-10-18 14:35:26 +00003144 }
3145 }
3146
3147 indent_impl(out) <<
3148 tmp_sb << ".Append(')');" << endl;
3149 indent_impl(out) <<
3150 "Result := " << tmp_sb << ".ToString;" << endl;
3151
3152 indent_down_impl();
3153 indent_impl(out) << "finally" << endl;
3154 indent_up_impl();
3155 indent_impl(out) << tmp_sb << ".Free;" << endl;
3156 indent_down_impl();
3157 indent_impl(out) << "end;" << endl;
3158
3159 indent_down_impl();
3160 indent_impl(out) << "end;" << endl << endl;
3161}
3162
3163bool t_delphi_generator::is_void( t_type* type ) {
3164 while (type->is_typedef()) {
3165 type = ((t_typedef*)type)->get_type();
3166 }
3167
3168 if (type->is_base_type()) {
3169 t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
3170 if (tbase == t_base_type::TYPE_VOID) {
3171 return true;
3172 }
3173 }
3174 return false;
3175}
3176
Jens Geyerc2c4d722013-06-04 21:43:40 +02003177THRIFT_REGISTER_GENERATOR(delphi, "delphi",
Jens Geyer1075a6f2013-07-14 13:54:10 +02003178" ansistr_binary: Use AnsiString for binary datatype (default is TBytes).\n"
3179" register_types: Enable TypeRegistry, allows for creation of struct, union\n"
Jens Geyerec8744c2013-09-06 21:08:24 +02003180" and container instances by interface or TypeInfo()\n"
3181" constprefix: Name TConstants classes after IDL to reduce ambiguities\n");
Jake Farrell7ae13e12011-10-18 14:35:26 +00003182