]> git.proxmox.com Git - ceph.git/blame - ceph/src/jaegertracing/thrift/compiler/cpp/src/thrift/generate/t_delphi_generator.cc
buildsys: switch source download to quincy
[ceph.git] / ceph / src / jaegertracing / thrift / compiler / cpp / src / thrift / generate / t_delphi_generator.cc
CommitLineData
f67539c2
TL
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 *
19 * 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
24#include <cassert>
25
26#include <string>
27#include <fstream>
28#include <iostream>
29#include <vector>
30#include <list>
31
32#include <stdlib.h>
33#include <sys/stat.h>
34#include <sstream>
35#include <cctype>
36
37#include "thrift/platform.h"
38#include "thrift/generate/t_oop_generator.h"
39
40using std::map;
41using std::ofstream;
42using std::ostream;
43using std::ostringstream;
44using std::string;
45using std::stringstream;
46using std::vector;
47
48static const string endl = "\n"; // avoid ostream << std::endl flushes
49
50class t_delphi_generator : public t_oop_generator {
51public:
52 t_delphi_generator(t_program* program,
53 const std::map<std::string, std::string>& parsed_options,
54 const std::string& option_string)
55 : t_oop_generator(program) {
56 (void)option_string;
57 indent_impl_ = 0;
58 has_forward = false;
59 has_enum = false;
60 has_const = false;
61 std::map<std::string, std::string>::const_iterator iter;
62
63 ansistr_binary_ = false;
64 register_types_ = false;
65 constprefix_ = false;
66 events_ = false;
67 xmldoc_ = false;
68 async_ = false;
69 for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
70 if( iter->first.compare("ansistr_binary") == 0) {
71 ansistr_binary_ = true;
72 } else if( iter->first.compare("register_types") == 0) {
73 register_types_ = true;
74 } else if( iter->first.compare("constprefix") == 0) {
75 constprefix_ = true;
76 } else if( iter->first.compare("events") == 0) {
77 events_ = true;
78 } else if( iter->first.compare("xmldoc") == 0) {
79 xmldoc_ = true;
80 } else if( iter->first.compare("async") == 0) {
81 async_ = true;
82 } else {
83 throw "unknown option delphi:" + iter->first;
84 }
85 }
86
87 out_dir_base_ = "gen-delphi";
88 escape_.clear();
89 escape_['\''] = "''";
90 }
91
92 void init_generator() override;
93 void close_generator() override;
94
95 void generate_consts(std::vector<t_const*> consts) override;
96
97 void generate_typedef(t_typedef* ttypedef) override;
98 void generate_enum(t_enum* tenum) override;
99 void generate_forward_declaration(t_struct* tstruct) override;
100 void generate_struct(t_struct* tstruct) override;
101 void generate_xception(t_struct* txception) override;
102 void generate_service(t_service* tservice) override;
103 void generate_property(ostream& out, t_field* tfield, bool isPublic, bool is_xception);
104 void generate_property_writer_(ostream& out, t_field* tfield, bool isPublic);
105
106 void generate_delphi_property(ostream& out,
107 bool struct_is_exception,
108 t_field* tfield,
109 bool isPublic,
110 std::string fieldPrefix = "");
111 void generate_delphi_isset_reader_definition(ostream& out, t_field* tfield, bool is_xception);
112 void generate_delphi_property_reader_definition(ostream& out,
113 t_field* tfield,
114 bool is_xception_class);
115 void generate_delphi_property_writer_definition(ostream& out,
116 t_field* tfield,
117 bool is_xception_class);
118 void generate_delphi_property_reader_impl(ostream& out,
119 std::string cls_prefix,
120 std::string name,
121 t_type* type,
122 t_field* tfield,
123 std::string fieldPrefix,
124 bool is_xception_class);
125 void generate_delphi_property_writer_impl(ostream& out,
126 std::string cls_prefix,
127 std::string name,
128 t_type* type,
129 t_field* tfield,
130 std::string fieldPrefix,
131 bool is_xception_class,
132 bool is_union,
133 bool is_xception_factory,
134 std::string xception_factory_name);
135 void generate_delphi_clear_union_value(ostream& out,
136 std::string cls_prefix,
137 std::string name,
138 t_type* type,
139 t_field* tfield,
140 std::string fieldPrefix,
141 bool is_xception_class,
142 bool is_union,
143 bool is_xception_factory,
144 std::string xception_factory_name);
145 void generate_delphi_isset_reader_impl(ostream& out,
146 std::string cls_prefix,
147 std::string name,
148 t_type* type,
149 t_field* tfield,
150 std::string fieldPrefix,
151 bool is_xception);
152 void generate_delphi_struct_writer_impl(ostream& out,
153 std::string cls_prefix,
154 t_struct* tstruct,
155 bool is_exception);
156 void generate_delphi_struct_result_writer_impl(ostream& out,
157 std::string cls_prefix,
158 t_struct* tstruct,
159 bool is_exception);
160
161 void generate_delphi_struct_tostring_impl(ostream& out,
162 std::string cls_prefix,
163 t_struct* tstruct,
164 bool is_exception,
165 bool is_x_factory);
166
167 void add_delphi_uses_list(string unitname);
168
169 void generate_delphi_struct_reader_impl(ostream& out,
170 std::string cls_prefix,
171 t_struct* tstruct,
172 bool is_exception);
173 void generate_delphi_create_exception_impl(ostream& out,
174 string cls_prefix,
175 t_struct* tstruct,
176 bool is_exception);
177
178 bool const_needs_var(t_type* type);
179 void print_const_prop(std::ostream& out, string name, t_type* type, t_const_value* value);
180 void print_private_field(std::ostream& out, string name, t_type* type, t_const_value* value);
181 void print_const_value(std::ostream& vars,
182 std::ostream& out,
183 std::string name,
184 t_type* type,
185 t_const_value* value);
186 void initialize_field(std::ostream& vars,
187 std::ostream& out,
188 std::string name,
189 t_type* type,
190 t_const_value* value);
191 void finalize_field(std::ostream& out,
192 std::string name,
193 t_type* type,
194 t_const_value* value,
195 std::string cls_nm = "");
196 std::string render_const_value(std::ostream& local_vars,
197 std::ostream& out,
198 std::string name,
199 t_type* type,
200 t_const_value* value);
201 void print_const_def_value(std::ostream& vars,
202 std::ostream& out,
203 std::string name,
204 t_type* type,
205 t_const_value* value,
206 std::string cls_nm = "");
207 std::string make_constants_classname();
208
209 void generate_delphi_struct(t_struct* tstruct, bool is_exception);
210 void generate_delphi_struct_impl(ostream& out,
211 std::string cls_prefix,
212 t_struct* tstruct,
213 bool is_exception,
214 bool is_result = false,
215 bool is_x_factory = false);
216 void print_delphi_struct_type_factory_func(ostream& out, t_struct* tstruct);
217 void generate_delphi_struct_type_factory(ostream& out,
218 std::string cls_prefix,
219 t_struct* tstruct,
220 bool is_exception,
221 bool is_result = false,
222 bool is_x_factory = false);
223 void generate_delphi_struct_type_factory_registration(ostream& out,
224 std::string cls_prefix,
225 t_struct* tstruct,
226 bool is_exception,
227 bool is_result = false,
228 bool is_x_factory = false);
229 void generate_delphi_struct_definition(std::ostream& out,
230 t_struct* tstruct,
231 bool is_xception = false,
232 bool in_class = false,
233 bool is_result = false,
234 bool is_x_factory = false);
235 void generate_delphi_struct_reader(std::ostream& out, t_struct* tstruct);
236 void generate_delphi_struct_result_writer(std::ostream& out, t_struct* tstruct);
237 void generate_delphi_struct_writer(std::ostream& out, t_struct* tstruct);
238 void generate_delphi_struct_tostring(std::ostream& out, t_struct* tstruct);
239
240 void generate_function_helpers(t_function* tfunction);
241 void generate_service_interface(t_service* tservice);
242 void generate_service_interface(t_service* tservice, bool for_async);
243 void generate_service_helpers(t_service* tservice);
244 void generate_service_client(t_service* tservice);
245 void generate_service_server(t_service* tservice);
246 void generate_process_function(t_service* tservice, t_function* function);
247
248 void generate_deserialize_field(std::ostream& out,
249 bool is_xception,
250 t_field* tfield,
251 std::string prefix,
252 std::ostream& local_vars);
253 void generate_deserialize_struct(std::ostream& out,
254 t_struct* tstruct,
255 std::string name,
256 std::string prefix);
257 void generate_deserialize_container(ostream& out,
258 bool is_xception,
259 t_type* ttype,
260 string name,
261 std::ostream& local_vars);
262
263 void generate_deserialize_set_element(std::ostream& out,
264 bool is_xception,
265 t_set* tset,
266 std::string prefix,
267 std::ostream& local_vars);
268 void generate_deserialize_map_element(std::ostream& out,
269 bool is_xception,
270 t_map* tmap,
271 std::string prefix,
272 std::ostream& local_vars);
273 void generate_deserialize_list_element(std::ostream& out,
274 bool is_xception,
275 t_list* list,
276 std::string prefix,
277 std::ostream& local_vars);
278
279 void generate_serialize_field(std::ostream& out,
280 bool is_xception,
281 t_field* tfield,
282 std::string prefix,
283 std::ostream& local_vars);
284 void generate_serialize_struct(std::ostream& out,
285 t_struct* tstruct,
286 std::string prefix,
287 std::ostream& local_vars);
288 void generate_serialize_container(std::ostream& out,
289 bool is_xception,
290 t_type* ttype,
291 std::string prefix,
292 std::ostream& local_vars);
293 void generate_serialize_map_element(std::ostream& out,
294 bool is_xception,
295 t_map* tmap,
296 std::string iter,
297 std::string map,
298 std::ostream& local_vars);
299 void generate_serialize_set_element(std::ostream& out,
300 bool is_xception,
301 t_set* tmap,
302 std::string iter,
303 std::ostream& local_vars);
304 void generate_serialize_list_element(std::ostream& out,
305 bool is_xception,
306 t_list* tlist,
307 std::string iter,
308 std::ostream& local_vars);
309
310 void delphi_type_usings(std::ostream& out);
311 std::string delphi_thrift_usings();
312
313 std::string type_name(t_type* ttype,
314 bool b_cls = false,
315 bool b_no_postfix = false,
316 bool b_exception_factory = false,
317 bool b_full_exception_factory = false);
318 std::string normalize_clsnm(std::string name,
319 std::string prefix,
320 bool b_no_check_keyword = false);
321 std::string make_valid_delphi_identifier(std::string const& fromName);
322 std::string input_arg_prefix(t_type* ttype);
323
324 std::string base_type_name(t_base_type* tbase);
325 std::string declare_field(t_field* tfield,
326 bool init = false,
327 std::string prefix = "",
328 bool is_xception_class = false);
329 std::string function_signature(t_function* tfunction,
330 bool for_async,
331 std::string full_cls = "",
332 bool is_xception = false);
333 std::string argument_list(t_struct* tstruct);
334 std::string constructor_argument_list(t_struct* tstruct, std::string current_indent);
335 std::string type_to_enum(t_type* ttype);
336 std::string prop_name(t_field* tfield, bool is_xception = false);
337 std::string prop_name(std::string name, bool is_xception = false);
338 std::string constructor_param_name(string name);
339
340 void write_enum(std::string line);
341 void write_forward_decr(std::string line);
342 void write_const(std::string line);
343 void write_struct(std::string line);
344 void write_service(std::string line);
345
346 std::string autogen_comment() override {
347 return std::string("(**\n") + " * Autogenerated by Thrift Compiler (" + THRIFT_VERSION + ")\n"
348 + " *\n" + " * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n"
349 + " *)\n";
350 }
351
352 string replace_all(string contents, string search, string replace);
353 string xml_encode(string contents);
354 string xmldoc_encode(string contents);
355 string xmlattrib_encode(string contents);
356 void generate_delphi_doc(std::ostream& out, t_field* field);
357 void generate_delphi_doc(std::ostream& out, t_doc* tdoc);
358 void generate_delphi_doc(std::ostream& out, t_function* tdoc);
359 void generate_delphi_docstring_comment(std::ostream& out, string contents);
360
361 bool type_can_be_null(t_type* ttype) {
362 while (ttype->is_typedef()) {
363 ttype = ((t_typedef*)ttype)->get_type();
364 }
365
366 return ttype->is_container() || ttype->is_struct() || ttype->is_xception();
367 }
368
369private:
370 std::string namespace_name_;
371 std::ostringstream s_forward_decr;
372 std::ostringstream s_enum;
373 std::ostringstream s_const;
374 std::ostringstream s_struct;
375 std::ostringstream s_service;
376 std::ostringstream s_const_impl;
377 std::ostringstream s_struct_impl;
378 std::ostringstream s_service_impl;
379 std::ostringstream s_type_factory_registration;
380 std::ostringstream s_type_factory_funcs;
381 bool has_forward;
382 bool has_enum;
383 bool has_const;
384 std::string namespace_dir_;
385 std::map<std::string, int> delphi_keywords;
386 std::map<std::string, int> delphi_reserved_method;
387 std::map<std::string, int> delphi_reserved_method_exception;
388 std::map<std::string, int> types_known;
389 std::list<t_typedef*> typedefs_pending;
390 std::vector<std::string> uses_list;
391 void create_keywords();
392 bool find_keyword(std::map<std::string, int>& keyword_map, std::string name);
393 std::string normalize_name(std::string name,
394 bool b_method = false,
395 bool b_exception_method = false);
396 std::string empty_value(t_type* type);
397 bool is_fully_defined_type(t_type* ttype);
398 void add_defined_type(t_type* ttype);
399 void init_known_types_list();
400 bool is_void(t_type* type);
401 int indent_impl_;
402 bool ansistr_binary_;
403 bool register_types_;
404 bool constprefix_;
405 bool events_;
406 bool xmldoc_;
407 bool async_;
408 void indent_up_impl() { ++indent_impl_; };
409 void indent_down_impl() { --indent_impl_; };
410 std::string indent_impl() {
411 std::string ind = "";
412 int i;
413 for (i = 0; i < indent_impl_; ++i) {
414 ind += " ";
415 }
416 return ind;
417 };
418 std::ostream& indent_impl(std::ostream& os) { return os << indent_impl(); };
419};
420
421string t_delphi_generator::replace_all(string contents, string search, string repl) {
422 string str(contents);
423
424 size_t slen = search.length();
425 size_t rlen = repl.length();
426 size_t incr = (rlen > 0) ? rlen : 1;
427
428 if (slen > 0) {
429 size_t found = str.find(search);
430 while ((found != string::npos) && (found < str.length())) {
431 str.replace(found, slen, repl);
432 found = str.find(search, found + incr);
433 }
434 }
435
436 return str;
437}
438
439// XML encoding
440string t_delphi_generator::xml_encode(string contents) {
441 string str(contents);
442
443 // escape the escape
444 str = replace_all(str, "&", "&amp;");
445
446 // other standard XML entities
447 str = replace_all(str, "<", "&lt;");
448 str = replace_all(str, ">", "&gt;");
449
450 return str;
451}
452
453// XML attribute encoding
454string t_delphi_generator::xmlattrib_encode(string contents) {
455 string str(xml_encode(contents));
456
457 // our attribs are enclosed in "
458 str = replace_all(str, "\"", "\\\"");
459
460 return str;
461}
462
463// XML encoding for doc comments
464string t_delphi_generator::xmldoc_encode(string contents) {
465 string str(xml_encode(contents));
466
467 // XMLDoc specific: convert linebreaks into <para>graphs</para>
468 str = replace_all(str, "\r\n", "\r");
469 str = replace_all(str, "\n", "\r");
470 str = replace_all(str, "\r", "</para>\n<para>");
471
472 return str;
473}
474
475void t_delphi_generator::generate_delphi_docstring_comment(ostream& out, string contents) {
476 if (xmldoc_) {
477 generate_docstring_comment(out,
478 "{$REGION 'XMLDoc'}/// <summary>\n",
479 "/// ",
480 "<para>" + contents + "</para>",
481 "/// </summary>\n{$ENDREGION}\n");
482 }
483}
484
485void t_delphi_generator::generate_delphi_doc(ostream& out, t_field* field) {
486 if (xmldoc_) {
487 if (field->get_type()->is_enum()) {
488 string combined_message = xmldoc_encode(field->get_doc()) + "\n<seealso cref=\""
489 + xmldoc_encode(type_name(field->get_type())) + "\"/>";
490 generate_delphi_docstring_comment(out, combined_message);
491 } else {
492 generate_delphi_doc(out, (t_doc*)field);
493 }
494 }
495}
496
497void t_delphi_generator::generate_delphi_doc(ostream& out, t_doc* tdoc) {
498 if (tdoc->has_doc() && xmldoc_) {
499 generate_delphi_docstring_comment(out, xmldoc_encode(tdoc->get_doc()));
500 }
501}
502
503void t_delphi_generator::generate_delphi_doc(ostream& out, t_function* tfunction) {
504 if (tfunction->has_doc() && xmldoc_) {
505 stringstream ps;
506 const vector<t_field*>& fields = tfunction->get_arglist()->get_members();
507 vector<t_field*>::const_iterator p_iter;
508 for (p_iter = fields.begin(); p_iter != fields.end(); ++p_iter) {
509 t_field* p = *p_iter;
510 ps << "\n<param name=\"" << xmlattrib_encode(p->get_name()) << "\">";
511 if (p->has_doc()) {
512 std::string str = p->get_doc();
513 str.erase(std::remove(str.begin(), str.end(), '\n'),
514 str.end()); // remove the newlines that appear from the parser
515 ps << xmldoc_encode(str);
516 }
517 ps << "</param>";
518 }
519 generate_docstring_comment(out,
520 "{$REGION 'XMLDoc'}",
521 "/// ",
522 "<summary><para>" + xmldoc_encode(tfunction->get_doc())
523 + "</para></summary>" + ps.str(),
524 "{$ENDREGION}\n");
525 }
526}
527
528bool t_delphi_generator::find_keyword(std::map<std::string, int>& keyword_map, std::string name) {
529 std::string::size_type len = name.length();
530
531 if (len <= 0) {
532 return false;
533 }
534
535 std::string::size_type nlast = name.find_last_of('_');
536
537 if (nlast >= 1) {
538 if (nlast == (len - 1)) {
539 string new_name(name, 0, nlast);
540 return find_keyword(keyword_map, new_name);
541 }
542 }
543 return (keyword_map[name] == 1);
544}
545
546std::string t_delphi_generator::normalize_name(std::string name,
547 bool b_method,
548 bool b_exception_method) {
549 string tmp(name);
550 std::transform(tmp.begin(), tmp.end(), tmp.begin(), static_cast<int (*)(int)>(std::tolower));
551
552 bool b_found = false;
553
554 if (find_keyword(delphi_keywords, tmp)) {
555 b_found = true;
556 } else if (b_method && find_keyword(delphi_reserved_method, tmp)) {
557 b_found = true;
558 } else if (b_exception_method && find_keyword(delphi_reserved_method_exception, tmp)) {
559 b_found = true;
560 }
561
562 if (b_found) {
563 return name + "_";
564 } else {
565 return name;
566 }
567}
568
569void t_delphi_generator::create_keywords() {
570 delphi_keywords["and"] = 1;
571 delphi_keywords["end"] = 1;
572 delphi_keywords["interface"] = 1;
573 delphi_keywords["raise"] = 1;
574 delphi_keywords["uses"] = 1;
575 delphi_keywords["array"] = 1;
576 delphi_keywords["except"] = 1;
577 delphi_keywords["is"] = 1;
578 delphi_keywords["record"] = 1;
579 delphi_keywords["var"] = 1;
580 delphi_keywords["as"] = 1;
581 delphi_keywords["exports"] = 1;
582 delphi_keywords["label"] = 1;
583 delphi_keywords["repeat"] = 1;
584 delphi_keywords["while"] = 1;
585 delphi_keywords["asm"] = 1;
586 delphi_keywords["file"] = 1;
587 delphi_keywords["library"] = 1;
588 delphi_keywords["resourcestring"] = 1;
589 delphi_keywords["with"] = 1;
590 delphi_keywords["begin"] = 1;
591 delphi_keywords["finalization"] = 1;
592 delphi_keywords["mod"] = 1;
593 delphi_keywords["set"] = 1;
594 delphi_keywords["xor"] = 1;
595 delphi_keywords["case"] = 1;
596 delphi_keywords["finally"] = 1;
597 delphi_keywords["nil"] = 1;
598 delphi_keywords["shl"] = 1;
599 delphi_keywords["class"] = 1;
600 delphi_keywords["for"] = 1;
601 delphi_keywords["not"] = 1;
602 delphi_keywords["shr"] = 1;
603 delphi_keywords["const"] = 1;
604 delphi_keywords["function"] = 1;
605 delphi_keywords["object"] = 1;
606 delphi_keywords["string"] = 1;
607 delphi_keywords["constructor"] = 1;
608 delphi_keywords["goto"] = 1;
609 delphi_keywords["of"] = 1;
610 delphi_keywords["then"] = 1;
611 delphi_keywords["destructor"] = 1;
612 delphi_keywords["if"] = 1;
613 delphi_keywords["or"] = 1;
614 delphi_keywords["threadvar"] = 1;
615 delphi_keywords["dispinterface"] = 1;
616 delphi_keywords["implementation"] = 1;
617 delphi_keywords["out"] = 1;
618 delphi_keywords["to"] = 1;
619 delphi_keywords["div"] = 1;
620 delphi_keywords["in"] = 1;
621 delphi_keywords["packed"] = 1;
622 delphi_keywords["try"] = 1;
623 delphi_keywords["do"] = 1;
624 delphi_keywords["inherited"] = 1;
625 delphi_keywords["procedure"] = 1;
626 delphi_keywords["type"] = 1;
627 delphi_keywords["downto"] = 1;
628 delphi_keywords["initialization"] = 1;
629 delphi_keywords["program"] = 1;
630 delphi_keywords["unit"] = 1;
631 delphi_keywords["else"] = 1;
632 delphi_keywords["inline"] = 1;
633 delphi_keywords["property"] = 1;
634 delphi_keywords["until"] = 1;
635 delphi_keywords["private"] = 1;
636 delphi_keywords["protected"] = 1;
637 delphi_keywords["public"] = 1;
638 delphi_keywords["published"] = 1;
639 delphi_keywords["automated"] = 1;
640 delphi_keywords["at"] = 1;
641 delphi_keywords["on"] = 1;
642
643 // reserved/predefined variables and types (lowercase!)
644 delphi_keywords["result"] = 1;
645 delphi_keywords["system"] = 1;
646 delphi_keywords["sysutils"] = 1;
647 delphi_keywords["thrift"] = 1;
648 delphi_keywords["tbytes"] = 1;
649 delphi_keywords["tobject"] = 1;
650 delphi_keywords["tclass"] = 1;
651 delphi_keywords["tinterfacedobject"] = 1;
652 delphi_keywords["ansistring"] = 1;
653 delphi_keywords["string"] = 1;
654 delphi_keywords["boolean"] = 1;
655 delphi_keywords["shortint"] = 1;
656 delphi_keywords["smallint"] = 1;
657 delphi_keywords["integer"] = 1;
658 delphi_keywords["int64"] = 1;
659 delphi_keywords["double"] = 1;
660
661 delphi_reserved_method["create"] = 1;
662 delphi_reserved_method["free"] = 1;
663 delphi_reserved_method["initinstance"] = 1;
664 delphi_reserved_method["cleanupinstance"] = 1;
665 delphi_reserved_method["classtype"] = 1;
666 delphi_reserved_method["classname"] = 1;
667 delphi_reserved_method["classnameis"] = 1;
668 delphi_reserved_method["classparent"] = 1;
669 delphi_reserved_method["classinfo"] = 1;
670 delphi_reserved_method["instancesize"] = 1;
671 delphi_reserved_method["inheritsfrom"] = 1;
672 delphi_reserved_method["methodaddress"] = 1;
673 delphi_reserved_method["methodname"] = 1;
674 delphi_reserved_method["fieldaddress"] = 1;
675 delphi_reserved_method["getinterface"] = 1;
676 delphi_reserved_method["getinterfaceentry"] = 1;
677 delphi_reserved_method["getinterfacetable"] = 1;
678 delphi_reserved_method["unitname"] = 1;
679 delphi_reserved_method["equals"] = 1;
680 delphi_reserved_method["gethashcode"] = 1;
681 delphi_reserved_method["tostring"] = 1;
682 delphi_reserved_method["safecallexception"] = 1;
683 delphi_reserved_method["afterconstruction"] = 1;
684 delphi_reserved_method["beforedestruction"] = 1;
685 delphi_reserved_method["dispatch"] = 1;
686 delphi_reserved_method["defaulthandler"] = 1;
687 delphi_reserved_method["newinstance"] = 1;
688 delphi_reserved_method["freeinstance"] = 1;
689 delphi_reserved_method["destroy"] = 1;
690 delphi_reserved_method["read"] = 1;
691 delphi_reserved_method["write"] = 1;
692
693 delphi_reserved_method_exception["setinnerexception"] = 1;
694 delphi_reserved_method_exception["setstackinfo"] = 1;
695 delphi_reserved_method_exception["getstacktrace"] = 1;
696 delphi_reserved_method_exception["raisingexception"] = 1;
697 delphi_reserved_method_exception["createfmt"] = 1;
698 delphi_reserved_method_exception["createres"] = 1;
699 delphi_reserved_method_exception["createresfmt"] = 1;
700 delphi_reserved_method_exception["createhelp"] = 1;
701 delphi_reserved_method_exception["createfmthelp"] = 1;
702 delphi_reserved_method_exception["createreshelp"] = 1;
703 delphi_reserved_method_exception["createresfmthelp"] = 1;
704 delphi_reserved_method_exception["getbaseexception"] = 1;
705 delphi_reserved_method_exception["baseexception"] = 1;
706 delphi_reserved_method_exception["helpcontext"] = 1;
707 delphi_reserved_method_exception["innerexception"] = 1;
708 delphi_reserved_method_exception["message"] = 1;
709 delphi_reserved_method_exception["stacktrace"] = 1;
710 delphi_reserved_method_exception["stackinfo"] = 1;
711 delphi_reserved_method_exception["getexceptionstackinfoproc"] = 1;
712 delphi_reserved_method_exception["getstackinfostringproc"] = 1;
713 delphi_reserved_method_exception["cleanupstackinfoproc"] = 1;
714 delphi_reserved_method_exception["raiseouterexception"] = 1;
715 delphi_reserved_method_exception["throwouterexception"] = 1;
716}
717
718void t_delphi_generator::add_delphi_uses_list(string unitname) {
719 vector<std::string>::const_iterator s_iter;
720 bool found = false;
721 for (s_iter = uses_list.begin(); s_iter != uses_list.end(); ++s_iter) {
722 if ((*s_iter) == unitname) {
723 found = true;
724 break;
725 }
726 }
727 if (!found) {
728 uses_list.push_back(unitname);
729 }
730}
731
732void t_delphi_generator::init_generator() {
733 indent_impl_ = 0;
734 namespace_name_ = program_->get_namespace("delphi");
735 has_forward = false;
736 has_enum = false;
737 has_const = false;
738 create_keywords();
739
740 add_delphi_uses_list("Classes");
741 add_delphi_uses_list("SysUtils");
742 add_delphi_uses_list("Generics.Collections");
743 if(async_) {
744 add_delphi_uses_list("System.Threading");
745 }
746
747 add_delphi_uses_list("Thrift");
748 add_delphi_uses_list("Thrift.Utils");
749 add_delphi_uses_list("Thrift.Collections");
750 add_delphi_uses_list("Thrift.Protocol");
751 add_delphi_uses_list("Thrift.Transport");
752 if (register_types_) {
753 add_delphi_uses_list("Thrift.TypeRegistry");
754 }
755
756 init_known_types_list();
757
758 string unitname, nsname;
759 const vector<t_program*>& includes = program_->get_includes();
760 for (auto include : includes) {
761 unitname = include->get_name();
762 nsname = include->get_namespace("delphi");
763 if ("" != nsname) {
764 unitname = normalize_name(nsname);
765 }
766 add_delphi_uses_list(unitname);
767 }
768
769 MKDIR(get_out_dir().c_str());
770}
771
772void t_delphi_generator::close_generator() {
773 std::string unitname = program_name_;
774 if ("" != namespace_name_) {
775 unitname = namespace_name_;
776 }
777
778 for (int i = 0; i < (int)unitname.size(); i++) {
779 if (unitname[i] == ' ') {
780 unitname.replace(i, 1, "_");
781 }
782 }
783
784 unitname = normalize_name(unitname);
785
786 std::string f_name = get_out_dir() + "/" + unitname + ".pas";
787 ofstream_with_content_based_conditional_update f_all;
788
789 f_all.open(f_name);
790
791 f_all << autogen_comment() << endl;
792 generate_delphi_doc(f_all, program_);
793 f_all << "unit " << unitname << ";" << endl << endl;
794 f_all << "interface" << endl << endl;
795 f_all << "uses" << endl;
796
797 indent_up();
798
799 vector<std::string>::const_iterator s_iter;
800 for (s_iter = uses_list.begin(); s_iter != uses_list.end(); ++s_iter) {
801 if (s_iter != uses_list.begin()) {
802 f_all << ",";
803 f_all << endl;
804 }
805 indent(f_all) << *s_iter;
806 }
807
808 f_all << ";" << endl << endl;
809
810 indent_down();
811
812 string tmp_unit(unitname);
813 for (int i = 0; i < (int)tmp_unit.size(); i++) {
814 if (tmp_unit[i] == '.') {
815 tmp_unit.replace(i, 1, "_");
816 }
817 }
818
819 f_all << "const" << endl;
820 indent_up();
821 indent(f_all) << "c" << tmp_unit
822 << "_Option_AnsiStr_Binary = " << (ansistr_binary_ ? "True" : "False") << ";"
823 << endl;
824 indent(f_all) << "c" << tmp_unit
825 << "_Option_Register_Types = " << (register_types_ ? "True" : "False") << ";"
826 << endl;
827 indent(f_all) << "c" << tmp_unit
828 << "_Option_ConstPrefix = " << (constprefix_ ? "True" : "False") << ";" << endl;
829 indent(f_all) << "c" << tmp_unit << "_Option_Events = " << (events_ ? "True" : "False")
830 << ";" << endl;
831 indent(f_all) << "c" << tmp_unit << "_Option_XmlDoc = " << (xmldoc_ ? "True" : "False")
832 << ";" << endl;
833 indent_down();
834
835 f_all << endl;
836 f_all << "type" << endl;
837 if (has_forward) {
838 f_all << s_forward_decr.str() << endl;
839 }
840 if (has_enum) {
841 indent(f_all) << endl;
842 indent(f_all) << "{$SCOPEDENUMS ON}" << endl << endl;
843 f_all << s_enum.str();
844 indent(f_all) << "{$SCOPEDENUMS OFF}" << endl << endl;
845 }
846 f_all << s_struct.str();
847 f_all << s_service.str();
848 f_all << s_const.str();
849 f_all << "implementation" << endl << endl;
850 f_all << s_struct_impl.str();
851 f_all << s_service_impl.str();
852 f_all << s_const_impl.str();
853
854 if (register_types_) {
855 f_all << endl;
856 f_all << "// Type factory methods and registration" << endl;
857 f_all << s_type_factory_funcs.str();
858 f_all << "procedure RegisterTypeFactories;" << endl;
859 f_all << "begin" << endl;
860 f_all << s_type_factory_registration.str();
861 f_all << "end;" << endl;
862 }
863 f_all << endl;
864
865 string constants_class = make_constants_classname();
866
867 f_all << "initialization" << endl;
868 if (has_const) {
869 f_all << "{$IF CompilerVersion < 21.0} // D2010" << endl;
870 f_all << " " << constants_class.c_str() << "_Initialize;" << endl;
871 f_all << "{$IFEND}" << endl;
872 }
873 if (register_types_) {
874 f_all << " RegisterTypeFactories;" << endl;
875 }
876 f_all << endl;
877
878 f_all << "finalization" << endl;
879 if (has_const) {
880 f_all << "{$IF CompilerVersion < 21.0} // D2010" << endl;
881 f_all << " " << constants_class.c_str() << "_Finalize;" << endl;
882 f_all << "{$IFEND}" << endl;
883 }
884 f_all << endl << endl;
885
886 f_all << "end." << endl;
887 f_all.close();
888
889 if (!typedefs_pending.empty()) {
890 pwarning(0, "%d typedefs with unresolved type references left:\n", typedefs_pending.size());
891 for (std::list<t_typedef*>::iterator iter = typedefs_pending.begin();
892 typedefs_pending.end() != iter;
893 ++iter) {
894 pwarning(0, "- %s\n", (*iter)->get_symbolic().c_str());
895 }
896 }
897}
898
899void t_delphi_generator::delphi_type_usings(ostream& out) {
900 indent_up();
901 indent(out) << "Classes, SysUtils, Generics.Collections, Thrift.Collections, Thrift.Protocol,"
902 << endl;
903 indent(out) << "Thrift.Transport;" << endl << endl;
904 indent_down();
905}
906
907void t_delphi_generator::generate_forward_declaration(t_struct* tstruct) {
908 // Forward declare struct def
909 has_forward = true;
910 pverbose("forward declaration of %s\n", type_name(tstruct).c_str());
911
912 string what = tstruct->is_xception() ? "class" : "interface";
913
914 indent_up();
915 indent(s_forward_decr) << type_name(tstruct, tstruct->is_xception(), true) << " = " << what << ";"
916 << endl;
917 indent_down();
918
919 add_defined_type(tstruct);
920}
921
922void t_delphi_generator::generate_typedef(t_typedef* ttypedef) {
923 t_type* type = ttypedef->get_type();
924
925 // write now or save for later?
926 if (!is_fully_defined_type(type)) {
927 pverbose("typedef %s: unresolved dependencies found\n", type_name(ttypedef).c_str());
928 typedefs_pending.push_back(ttypedef);
929 return;
930 }
931
932 indent_up();
933 generate_delphi_doc(s_struct, ttypedef);
934 indent(s_struct) << type_name(ttypedef) << " = ";
935
936 // commented out: the benefit is not big enough to risk breaking existing code
937 // bool container = type->is_list() || type->is_map() || type->is_set();
938 // if( ! container)
939 // s_struct << "type "; //the "type A = type B" syntax leads to E2574 with generics
940
941 s_struct << type_name(ttypedef->get_type()) << ";" << endl << endl;
942 indent_down();
943
944 add_defined_type(ttypedef);
945}
946
947bool t_delphi_generator::is_fully_defined_type(t_type* ttype) {
948 if ((NULL != ttype->get_program()) && (ttype->get_program() != program_)) {
949 t_scope* scope = ttype->get_program()->scope();
950 if (NULL != scope->get_type(ttype->get_name())) {
951 // printf("type %s found in included scope %s\n", ttype->get_name().c_str(),
952 // ttype->get_program()->get_name().c_str());
953 return true;
954 }
955 }
956
957 if (ttype->is_typedef()) {
958 return (1 == types_known[type_name(ttype)]);
959 }
960
961 if (ttype->is_base_type()) {
962 return (1 == types_known[base_type_name((t_base_type*)ttype)]);
963 } else if (ttype->is_enum()) {
964 return true; // enums are written first, before all other types
965 } else if (ttype->is_map()) {
966 t_map* tmap = (t_map*)ttype;
967 return is_fully_defined_type(tmap->get_key_type())
968 && is_fully_defined_type(tmap->get_val_type());
969 } else if (ttype->is_set()) {
970 t_set* tset = (t_set*)ttype;
971 return is_fully_defined_type(tset->get_elem_type());
972 } else if (ttype->is_list()) {
973 t_list* tlist = (t_list*)ttype;
974 return is_fully_defined_type(tlist->get_elem_type());
975 }
976
977 return (1 == types_known[type_name(ttype)]);
978}
979
980void t_delphi_generator::add_defined_type(t_type* ttype) {
981 // mark as known type
982 types_known[type_name(ttype)] = 1;
983
984 // check all pending typedefs
985 std::list<t_typedef*>::iterator iter;
986 bool more = true;
987 while (more && (!typedefs_pending.empty())) {
988 more = false;
989
990 for (iter = typedefs_pending.begin(); typedefs_pending.end() != iter; ++iter) {
991 t_typedef* ttypedef = (*iter);
992 if (is_fully_defined_type(ttypedef->get_type())) {
993 pverbose("typedef %s: all pending references are now resolved\n",
994 type_name(ttypedef).c_str());
995 typedefs_pending.erase(iter);
996 generate_typedef(ttypedef);
997 more = true;
998 break;
999 }
1000 }
1001 }
1002}
1003
1004void t_delphi_generator::init_known_types_list() {
1005 // known base types
1006 types_known[type_name(g_type_string)] = 1;
1007 types_known[type_name(g_type_binary)] = 1;
1008 types_known[type_name(g_type_bool)] = 1;
1009 types_known[type_name(g_type_i8)] = 1;
1010 types_known[type_name(g_type_i16)] = 1;
1011 types_known[type_name(g_type_i32)] = 1;
1012 types_known[type_name(g_type_i64)] = 1;
1013 types_known[type_name(g_type_double)] = 1;
1014}
1015
1016void t_delphi_generator::generate_enum(t_enum* tenum) {
1017 has_enum = true;
1018 indent_up();
1019 generate_delphi_doc(s_enum, tenum);
1020 indent(s_enum) << type_name(tenum, true, true) << " = "
1021 << "(" << endl;
1022 indent_up();
1023 vector<t_enum_value*> constants = tenum->get_constants();
1024 if (constants.empty()) {
1025 indent(s_enum) << "dummy = 0 // empty enums are not allowed";
1026 } else {
1027 vector<t_enum_value*>::iterator c_iter;
1028 for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
1029 int value = (*c_iter)->get_value();
1030 if (c_iter != constants.begin()) {
1031 s_enum << ",";
1032 s_enum << endl;
1033 }
1034 generate_delphi_doc(s_enum, *c_iter);
1035 indent(s_enum) << normalize_name((*c_iter)->get_name()) << " = " << value;
1036 }
1037 }
1038 s_enum << endl;
1039 indent_down();
1040 indent(s_enum) << ");" << endl << endl;
1041 indent_down();
1042}
1043
1044std::string t_delphi_generator::make_valid_delphi_identifier(std::string const& fromName) {
1045 std::string str = fromName;
1046 if (str.empty()) {
1047 return str;
1048 }
1049
1050 // tests rely on this
1051 assert(('A' < 'Z') && ('a' < 'z') && ('0' < '9'));
1052
1053 // if the first letter is a number, we add an additional underscore in front of it
1054 char c = str.at(0);
1055 if (('0' <= c) && (c <= '9')) {
1056 str = "_" + str;
1057 }
1058
1059 // following chars: letter, number or underscore
1060 for (size_t i = 0; i < str.size(); ++i) {
1061 c = str.at(i);
1062 if ((('A' > c) || (c > 'Z')) && (('a' > c) || (c > 'z')) && (('0' > c) || (c > '9'))
1063 && ('_' != c)) {
1064 str.replace(i, 1, "_");
1065 }
1066 }
1067
1068 return str;
1069}
1070
1071std::string t_delphi_generator::make_constants_classname() {
1072 if (constprefix_) {
1073 return make_valid_delphi_identifier("T" + program_name_ + "Constants");
1074 } else {
1075 return "TConstants"; // compatibility
1076 }
1077}
1078
1079void t_delphi_generator::generate_consts(std::vector<t_const*> consts) {
1080 if (consts.empty()) {
1081 return;
1082 }
1083
1084 has_const = true;
1085 string constants_class = make_constants_classname();
1086
1087 indent_up();
1088 indent(s_const) << constants_class.c_str() << " = class" << endl;
1089 indent(s_const) << "private" << endl;
1090 indent_up();
1091 vector<t_const*>::iterator c_iter;
1092 for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
1093 if (const_needs_var((*c_iter)->get_type())) {
1094 print_private_field(s_const,
1095 normalize_name((*c_iter)->get_name()),
1096 (*c_iter)->get_type(),
1097 (*c_iter)->get_value());
1098 }
1099 }
1100 indent_down();
1101 indent(s_const) << "public" << endl;
1102 indent_up();
1103 for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
1104 generate_delphi_doc(s_const, *c_iter);
1105 print_const_prop(s_const,
1106 normalize_name((*c_iter)->get_name()),
1107 (*c_iter)->get_type(),
1108 (*c_iter)->get_value());
1109 }
1110 indent(s_const) << "{$IF CompilerVersion >= 21.0}" << endl;
1111 indent(s_const) << "class constructor Create;" << endl;
1112 indent(s_const) << "class destructor Destroy;" << endl;
1113 indent(s_const) << "{$IFEND}" << endl;
1114 indent_down();
1115 indent(s_const) << "end;" << endl << endl;
1116 indent_down();
1117
1118 std::ostringstream vars, code;
1119
1120 indent_up_impl();
1121 for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
1122 initialize_field(vars,
1123 code,
1124 "F" + prop_name((*c_iter)->get_name()),
1125 (*c_iter)->get_type(),
1126 (*c_iter)->get_value());
1127 }
1128 indent_down_impl();
1129
1130 indent_impl(s_const_impl) << "{$IF CompilerVersion >= 21.0}" << endl;
1131 indent_impl(s_const_impl) << "class constructor " << constants_class.c_str() << ".Create;"
1132 << endl;
1133
1134 if (!vars.str().empty()) {
1135 indent_impl(s_const_impl) << "var" << endl;
1136 s_const_impl << vars.str();
1137 }
1138 indent_impl(s_const_impl) << "begin" << endl;
1139 if (!code.str().empty()) {
1140 s_const_impl << code.str();
1141 }
1142 indent_impl(s_const_impl) << "end;" << endl << endl;
1143 indent_impl(s_const_impl) << "class destructor " << constants_class.c_str() << ".Destroy;"
1144 << endl;
1145 indent_impl(s_const_impl) << "begin" << endl;
1146 indent_up_impl();
1147 for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
1148 if (const_needs_var((*c_iter)->get_type())) {
1149 finalize_field(s_const_impl,
1150 normalize_name((*c_iter)->get_name()),
1151 (*c_iter)->get_type(),
1152 (*c_iter)->get_value());
1153 }
1154 }
1155 indent_impl(s_const_impl) << "inherited;" << endl;
1156 indent_down_impl();
1157 indent_impl(s_const_impl) << "end;" << endl;
1158 indent_impl(s_const_impl) << "{$ELSE}" << endl;
1159
1160 vars.str("");
1161 code.str("");
1162
1163 indent_up_impl();
1164 for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
1165 if (const_needs_var((*c_iter)->get_type())) {
1166 initialize_field(vars,
1167 code,
1168 constants_class + ".F" + prop_name((*c_iter)->get_name()),
1169 (*c_iter)->get_type(),
1170 (*c_iter)->get_value());
1171 }
1172 }
1173 indent_down_impl();
1174
1175 indent_impl(s_const_impl) << "procedure " << constants_class.c_str() << "_Initialize;" << endl;
1176 if (!vars.str().empty()) {
1177 indent_impl(s_const_impl) << "var" << endl;
1178 s_const_impl << vars.str();
1179 }
1180 indent_impl(s_const_impl) << "begin" << endl;
1181 if (!code.str().empty()) {
1182 s_const_impl << code.str();
1183 }
1184 indent_impl(s_const_impl) << "end;" << endl << endl;
1185
1186 indent_impl(s_const_impl) << "procedure " << constants_class.c_str() << "_Finalize;" << endl;
1187 indent_impl(s_const_impl) << "begin" << endl;
1188 indent_up_impl();
1189 for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) {
1190 finalize_field(s_const_impl,
1191 normalize_name((*c_iter)->get_name()),
1192 (*c_iter)->get_type(),
1193 (*c_iter)->get_value(),
1194 constants_class);
1195 }
1196 indent_down_impl();
1197 indent_impl(s_const_impl) << "end;" << endl;
1198 indent_impl(s_const_impl) << "{$IFEND}" << endl << endl;
1199}
1200
1201void t_delphi_generator::print_const_def_value(std::ostream& vars,
1202 std::ostream& out,
1203 string name,
1204 t_type* type,
1205 t_const_value* value,
1206 string cls_nm) {
1207
1208 string cls_prefix;
1209
1210 if (cls_nm == "") {
1211 cls_prefix = "";
1212 } else {
1213 cls_prefix = cls_nm + ".";
1214 }
1215
1216 if (type->is_struct() || type->is_xception()) {
1217 const vector<t_field*>& fields = ((t_struct*)type)->get_members();
1218 vector<t_field*>::const_iterator f_iter;
1219 const map<t_const_value*, t_const_value*, t_const_value::value_compare>& val = value->get_map();
1220 map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
1221 for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
1222 t_type* field_type = NULL;
1223 for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
1224 if ((*f_iter)->get_name() == v_iter->first->get_string()) {
1225 field_type = (*f_iter)->get_type();
1226 }
1227 }
1228 if (field_type == NULL) {
1229 throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string();
1230 }
1231 string val = render_const_value(vars, out, name, field_type, v_iter->second);
1232 indent_impl(out) << cls_prefix << normalize_name(name) << "."
1233 << prop_name(v_iter->first->get_string(), type->is_xception())
1234 << " := " << val << ";" << endl;
1235 }
1236 } else if (type->is_map()) {
1237 t_type* ktype = ((t_map*)type)->get_key_type();
1238 t_type* vtype = ((t_map*)type)->get_val_type();
1239 const map<t_const_value*, t_const_value*, t_const_value::value_compare>& val = value->get_map();
1240 map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter;
1241 for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
1242 string key = render_const_value(vars, out, name, ktype, v_iter->first);
1243 string val = render_const_value(vars, out, name, vtype, v_iter->second);
1244 indent_impl(out) << cls_prefix << normalize_name(name) << "[" << key << "]"
1245 << " := " << val << ";" << endl;
1246 }
1247 } else if (type->is_list() || type->is_set()) {
1248 t_type* etype;
1249 if (type->is_list()) {
1250 etype = ((t_list*)type)->get_elem_type();
1251 } else {
1252 etype = ((t_set*)type)->get_elem_type();
1253 }
1254
1255 const vector<t_const_value*>& val = value->get_list();
1256 vector<t_const_value*>::const_iterator v_iter;
1257 for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
1258 string val = render_const_value(vars, out, name, etype, *v_iter);
1259 indent_impl(out) << cls_prefix << normalize_name(name) << ".Add(" << val << ");" << endl;
1260 }
1261 }
1262}
1263
1264void t_delphi_generator::print_private_field(std::ostream& out,
1265 string name,
1266 t_type* type,
1267 t_const_value* value) {
1268 (void)value;
1269 indent(out) << "class var F" << name << ": " << type_name(type) << ";" << endl;
1270}
1271
1272bool t_delphi_generator::const_needs_var(t_type* type) {
1273 t_type* truetype = type;
1274 while (truetype->is_typedef()) {
1275 truetype = ((t_typedef*)truetype)->get_type();
1276 }
1277 return (!truetype->is_base_type());
1278}
1279
1280void t_delphi_generator::print_const_prop(std::ostream& out,
1281 string name,
1282 t_type* type,
1283 t_const_value* value) {
1284 (void)value;
1285 if (const_needs_var(type)) {
1286 indent(out) << "class property " << name << ": " << type_name(type) << " read F" << name << ";"
1287 << endl;
1288 } else {
1289 std::ostringstream vars; // dummy
1290 string v2 = render_const_value(vars, out, name, type, value);
1291 indent(out) << "const " << name << " = " << v2 << ";" << endl;
1292 }
1293}
1294
1295void t_delphi_generator::print_const_value(std::ostream& vars,
1296 std::ostream& out,
1297 string name,
1298 t_type* type,
1299 t_const_value* value) {
1300 t_type* truetype = type;
1301 while (truetype->is_typedef()) {
1302 truetype = ((t_typedef*)truetype)->get_type();
1303 }
1304
1305 if (truetype->is_base_type()) {
1306 // already done
1307 // string v2 = render_const_value( vars, out, name, type, value);
1308 // indent_impl(out) << name << " := " << v2 << ";" << endl;
1309 } else if (truetype->is_enum()) {
1310 indent_impl(out) << name << " := " << type_name(type) << "." << value->get_identifier_name()
1311 << ";" << endl;
1312 } else {
1313 string typname;
1314 typname = type_name(truetype, true, false, type->is_xception(), type->is_xception());
1315 indent_impl(out) << name << " := " << typname << ".Create;" << endl;
1316 print_const_def_value(vars, out, name, truetype, value);
1317 }
1318}
1319
1320void t_delphi_generator::initialize_field(std::ostream& vars,
1321 std::ostream& out,
1322 string name,
1323 t_type* type,
1324 t_const_value* value) {
1325 print_const_value(vars, out, name, type, value);
1326}
1327
1328void t_delphi_generator::finalize_field(std::ostream& out,
1329 string name,
1330 t_type* type,
1331 t_const_value* value,
1332 string cls_nm) {
1333 (void)out;
1334 (void)name;
1335 (void)type;
1336 (void)value;
1337 (void)cls_nm;
1338}
1339
1340string t_delphi_generator::render_const_value(ostream& vars,
1341 ostream& out,
1342 string name,
1343 t_type* type,
1344 t_const_value* value) {
1345 (void)name;
1346
1347 t_type* truetype = type;
1348 while (truetype->is_typedef()) {
1349 truetype = ((t_typedef*)truetype)->get_type();
1350 }
1351
1352 std::ostringstream render;
1353
1354 if (truetype->is_base_type()) {
1355 t_base_type::t_base tbase = ((t_base_type*)truetype)->get_base();
1356 switch (tbase) {
1357 case t_base_type::TYPE_STRING:
1358 render << "'" << get_escaped_string(value) << "'";
1359 break;
1360 case t_base_type::TYPE_BOOL:
1361 render << ((value->get_integer() > 0) ? "True" : "False");
1362 break;
1363 case t_base_type::TYPE_I8:
1364 render << "ShortInt( " << value->get_integer() << ")";
1365 break;
1366 case t_base_type::TYPE_I16:
1367 render << "SmallInt( " << value->get_integer() << ")";
1368 break;
1369 case t_base_type::TYPE_I32:
1370 render << "LongInt( " << value->get_integer() << ")";
1371 break;
1372 case t_base_type::TYPE_I64:
1373 render << "Int64( " << value->get_integer() << ")";
1374 break;
1375 case t_base_type::TYPE_DOUBLE:
1376 if (value->get_type() == t_const_value::CV_INTEGER) {
1377 render << value->get_integer() << ".0"; // make it a double constant by adding ".0"
1378 } else {
1379 render << value->get_double();
1380 }
1381 break;
1382 default:
1383 throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
1384 }
1385 } else if (truetype->is_enum()) {
1386 render << type_name(type, false) << "." << value->get_identifier_name();
1387 } else {
1388 string t = tmp("tmp");
1389 vars << " " << t << " : " << type_name(type) << ";" << endl;
1390 print_const_value(vars, out, t, type, value);
1391 render << t;
1392 }
1393
1394 return render.str();
1395}
1396
1397void t_delphi_generator::generate_struct(t_struct* tstruct) {
1398 generate_delphi_struct(tstruct, false);
1399}
1400
1401void t_delphi_generator::generate_xception(t_struct* txception) {
1402 generate_delphi_struct(txception, true);
1403}
1404
1405void t_delphi_generator::generate_delphi_struct(t_struct* tstruct, bool is_exception) {
1406 indent_up();
1407 generate_delphi_struct_definition(s_struct, tstruct, is_exception);
1408 indent_down();
1409
1410 add_defined_type(tstruct);
1411
1412 generate_delphi_struct_impl(s_struct_impl, "", tstruct, is_exception);
1413 if (register_types_) {
1414 generate_delphi_struct_type_factory(s_type_factory_funcs, "", tstruct, is_exception);
1415 generate_delphi_struct_type_factory_registration(s_type_factory_registration,
1416 "",
1417 tstruct,
1418 is_exception);
1419 }
1420}
1421
1422void t_delphi_generator::generate_delphi_struct_impl(ostream& out,
1423 string cls_prefix,
1424 t_struct* tstruct,
1425 bool is_exception,
1426 bool is_result,
1427 bool is_x_factory) {
1428
1429 if (is_exception && (!is_x_factory)) {
1430 generate_delphi_struct_impl(out, cls_prefix, tstruct, is_exception, is_result, true);
1431 }
1432
1433 string cls_nm;
1434
1435 string exception_factory_name;
1436
1437 if (is_exception) {
1438 exception_factory_name = normalize_clsnm(tstruct->get_name(), "", true) + "Factory";
1439 }
1440
1441 if (is_exception) {
1442 cls_nm = type_name(tstruct, true, (!is_x_factory), is_x_factory, true);
1443 } else {
1444 cls_nm = type_name(tstruct, true, false);
1445 }
1446
1447 std::ostringstream vars, code;
1448
1449 const vector<t_field*>& members = tstruct->get_members();
1450 vector<t_field*>::const_iterator m_iter;
1451
1452 indent_up_impl();
1453 for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
1454 t_type* t = (*m_iter)->get_type();
1455 while (t->is_typedef()) {
1456 t = ((t_typedef*)t)->get_type();
1457 }
1458 if ((*m_iter)->get_value() != NULL) {
1459 initialize_field(vars,
1460 code,
1461 "F" + prop_name((*m_iter)->get_name(), is_exception),
1462 t,
1463 (*m_iter)->get_value());
1464 if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
1465 indent_impl(code) << "F__isset_" << prop_name((*m_iter), is_exception) << " := True;"
1466 << endl;
1467 }
1468 }
1469 }
1470 indent_down_impl();
1471
1472 indent_impl(out) << "constructor " << cls_prefix << cls_nm << "."
1473 << "Create;" << endl;
1474
1475 if (!vars.str().empty()) {
1476 out << "var" << endl;
1477 out << vars.str();
1478 }
1479
1480 indent_impl(out) << "begin" << endl;
1481 indent_up_impl();
1482 if (is_exception && (!is_x_factory)) {
1483 indent_impl(out) << "inherited Create('');" << endl;
1484 } else {
1485 indent_impl(out) << "inherited;" << endl;
1486 }
1487
1488 if (!code.str().empty()) {
1489 out << code.str();
1490 }
1491
1492 indent_down_impl();
1493 indent_impl(out) << "end;" << endl << endl;
1494
1495 if ((members.size() > 0) && is_exception && (!is_x_factory)) {
1496 indent_impl(out) << "constructor " << cls_prefix << cls_nm << "."
1497 << "Create(" << constructor_argument_list(tstruct, indent_impl()) << ");"
1498 << endl;
1499 indent_impl(out) << "begin" << endl;
1500 indent_up_impl();
1501 indent_impl(out) << "Create;" << endl;
1502 for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
1503 string propname = prop_name((*m_iter)->get_name(), is_exception);
1504 string param_name = constructor_param_name((*m_iter)->get_name());
1505 indent_impl(out) << propname << " := " << param_name << ";" << endl;
1506 }
1507 indent_impl(out) << "UpdateMessageProperty;" << endl;
1508 indent_down_impl();
1509 indent_impl(out) << "end;" << endl << endl;
1510 }
1511
1512 indent_impl(out) << "destructor " << cls_prefix << cls_nm << "."
1513 << "Destroy;" << endl;
1514 indent_impl(out) << "begin" << endl;
1515 indent_up_impl();
1516
1517 for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
1518 t_type* t = (*m_iter)->get_type();
1519 while (t->is_typedef()) {
1520 t = ((t_typedef*)t)->get_type();
1521 }
1522 finalize_field(out, prop_name(*m_iter, is_exception), t, (*m_iter)->get_value());
1523 }
1524
1525 indent_impl(out) << "inherited;" << endl;
1526 indent_down_impl();
1527 indent_impl(out) << "end;" << endl << endl;
1528
1529 if (is_exception && (!is_x_factory)) {
1530 indent_impl(out) << "function " << cls_prefix << cls_nm << "." << exception_factory_name
1531 << ": I" << exception_factory_name << ";" << endl;
1532 indent_impl(out) << "begin" << endl;
1533 indent_up_impl();
1534 indent_impl(out) << "if F" << exception_factory_name << " = nil" << endl;
1535 indent_impl(out) << "then F" << exception_factory_name << " := T" << exception_factory_name << "Impl.Create;" << endl;
1536 indent_impl(out) << endl;
1537 indent_impl(out) << "result := F" << exception_factory_name << ";" << endl;
1538 indent_down_impl();
1539 indent_impl(out) << "end;" << endl << endl;
1540 }
1541
1542 if (tstruct->is_union()) {
1543 indent_impl(out) << "procedure " << cls_prefix << cls_nm << "."
1544 << "ClearUnionValues;" << endl;
1545 indent_impl(out) << "begin" << endl;
1546 indent_up_impl();
1547 for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
1548 t_type* t = (*m_iter)->get_type();
1549 while (t->is_typedef()) {
1550 t = ((t_typedef*)t)->get_type();
1551 }
1552
1553 generate_delphi_clear_union_value(out,
1554 cls_prefix,
1555 cls_nm,
1556 t,
1557 *m_iter,
1558 "F",
1559 is_exception,
1560 tstruct->is_union(),
1561 is_x_factory,
1562 exception_factory_name);
1563 }
1564 indent_down_impl();
1565 indent_impl(out) << "end;" << endl << endl;
1566 }
1567
1568 for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
1569 t_type* t = (*m_iter)->get_type();
1570 while (t->is_typedef()) {
1571 t = ((t_typedef*)t)->get_type();
1572 }
1573 generate_delphi_property_reader_impl(out, cls_prefix, cls_nm, t, *m_iter, "F", is_exception);
1574 generate_delphi_property_writer_impl(out,
1575 cls_prefix,
1576 cls_nm,
1577 t,
1578 *m_iter,
1579 "F",
1580 is_exception,
1581 tstruct->is_union(),
1582 is_x_factory,
1583 exception_factory_name);
1584 if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
1585 generate_delphi_isset_reader_impl(out, cls_prefix, cls_nm, t, *m_iter, "F", is_exception);
1586 }
1587 }
1588
1589 if ((!is_exception) || is_x_factory) {
1590 generate_delphi_struct_reader_impl(out, cls_prefix, tstruct, is_exception);
1591 if (is_result) {
1592 generate_delphi_struct_result_writer_impl(out, cls_prefix, tstruct, is_exception);
1593 } else {
1594 generate_delphi_struct_writer_impl(out, cls_prefix, tstruct, is_exception);
1595 }
1596 }
1597 generate_delphi_struct_tostring_impl(out, cls_prefix, tstruct, is_exception, is_x_factory);
1598
1599 if (is_exception && is_x_factory) {
1600 generate_delphi_create_exception_impl(out, cls_prefix, tstruct, is_exception);
1601 }
1602}
1603
1604void t_delphi_generator::print_delphi_struct_type_factory_func(ostream& out, t_struct* tstruct) {
1605 string struct_intf_name = type_name(tstruct);
1606 out << "Create_";
1607 out << struct_intf_name;
1608 out << "_Impl";
1609}
1610
1611void t_delphi_generator::generate_delphi_struct_type_factory(ostream& out,
1612 string cls_prefix,
1613 t_struct* tstruct,
1614 bool is_exception,
1615 bool is_result,
1616 bool is_x_factory) {
1617 (void)cls_prefix;
1618 if (is_exception)
1619 return;
1620 if (is_result)
1621 return;
1622 if (is_x_factory)
1623 return;
1624
1625 string struct_intf_name = type_name(tstruct);
1626 string cls_nm = type_name(tstruct, true, false);
1627
1628 out << "function ";
1629 print_delphi_struct_type_factory_func(out, tstruct);
1630 out << ": ";
1631 out << struct_intf_name;
1632 out << ";" << endl;
1633 out << "begin" << endl;
1634 indent_up();
1635 indent(out) << "Result := " << cls_nm << ".Create;" << endl;
1636 indent_down();
1637 out << "end;" << endl << endl;
1638}
1639
1640void t_delphi_generator::generate_delphi_struct_type_factory_registration(ostream& out,
1641 string cls_prefix,
1642 t_struct* tstruct,
1643 bool is_exception,
1644 bool is_result,
1645 bool is_x_factory) {
1646 (void)cls_prefix;
1647 if (is_exception)
1648 return;
1649 if (is_result)
1650 return;
1651 if (is_x_factory)
1652 return;
1653
1654 string struct_intf_name = type_name(tstruct);
1655
1656 indent(out) << " TypeRegistry.RegisterTypeFactory<" << struct_intf_name << ">(";
1657 print_delphi_struct_type_factory_func(out, tstruct);
1658 out << ");";
1659 out << endl;
1660}
1661
1662void t_delphi_generator::generate_delphi_struct_definition(ostream& out,
1663 t_struct* tstruct,
1664 bool is_exception,
1665 bool in_class,
1666 bool is_result,
1667 bool is_x_factory) {
1668 bool is_final = (tstruct->annotations_.find("final") != tstruct->annotations_.end());
1669 string struct_intf_name;
1670 string struct_name;
1671 string isset_name;
1672 const vector<t_field*>& members = tstruct->get_members();
1673 vector<t_field*>::const_iterator m_iter;
1674
1675 string exception_factory_name = normalize_clsnm(tstruct->get_name(), "", true) + "Factory";
1676
1677 if (is_exception) {
1678 struct_intf_name = type_name(tstruct, false, false, true);
1679 } else {
1680 struct_intf_name = type_name(tstruct);
1681 }
1682
1683 if (is_exception) {
1684 struct_name = type_name(tstruct, true, (!is_x_factory), is_x_factory);
1685 } else {
1686 struct_name = type_name(tstruct, true);
1687 }
1688
1689 if ((!is_exception) || is_x_factory) {
1690
1691 generate_delphi_doc(out, tstruct);
1692 indent(out) << struct_intf_name << " = interface(IBase)" << endl;
1693 indent_up();
1694
1695 for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
1696 generate_delphi_property_reader_definition(out, *m_iter, is_exception);
1697 generate_delphi_property_writer_definition(out, *m_iter, is_exception);
1698 }
1699
1700 if (is_x_factory) {
1701 out << endl;
1702 indent(out) << "// Create Exception Object" << endl;
1703 indent(out) << "function CreateException: " << type_name(tstruct, true, true) << ";" << endl;
1704 }
1705
1706 if (members.size() > 0) {
1707 out << endl;
1708 for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
1709 generate_property(out, *m_iter, true, is_exception);
1710 }
1711 }
1712
1713 if (members.size() > 0) {
1714 out << endl;
1715 for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
1716 if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
1717 generate_delphi_isset_reader_definition(out, *m_iter, is_exception);
1718 }
1719 }
1720 }
1721
1722 if (members.size() > 0) {
1723 out << endl;
1724 for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
1725 if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
1726 isset_name = "__isset_" + prop_name(*m_iter, is_exception);
1727 indent(out) << "property " << isset_name << ": System.Boolean read Get" << isset_name << ";"
1728 << endl;
1729 }
1730 }
1731 }
1732
1733 indent_down();
1734 indent(out) << "end;" << endl << endl;
1735 }
1736
1737 generate_delphi_doc(out, tstruct);
1738 indent(out) << struct_name << " = ";
1739 if (is_final) {
1740 out << "sealed ";
1741 }
1742 out << "class(";
1743 if (is_exception && (!is_x_factory)) {
1744 out << "TException";
1745 } else {
1746 out << "TInterfacedObject, IBase, ISupportsToString, " << struct_intf_name;
1747 }
1748 out << ")" << endl;
1749
1750 if (is_exception && (!is_x_factory)) {
1751 indent(out) << "public" << endl;
1752 indent_up();
1753 indent(out) << "type" << endl;
1754 indent_up();
1755 generate_delphi_struct_definition(out, tstruct, is_exception, in_class, is_result, true);
1756 indent_down();
1757 indent_down();
1758 }
1759
1760 indent(out) << "private" << endl;
1761 indent_up();
1762
1763 if (is_exception && (!is_x_factory)) {
1764 indent(out) << "F" << exception_factory_name << " :" << struct_intf_name << ";" << endl << endl;
1765 }
1766
1767 for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
1768 indent(out) << declare_field(*m_iter, false, "F", is_exception) << endl;
1769 }
1770
1771 if (members.size() > 0) {
1772 indent(out) << endl;
1773 for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
1774 if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
1775 isset_name = "F__isset_" + prop_name(*m_iter, is_exception);
1776 indent(out) << isset_name << ": System.Boolean;" << endl;
1777 }
1778 }
1779 }
1780
1781 indent(out) << endl;
1782
1783 for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
1784 generate_delphi_property_reader_definition(out, *m_iter, is_exception);
1785 generate_delphi_property_writer_definition(out, *m_iter, is_exception);
1786 }
1787
1788 if (tstruct->is_union()) {
1789 out << endl;
1790 indent(out) << "// Clear values(for union's property setter)" << endl;
1791 indent(out) << "procedure ClearUnionValues;" << endl;
1792 }
1793
1794 if (members.size() > 0) {
1795 out << endl;
1796 for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
1797 if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
1798 isset_name = "__isset_" + prop_name(*m_iter, is_exception);
1799 indent(out) << "function Get" << isset_name << ": System.Boolean;" << endl;
1800 }
1801 }
1802 }
1803
1804 indent_down();
1805
1806 indent(out) << "public" << endl;
1807 indent_up();
1808
1809 if ((members.size() > 0) && is_exception && (!is_x_factory)) {
1810 indent(out) << "constructor Create; overload;" << endl;
1811 indent(out) << "constructor Create(" << constructor_argument_list(tstruct, indent())
1812 << "); overload;" << endl;
1813 } else {
1814 indent(out) << "constructor Create;" << endl;
1815 }
1816
1817 indent(out) << "destructor Destroy; override;" << endl;
1818
1819 out << endl;
1820 indent(out) << "function ToString: string; override;" << endl;
1821
1822 if (is_exception && (!is_x_factory)) {
1823 out << endl;
1824 indent(out) << "// Exception Factory" << endl;
1825 indent(out) << "function " << exception_factory_name << ": " << struct_intf_name << ";" << endl;
1826 }
1827
1828 if ((!is_exception) || is_x_factory) {
1829 out << endl;
1830 indent(out) << "// IBase" << endl;
1831 indent(out) << "procedure Read( const iprot: IProtocol);" << endl;
1832 indent(out) << "procedure Write( const oprot: IProtocol);" << endl;
1833 }
1834
1835 if (is_exception && is_x_factory) {
1836 out << endl;
1837 indent(out) << "// Create Exception Object" << endl;
1838 indent(out) << "function CreateException: " << type_name(tstruct, true, true) << ";" << endl;
1839 }
1840
1841 if (members.size() > 0) {
1842 out << endl;
1843 indent(out) << "// Properties" << endl;
1844 for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
1845 generate_property(out, *m_iter, true, is_exception);
1846 }
1847 }
1848
1849 if (members.size() > 0) {
1850 out << endl;
1851 indent(out) << "// isset" << endl;
1852 for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
1853 if ((*m_iter)->get_req() != t_field::T_REQUIRED) {
1854 isset_name = "__isset_" + prop_name(*m_iter, is_exception);
1855 indent(out) << "property " << isset_name << ": System.Boolean read Get" << isset_name << ";"
1856 << endl;
1857 }
1858 }
1859 }
1860
1861 indent_down();
1862 indent(out) << "end;" << endl << endl;
1863}
1864
1865void t_delphi_generator::generate_service(t_service* tservice) {
1866 indent_up();
1867 generate_delphi_doc(s_service, tservice);
1868 indent(s_service) << normalize_clsnm(service_name_, "T") << " = class" << endl;
1869 indent(s_service) << "public" << endl;
1870 indent_up();
1871 indent(s_service) << "type" << endl;
1872 generate_service_interface(tservice);
1873 generate_service_client(tservice);
1874 generate_service_server(tservice);
1875 generate_service_helpers(tservice);
1876 indent_down();
1877 indent_down();
1878 indent(s_service) << "end;" << endl;
1879 indent(s_service) << endl;
1880 indent_down();
1881}
1882
1883void t_delphi_generator::generate_service_interface(t_service* tservice) {
1884 generate_service_interface(tservice,false);
1885 if(async_) {
1886 generate_service_interface(tservice,true);
1887 }
1888}
1889
1890
1891void t_delphi_generator::generate_service_interface(t_service* tservice, bool for_async) {
1892 string extends = "";
1893 string extends_iface = "";
1894 string iface_name = for_async ? "IAsync" : "Iface";
1895
1896 indent_up();
1897
1898 generate_delphi_doc(s_service, tservice);
1899 if (tservice->get_extends() != NULL) {
1900 extends = type_name(tservice->get_extends(), true, true);
1901 extends_iface = extends + "." + iface_name;
1902 generate_delphi_doc(s_service, tservice);
1903 indent(s_service) << iface_name << " = interface(" << extends_iface << ")" << endl;
1904 } else {
1905 indent(s_service) << iface_name << " = interface" << endl;
1906 }
1907
1908 indent_up();
1909 vector<t_function*> functions = tservice->get_functions();
1910 vector<t_function*>::iterator f_iter;
1911 for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
1912 generate_delphi_doc(s_service, *f_iter);
1913 indent(s_service) << function_signature(*f_iter, for_async) << endl;
1914 }
1915 indent_down();
1916 indent(s_service) << "end;" << endl << endl;
1917
1918 indent_down();
1919}
1920
1921void t_delphi_generator::generate_service_helpers(t_service* tservice) {
1922 vector<t_function*> functions = tservice->get_functions();
1923 vector<t_function*>::iterator f_iter;
1924
1925 for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
1926 t_struct* ts = (*f_iter)->get_arglist();
1927 generate_delphi_struct_definition(s_service, ts, false, true);
1928 generate_delphi_struct_impl(s_service_impl,
1929 normalize_clsnm(service_name_, "T") + ".",
1930 ts,
1931 false);
1932 generate_function_helpers(*f_iter);
1933 }
1934}
1935
1936void t_delphi_generator::generate_service_client(t_service* tservice) {
1937 indent_up();
1938 string extends = "";
1939 string extends_client = "TInterfacedObject";
1940 string implements = async_ ? "Iface, IAsync" : "Iface";
1941
1942 generate_delphi_doc(s_service, tservice);
1943 if (tservice->get_extends() != NULL) {
1944 extends = type_name(tservice->get_extends(), true, true);
1945 extends_client = extends + ".TClient";
1946 }
1947 indent(s_service) << "TClient = class( " << extends_client << ", " << implements << ")" << endl;
1948
1949 indent(s_service) << "public" << endl;
1950 indent_up();
1951
1952 indent(s_service) << "constructor Create( prot: IProtocol); overload;" << endl;
1953
1954 indent_impl(s_service_impl) << "constructor " << normalize_clsnm(service_name_, "T")
1955 << ".TClient.Create( prot: IProtocol);" << endl;
1956 indent_impl(s_service_impl) << "begin" << endl;
1957 indent_up_impl();
1958 indent_impl(s_service_impl) << "Create( prot, prot );" << endl;
1959 indent_down_impl();
1960 indent_impl(s_service_impl) << "end;" << endl << endl;
1961
1962 indent(s_service)
1963 << "constructor Create( const iprot: IProtocol; const oprot: IProtocol); overload;" << endl;
1964
1965 indent_impl(s_service_impl) << "constructor " << normalize_clsnm(service_name_, "T")
1966 << ".TClient.Create( const iprot: IProtocol; const oprot: IProtocol);"
1967 << endl;
1968 indent_impl(s_service_impl) << "begin" << endl;
1969 indent_up_impl();
1970 indent_impl(s_service_impl) << "inherited Create;" << endl;
1971 indent_impl(s_service_impl) << "iprot_ := iprot;" << endl;
1972 indent_impl(s_service_impl) << "oprot_ := oprot;" << endl;
1973 indent_down_impl();
1974 indent_impl(s_service_impl) << "end;" << endl << endl;
1975
1976 indent_down();
1977
1978 if (extends.empty()) {
1979 indent(s_service) << "protected" << endl;
1980 indent_up();
1981 indent(s_service) << "iprot_: IProtocol;" << endl;
1982 indent(s_service) << "oprot_: IProtocol;" << endl;
1983 indent(s_service) << "seqid_: System.Integer;" << endl;
1984 indent_down();
1985
1986 indent(s_service) << "public" << endl;
1987 indent_up();
1988 indent(s_service) << "property InputProtocol: IProtocol read iprot_;" << endl;
1989 indent(s_service) << "property OutputProtocol: IProtocol read oprot_;" << endl;
1990 indent_down();
1991 }
1992
1993 vector<t_function*> functions = tservice->get_functions();
1994 vector<t_function*>::const_iterator f_iter;
1995
1996 indent(s_service) << "protected" << endl;
1997 indent_up();
1998
1999 indent(s_service) << "// Iface" << endl;
2000 for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
2001 string funname = (*f_iter)->get_name();
2002 generate_delphi_doc(s_service, *f_iter);
2003 indent(s_service) << function_signature(*f_iter, false) << endl;
2004 }
2005
2006 if( async_) {
2007 indent(s_service) << endl;
2008 indent(s_service) << "// IAsync" << endl;
2009 for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
2010 string funname = (*f_iter)->get_name();
2011 generate_delphi_doc(s_service, *f_iter);
2012 indent(s_service) << function_signature(*f_iter, true) << endl;
2013 }
2014 }
2015
2016 indent_down();
2017
2018 indent(s_service) << "public" << endl;
2019 indent_up();
2020
2021 string full_cls = normalize_clsnm(service_name_, "T") + ".TClient";
2022
2023 for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
2024 string funname = (*f_iter)->get_name();
2025
2026 vector<t_field*>::const_iterator fld_iter;
2027 t_struct* arg_struct = (*f_iter)->get_arglist();
2028 const vector<t_field*>& fields = arg_struct->get_members();
2029
2030 // one for sync only, two for async+sync
2031 int mode = async_ ? 1 : 0;
2032 while( mode >= 0) {
2033 bool for_async = (mode != 0);
2034 mode--;
2035
2036 indent_impl(s_service_impl) << function_signature(*f_iter, for_async, full_cls) << endl;
2037 indent_impl(s_service_impl) << "begin" << endl;
2038 indent_up_impl();
2039
2040 t_type* ttype = (*f_iter)->get_returntype();
2041 if( for_async) {
2042 if (is_void(ttype)) {
2043 // Delphi forces us to specify a type with IFuture<T>, so we use Integer=0 for void methods
2044 indent_impl(s_service_impl) << "result := TTask.Future<System.Integer>(function: System.Integer" << endl;
2045 } else {
2046 string rettype = type_name(ttype, false, true, false, true);
2047 indent_impl(s_service_impl) << "result := TTask.Future<" << rettype << ">(function: " << rettype << endl;
2048 }
2049 indent_impl(s_service_impl) << "begin" << endl;
2050 indent_up_impl();
2051 }
2052
2053 indent_impl(s_service_impl) << "send_" << funname << "(";
2054
2055 bool first = true;
2056 for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
2057 if (first) {
2058 first = false;
2059 } else {
2060 s_service_impl << ", ";
2061 }
2062 s_service_impl << normalize_name((*fld_iter)->get_name());
2063 }
2064 s_service_impl << ");" << endl;
2065
2066 if (!(*f_iter)->is_oneway()) {
2067 s_service_impl << indent_impl();
2068 if (!(*f_iter)->get_returntype()->is_void()) {
2069 s_service_impl << "Result := ";
2070 }
2071 s_service_impl << "recv_" << funname << "();" << endl;
2072 }
2073
2074 if( for_async) {
2075 if (is_void(ttype)) {
2076 indent_impl(s_service_impl) << "Result := 0;" << endl; // no IFuture<void> in Delphi
2077 }
2078 indent_down_impl();
2079 indent_impl(s_service_impl) << "end);" << endl;
2080 }
2081
2082 indent_down_impl();
2083 indent_impl(s_service_impl) << "end;" << endl << endl;
2084 }
2085
2086 t_function send_function(g_type_void,
2087 string("send_") + (*f_iter)->get_name(),
2088 (*f_iter)->get_arglist());
2089
2090 string argsname = (*f_iter)->get_name() + "_args";
2091 string args_clsnm = normalize_clsnm(argsname, "T");
2092 string args_intfnm = normalize_clsnm(argsname, "I");
2093
2094 string argsvar = tmp("_args");
2095 string msgvar = tmp("_msg");
2096
2097 indent(s_service) << function_signature(&send_function, false) << endl;
2098 indent_impl(s_service_impl) << function_signature(&send_function, false, full_cls) << endl;
2099 indent_impl(s_service_impl) << "var" << endl;
2100 indent_up_impl();
2101 indent_impl(s_service_impl) << argsvar << " : " << args_intfnm << ";" << endl;
2102 indent_impl(s_service_impl) << msgvar << " : Thrift.Protocol.TThriftMessage;" << endl;
2103 indent_down_impl();
2104 indent_impl(s_service_impl) << "begin" << endl;
2105 indent_up_impl();
2106
2107 indent_impl(s_service_impl) << "seqid_ := seqid_ + 1;" << endl;
2108 indent_impl(s_service_impl) << "Thrift.Protocol.Init( " << msgvar << ", '" << funname
2109 << "', " << ((*f_iter)->is_oneway() ? "TMessageType.Oneway"
2110 : "TMessageType.Call")
2111 << ", seqid_);" << endl;
2112
2113 indent_impl(s_service_impl) << "oprot_.WriteMessageBegin( " << msgvar << " );" << endl;
2114 indent_impl(s_service_impl) << argsvar << " := " << args_clsnm << "Impl.Create();" << endl;
2115
2116 for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
2117 indent_impl(s_service_impl) << argsvar << "." << prop_name(*fld_iter)
2118 << " := " << normalize_name((*fld_iter)->get_name()) << ";"
2119 << endl;
2120 }
2121 indent_impl(s_service_impl) << argsvar << ".Write(oprot_);" << endl;
2122 for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
2123 indent_impl(s_service_impl) << argsvar << "." << prop_name(*fld_iter)
2124 << " := " << empty_value((*fld_iter)->get_type()) << ";" << endl;
2125 }
2126
2127 indent_impl(s_service_impl) << "oprot_.WriteMessageEnd();" << endl;
2128 indent_impl(s_service_impl) << "oprot_.Transport.Flush();" << endl;
2129
2130 indent_down_impl();
2131 indent_impl(s_service_impl) << "end;" << endl << endl;
2132
2133 if (!(*f_iter)->is_oneway()) {
2134 string org_resultname = (*f_iter)->get_name() + "_result";
2135 string result_clsnm = normalize_clsnm(org_resultname, "T");
2136 string result_intfnm = normalize_clsnm(org_resultname, "I");
2137
2138 t_struct noargs(program_);
2139 t_function recv_function((*f_iter)->get_returntype(),
2140 string("recv_") + (*f_iter)->get_name(),
2141 &noargs,
2142 (*f_iter)->get_xceptions());
2143
2144 t_struct* xs = (*f_iter)->get_xceptions();
2145 const std::vector<t_field*>& xceptions = xs->get_members();
2146
2147 string exceptvar = tmp("_ex");
2148 string appexvar = tmp("_ax");
2149 string retvar = tmp("_ret");
2150
2151 indent(s_service) << function_signature(&recv_function, false) << endl;
2152 indent_impl(s_service_impl) << function_signature(&recv_function, false, full_cls) << endl;
2153 indent_impl(s_service_impl) << "var" << endl;
2154 indent_up_impl();
2155 indent_impl(s_service_impl) << msgvar << " : Thrift.Protocol.TThriftMessage;" << endl;
2156 if (xceptions.size() > 0) {
2157 indent_impl(s_service_impl) << exceptvar << " : Exception;" << endl;
2158 }
2159 indent_impl(s_service_impl) << appexvar << " : TApplicationException;" << endl;
2160 indent_impl(s_service_impl) << retvar << " : " << result_intfnm << ";" << endl;
2161
2162 indent_down_impl();
2163 indent_impl(s_service_impl) << "begin" << endl;
2164 indent_up_impl();
2165 indent_impl(s_service_impl) << msgvar << " := iprot_.ReadMessageBegin();" << endl;
2166 indent_impl(s_service_impl) << "if (" << msgvar << ".Type_ = TMessageType.Exception) then"
2167 << endl;
2168 indent_impl(s_service_impl) << "begin" << endl;
2169 indent_up_impl();
2170 indent_impl(s_service_impl) << appexvar << " := TApplicationException.Read(iprot_);" << endl;
2171 indent_impl(s_service_impl) << "iprot_.ReadMessageEnd();" << endl;
2172 indent_impl(s_service_impl) << "raise " << appexvar << ";" << endl;
2173 indent_down_impl();
2174 indent_impl(s_service_impl) << "end;" << endl;
2175
2176 indent_impl(s_service_impl) << retvar << " := " << result_clsnm << "Impl.Create();" << endl;
2177 indent_impl(s_service_impl) << retvar << ".Read(iprot_);" << endl;
2178 indent_impl(s_service_impl) << "iprot_.ReadMessageEnd();" << endl;
2179
2180 if (!(*f_iter)->get_returntype()->is_void()) {
2181 indent_impl(s_service_impl) << "if (" << retvar << ".__isset_success) then" << endl;
2182 indent_impl(s_service_impl) << "begin" << endl;
2183 indent_up_impl();
2184 indent_impl(s_service_impl) << "Result := " << retvar << ".Success;" << endl;
2185 t_type* type = (*f_iter)->get_returntype();
2186 if (type->is_struct() || type->is_xception() || type->is_map() || type->is_list()
2187 || type->is_set()) {
2188 indent_impl(s_service_impl) << retvar << ".Success := nil;" << endl;
2189 }
2190 indent_impl(s_service_impl) << "Exit;" << endl;
2191 indent_down_impl();
2192 indent_impl(s_service_impl) << "end;" << endl;
2193 }
2194
2195 vector<t_field*>::const_iterator x_iter;
2196 for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
2197 indent_impl(s_service_impl) << "if (" << retvar << ".__isset_" << prop_name(*x_iter)
2198 << ") then" << endl;
2199 indent_impl(s_service_impl) << "begin" << endl;
2200 indent_up_impl();
2201 indent_impl(s_service_impl) << exceptvar << " := " << retvar << "." << prop_name(*x_iter)
2202 << ".CreateException;" << endl;
2203 indent_impl(s_service_impl) << "raise " << exceptvar << ";" << endl;
2204 indent_down_impl();
2205 indent_impl(s_service_impl) << "end;" << endl;
2206 }
2207
2208 if (!(*f_iter)->get_returntype()->is_void()) {
2209 indent_impl(s_service_impl)
2210 << "raise TApplicationExceptionMissingResult.Create('"
2211 << (*f_iter)->get_name() << " failed: unknown result');" << endl;
2212 }
2213
2214 indent_down_impl();
2215 indent_impl(s_service_impl) << "end;" << endl << endl;
2216 }
2217 }
2218
2219 indent_down();
2220 indent(s_service) << "end;" << endl << endl;
2221}
2222
2223void t_delphi_generator::generate_service_server(t_service* tservice) {
2224 vector<t_function*> functions = tservice->get_functions();
2225 vector<t_function*>::iterator f_iter;
2226
2227 string extends = "";
2228 string extends_processor = "";
2229
2230 string full_cls = normalize_clsnm(service_name_, "T") + ".TProcessorImpl";
2231
2232 if (tservice->get_extends() != NULL) {
2233 extends = type_name(tservice->get_extends(), true, true);
2234 extends_processor = extends + ".TProcessorImpl";
2235 indent(s_service) << "TProcessorImpl = class(" << extends_processor << ", IProcessor)" << endl;
2236 } else {
2237 indent(s_service) << "TProcessorImpl = class( TInterfacedObject, IProcessor)" << endl;
2238 }
2239
2240 indent(s_service) << "public" << endl;
2241 indent_up();
2242 indent(s_service) << "constructor Create( iface_: Iface );" << endl;
2243 indent(s_service) << "destructor Destroy; override;" << endl;
2244 indent_down();
2245
2246 indent_impl(s_service_impl) << "constructor " << full_cls << ".Create( iface_: Iface );" << endl;
2247 indent_impl(s_service_impl) << "begin" << endl;
2248 indent_up_impl();
2249 if (tservice->get_extends() != NULL) {
2250 indent_impl(s_service_impl) << "inherited Create( iface_);" << endl;
2251 } else {
2252 indent_impl(s_service_impl) << "inherited Create;" << endl;
2253 }
2254 indent_impl(s_service_impl) << "Self.iface_ := iface_;" << endl;
2255 if (tservice->get_extends() != NULL) {
2256 indent_impl(s_service_impl) << "ASSERT( processMap_ <> nil); // inherited" << endl;
2257 } else {
2258 indent_impl(s_service_impl)
2259 << "processMap_ := TThriftDictionaryImpl<string, TProcessFunction>.Create;" << endl;
2260 }
2261
2262 for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
2263 indent_impl(s_service_impl) << "processMap_.AddOrSetValue( '" << (*f_iter)->get_name() << "', "
2264 << (*f_iter)->get_name() << "_Process);" << endl;
2265 }
2266 indent_down_impl();
2267 indent_impl(s_service_impl) << "end;" << endl << endl;
2268
2269 indent_impl(s_service_impl) << "destructor " << full_cls << ".Destroy;" << endl;
2270 indent_impl(s_service_impl) << "begin" << endl;
2271 indent_up_impl();
2272 indent_impl(s_service_impl) << "inherited;" << endl;
2273 indent_down_impl();
2274 indent_impl(s_service_impl) << "end;" << endl << endl;
2275
2276 indent(s_service) << "private" << endl;
2277 indent_up();
2278 indent(s_service) << "iface_: Iface;" << endl;
2279 indent_down();
2280
2281 if (tservice->get_extends() == NULL) {
2282 indent(s_service) << "protected" << endl;
2283 indent_up();
2284 indent(s_service) << "type" << endl;
2285 indent_up();
2286 indent(s_service) << "TProcessFunction = reference to procedure( seqid: System.Integer; const iprot: "
2287 "IProtocol; const oprot: IProtocol"
2288 << (events_ ? "; const events : IRequestEvents" : "") << ");" << endl;
2289 indent_down();
2290 indent_down();
2291 indent(s_service) << "protected" << endl;
2292 indent_up();
2293 indent(s_service) << "processMap_: IThriftDictionary<string, TProcessFunction>;" << endl;
2294 indent_down();
2295 }
2296
2297 indent(s_service) << "public" << endl;
2298 indent_up();
2299 if (extends.empty()) {
2300 indent(s_service) << "function Process( const iprot: IProtocol; const oprot: IProtocol; const "
2301 "events : IProcessorEvents): System.Boolean;" << endl;
2302 } else {
2303 indent(s_service) << "function Process( const iprot: IProtocol; const oprot: IProtocol; const "
2304 "events : IProcessorEvents): System.Boolean; reintroduce;" << endl;
2305 }
2306
2307 indent_impl(s_service_impl) << "function " << full_cls << ".Process( const iprot: IProtocol; "
2308 "const oprot: IProtocol; const events "
2309 ": IProcessorEvents): System.Boolean;" << endl;
2310 ;
2311 indent_impl(s_service_impl) << "var" << endl;
2312 indent_up_impl();
2313 indent_impl(s_service_impl) << "msg : Thrift.Protocol.TThriftMessage;" << endl;
2314 indent_impl(s_service_impl) << "fn : TProcessFunction;" << endl;
2315 indent_impl(s_service_impl) << "x : TApplicationException;" << endl;
2316 if (events_) {
2317 indent_impl(s_service_impl) << "context : IRequestEvents;" << endl;
2318 }
2319 indent_down_impl();
2320 indent_impl(s_service_impl) << "begin" << endl;
2321 indent_up_impl();
2322 indent_impl(s_service_impl) << "try" << endl;
2323 indent_up_impl();
2324 indent_impl(s_service_impl) << "msg := iprot.ReadMessageBegin();" << endl;
2325 indent_impl(s_service_impl) << "fn := nil;" << endl;
2326 indent_impl(s_service_impl) << "if not processMap_.TryGetValue(msg.Name, fn)" << endl;
2327 indent_impl(s_service_impl) << "or not Assigned(fn) then" << endl;
2328 indent_impl(s_service_impl) << "begin" << endl;
2329 indent_up_impl();
2330 indent_impl(s_service_impl) << "TProtocolUtil.Skip(iprot, TType.Struct);" << endl;
2331 indent_impl(s_service_impl) << "iprot.ReadMessageEnd();" << endl;
2332 indent_impl(s_service_impl) << "x := "
2333 "TApplicationExceptionUnknownMethod.Create("
2334 "'Invalid method name: ''' + msg.Name + '''');" << endl;
2335 indent_impl(s_service_impl)
2336 << "Thrift.Protocol.Init( msg, msg.Name, TMessageType.Exception, msg.SeqID);"
2337 << endl;
2338 indent_impl(s_service_impl) << "oprot.WriteMessageBegin( msg);" << endl;
2339 indent_impl(s_service_impl) << "x.Write(oprot);" << endl;
2340 indent_impl(s_service_impl) << "oprot.WriteMessageEnd();" << endl;
2341 indent_impl(s_service_impl) << "oprot.Transport.Flush();" << endl;
2342 indent_impl(s_service_impl) << "Result := True;" << endl;
2343 indent_impl(s_service_impl) << "Exit;" << endl;
2344 indent_down_impl();
2345 indent_impl(s_service_impl) << "end;" << endl;
2346 if (events_) {
2347 indent_impl(s_service_impl) << "if events <> nil" << endl;
2348 indent_impl(s_service_impl) << "then context := events.CreateRequestContext(msg.Name)" << endl;
2349 indent_impl(s_service_impl) << "else context := nil;" << endl;
2350 indent_impl(s_service_impl) << "try" << endl;
2351 indent_up_impl();
2352 indent_impl(s_service_impl) << "fn(msg.SeqID, iprot, oprot, context);" << endl;
2353 indent_down_impl();
2354 indent_impl(s_service_impl) << "finally" << endl;
2355 indent_up_impl();
2356 indent_impl(s_service_impl) << "if context <> nil then begin" << endl;
2357 indent_up_impl();
2358 indent_impl(s_service_impl) << "context.CleanupContext;" << endl;
2359 indent_impl(s_service_impl) << "context := nil;" << endl;
2360 indent_down_impl();
2361 indent_impl(s_service_impl) << "end;" << endl;
2362 indent_down_impl();
2363 indent_impl(s_service_impl) << "end;" << endl;
2364 } else {
2365 indent_impl(s_service_impl) << "fn(msg.SeqID, iprot, oprot);" << endl;
2366 }
2367 indent_down_impl();
2368 indent_impl(s_service_impl) << "except" << endl;
2369 indent_up_impl();
2370 indent_impl(s_service_impl) << "on TTransportExceptionTimedOut do begin" << endl;
2371 indent_up_impl();
2372 indent_impl(s_service_impl) << "Result := True;" << endl;
2373 indent_impl(s_service_impl) << "Exit;" << endl;
2374 indent_down_impl();
2375 indent_impl(s_service_impl) << "end;" << endl;
2376 indent_impl(s_service_impl) << "else begin" << endl;
2377 indent_up_impl();
2378 indent_impl(s_service_impl) << "Result := False;" << endl;
2379 indent_impl(s_service_impl) << "Exit;" << endl;
2380 indent_down_impl();
2381 indent_impl(s_service_impl) << "end;" << endl;
2382 indent_down_impl();
2383 indent_impl(s_service_impl) << "end;" << endl;
2384 indent_impl(s_service_impl) << "Result := True;" << endl;
2385 indent_down_impl();
2386 indent_impl(s_service_impl) << "end;" << endl << endl;
2387
2388 for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
2389 generate_process_function(tservice, *f_iter);
2390 }
2391
2392 indent_down();
2393 indent(s_service) << "end;" << endl << endl;
2394}
2395
2396void t_delphi_generator::generate_function_helpers(t_function* tfunction) {
2397 if (tfunction->is_oneway()) {
2398 return;
2399 }
2400
2401 t_struct result(program_, tfunction->get_name() + "_result");
2402 t_field success(tfunction->get_returntype(), "Success", 0);
2403 if (!tfunction->get_returntype()->is_void()) {
2404 result.append(&success);
2405 }
2406
2407 t_struct* xs = tfunction->get_xceptions();
2408 const vector<t_field*>& fields = xs->get_members();
2409 vector<t_field*>::const_iterator f_iter;
2410 for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
2411 result.append(*f_iter);
2412 }
2413
2414 generate_delphi_struct_definition(s_service, &result, false, true, true);
2415 generate_delphi_struct_impl(s_service_impl,
2416 normalize_clsnm(service_name_, "T") + ".",
2417 &result,
2418 false);
2419}
2420
2421void t_delphi_generator::generate_process_function(t_service* tservice, t_function* tfunction) {
2422 (void)tservice;
2423 string funcname = tfunction->get_name();
2424 string full_cls = normalize_clsnm(service_name_, "T") + ".TProcessorImpl";
2425
2426 string org_argsname = funcname + "_args";
2427 string args_clsnm = normalize_clsnm(org_argsname, "T");
2428 string args_intfnm = normalize_clsnm(org_argsname, "I");
2429
2430 string org_resultname = funcname + "_result";
2431 string result_clsnm = normalize_clsnm(org_resultname, "T");
2432 string result_intfnm = normalize_clsnm(org_resultname, "I");
2433
2434 indent(s_service) << "procedure " << funcname
2435 << "_Process( seqid: System.Integer; const iprot: IProtocol; const oprot: IProtocol"
2436 << (events_ ? "; const events : IRequestEvents" : "") << ");" << endl;
2437
2438 if (tfunction->is_oneway()) {
2439 indent_impl(s_service_impl) << "// one way processor" << endl;
2440 } else {
2441 indent_impl(s_service_impl) << "// both way processor" << endl;
2442 }
2443
2444 indent_impl(s_service_impl)
2445 << "procedure " << full_cls << "." << funcname
2446 << "_Process( seqid: System.Integer; const iprot: IProtocol; const oprot: IProtocol"
2447 << (events_ ? "; const events : IRequestEvents" : "") << ");" << endl;
2448 indent_impl(s_service_impl) << "var" << endl;
2449 indent_up_impl();
2450 indent_impl(s_service_impl) << "args: " << args_intfnm << ";" << endl;
2451 if (!tfunction->is_oneway()) {
2452 indent_impl(s_service_impl) << "msg: Thrift.Protocol.TThriftMessage;" << endl;
2453 indent_impl(s_service_impl) << "ret: " << result_intfnm << ";" << endl;
2454 indent_impl(s_service_impl) << "appx : TApplicationException;" << endl;
2455 }
2456
2457 indent_down_impl();
2458 indent_impl(s_service_impl) << "begin" << endl;
2459 indent_up_impl();
2460
2461 if (events_) {
2462 indent_impl(s_service_impl) << "if events <> nil then events.PreRead;" << endl;
2463 }
2464 indent_impl(s_service_impl) << "args := " << args_clsnm << "Impl.Create;" << endl;
2465 indent_impl(s_service_impl) << "args.Read(iprot);" << endl;
2466 indent_impl(s_service_impl) << "iprot.ReadMessageEnd();" << endl;
2467 if (events_) {
2468 indent_impl(s_service_impl) << "if events <> nil then events.PostRead;" << endl;
2469 }
2470
2471 t_struct* xs = tfunction->get_xceptions();
2472 const std::vector<t_field*>& xceptions = xs->get_members();
2473 vector<t_field*>::const_iterator x_iter;
2474
2475 if (!tfunction->is_oneway()) {
2476 indent_impl(s_service_impl) << "ret := " << result_clsnm << "Impl.Create;" << endl;
2477 }
2478
2479 indent_impl(s_service_impl) << "try" << endl;
2480 indent_up_impl();
2481
2482 t_struct* arg_struct = tfunction->get_arglist();
2483 const std::vector<t_field*>& fields = arg_struct->get_members();
2484 vector<t_field*>::const_iterator f_iter;
2485
2486 s_service_impl << indent_impl();
2487 if (!tfunction->is_oneway() && !tfunction->get_returntype()->is_void()) {
2488 s_service_impl << "ret.Success := ";
2489 }
2490 s_service_impl << "iface_." << normalize_name(tfunction->get_name(), true) << "(";
2491 bool first = true;
2492 for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
2493 if (first) {
2494 first = false;
2495 } else {
2496 s_service_impl << ", ";
2497 }
2498 s_service_impl << "args." << prop_name(*f_iter);
2499 }
2500 s_service_impl << ");" << endl;
2501
2502 for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
2503 indent_impl(s_service_impl) << "args." << prop_name(*f_iter)
2504 << " := " << empty_value((*f_iter)->get_type()) << ";" << endl;
2505 }
2506
2507 indent_down_impl();
2508 indent_impl(s_service_impl) << "except" << endl;
2509 indent_up_impl();
2510
2511 for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
2512 indent_impl(s_service_impl) << "on E: " << type_name((*x_iter)->get_type(), true, true)
2513 << " do begin" << endl;
2514 indent_up_impl();
2515 if (!tfunction->is_oneway()) {
2516 string factory_name = normalize_clsnm((*x_iter)->get_type()->get_name(), "", true)
2517 + "Factory";
2518 indent_impl(s_service_impl) << "ret." << prop_name(*x_iter) << " := E." << factory_name << ";"
2519 << endl;
2520 }
2521 indent_down_impl();
2522 indent_impl(s_service_impl) << "end;" << endl;
2523 }
2524
2525 indent_impl(s_service_impl) << "on E: Exception do begin" << endl;
2526 indent_up_impl();
2527 if(events_) {
2528 indent_impl(s_service_impl) << "if events <> nil then events.UnhandledError(E);" << endl;
2529 }
2530 if (!tfunction->is_oneway()) {
2531 indent_impl(s_service_impl) << "appx := TApplicationExceptionInternalError.Create(E.Message);"
2532 << endl;
2533 indent_impl(s_service_impl) << "try" << endl;
2534 indent_up_impl();
2535 if(events_) {
2536 indent_impl(s_service_impl) << "if events <> nil then events.PreWrite;" << endl;
2537 }
2538 indent_impl(s_service_impl) << "Thrift.Protocol.Init( msg, '"
2539 << tfunction->get_name() << "', TMessageType.Exception, seqid);"
2540 << endl;
2541 indent_impl(s_service_impl) << "oprot.WriteMessageBegin( msg);" << endl;
2542 indent_impl(s_service_impl) << "appx.Write(oprot);" << endl;
2543 indent_impl(s_service_impl) << "oprot.WriteMessageEnd();" << endl;
2544 indent_impl(s_service_impl) << "oprot.Transport.Flush();" << endl;
2545 if(events_) {
2546 indent_impl(s_service_impl) << "if events <> nil then events.PostWrite;" << endl;
2547 }
2548 indent_impl(s_service_impl) << "Exit;" << endl;
2549 indent_down_impl();
2550 indent_impl(s_service_impl) << "finally" << endl;
2551 indent_up_impl();
2552 indent_impl(s_service_impl) << "appx.Free;" << endl;
2553 indent_down_impl();
2554 indent_impl(s_service_impl) << "end;" << endl;
2555 }
2556 indent_down_impl();
2557 indent_impl(s_service_impl) << "end;" << endl;
2558
2559 indent_down_impl();
2560 indent_impl(s_service_impl) << "end;" << endl;
2561
2562 if (!tfunction->is_oneway()) {
2563 if (events_) {
2564 indent_impl(s_service_impl) << "if events <> nil then events.PreWrite;" << endl;
2565 }
2566 indent_impl(s_service_impl) << "Thrift.Protocol.Init( msg, '"
2567 << tfunction->get_name() << "', TMessageType.Reply, seqid); "
2568 << endl;
2569 indent_impl(s_service_impl) << "oprot.WriteMessageBegin( msg); " << endl;
2570 indent_impl(s_service_impl) << "ret.Write(oprot);" << endl;
2571 indent_impl(s_service_impl) << "oprot.WriteMessageEnd();" << endl;
2572 indent_impl(s_service_impl) << "oprot.Transport.Flush();" << endl;
2573 if (events_) {
2574 indent_impl(s_service_impl) << "if events <> nil then events.PostWrite;" << endl;
2575 }
2576 } else if (events_) {
2577 indent_impl(s_service_impl) << "if events <> nil then events.OnewayComplete;" << endl;
2578 }
2579
2580 indent_down_impl();
2581 indent_impl(s_service_impl) << "end;" << endl << endl;
2582}
2583
2584void t_delphi_generator::generate_deserialize_field(ostream& out,
2585 bool is_xception,
2586 t_field* tfield,
2587 string prefix,
2588 ostream& local_vars) {
2589 t_type* type = tfield->get_type();
2590 while (type->is_typedef()) {
2591 type = ((t_typedef*)type)->get_type();
2592 }
2593
2594 if (type->is_void()) {
2595 throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name();
2596 }
2597
2598 string name = prefix + prop_name(tfield, is_xception);
2599
2600 if (type->is_struct() || type->is_xception()) {
2601 generate_deserialize_struct(out, (t_struct*)type, name, "");
2602 } else if (type->is_container()) {
2603 generate_deserialize_container(out, is_xception, type, name, local_vars);
2604 } else if (type->is_base_type() || type->is_enum()) {
2605 indent_impl(out) << name << " := ";
2606
2607 if (type->is_enum()) {
2608 out << type_name(type, false) << "(";
2609 }
2610
2611 out << "iprot.";
2612
2613 if (type->is_base_type()) {
2614 t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
2615 switch (tbase) {
2616 case t_base_type::TYPE_VOID:
2617 throw "compiler error: cannot serialize void field in a struct: " + name;
2618 break;
2619 case t_base_type::TYPE_STRING:
2620 if (type->is_binary()) {
2621 if (ansistr_binary_) {
2622 out << "ReadAnsiString();";
2623 } else {
2624 out << "ReadBinary();";
2625 }
2626 } else {
2627 out << "ReadString();";
2628 }
2629 break;
2630 case t_base_type::TYPE_BOOL:
2631 out << "ReadBool();";
2632 break;
2633 case t_base_type::TYPE_I8:
2634 out << "ReadByte();";
2635 break;
2636 case t_base_type::TYPE_I16:
2637 out << "ReadI16();";
2638 break;
2639 case t_base_type::TYPE_I32:
2640 out << "ReadI32();";
2641 break;
2642 case t_base_type::TYPE_I64:
2643 out << "ReadI64();";
2644 break;
2645 case t_base_type::TYPE_DOUBLE:
2646 out << "ReadDouble();";
2647 break;
2648 default:
2649 throw "compiler error: no Delphi name for base type " + t_base_type::t_base_name(tbase);
2650 }
2651 } else if (type->is_enum()) {
2652 out << "ReadI32()";
2653 out << ");";
2654 }
2655 out << endl;
2656 } else {
2657 printf("DO NOT KNOW HOW TO DESERIALIZE FIELD '%s' TYPE '%s'\n",
2658 tfield->get_name().c_str(),
2659 type_name(type).c_str());
2660 }
2661}
2662
2663void t_delphi_generator::generate_deserialize_struct(ostream& out,
2664 t_struct* tstruct,
2665 string name,
2666 string prefix) {
2667 string typ_name;
2668
2669 if (tstruct->is_xception()) {
2670 typ_name = type_name(tstruct, true, false, true, true);
2671 } else {
2672 typ_name = type_name(tstruct, true, false);
2673 }
2674
2675 indent_impl(out) << prefix << name << " := " << typ_name << ".Create;" << endl;
2676 indent_impl(out) << prefix << name << ".Read(iprot);" << endl;
2677}
2678
2679void t_delphi_generator::generate_deserialize_container(ostream& out,
2680 bool is_xception,
2681 t_type* ttype,
2682 string name,
2683 std::ostream& local_vars) {
2684
2685 string obj;
2686 string counter;
2687 string local_var;
2688
2689 if (ttype->is_map()) {
2690 obj = tmp("_map");
2691 } else if (ttype->is_set()) {
2692 obj = tmp("_set");
2693 } else if (ttype->is_list()) {
2694 obj = tmp("_list");
2695 }
2696
2697 if (ttype->is_map()) {
2698 local_var = obj + ": TThriftMap;";
2699 } else if (ttype->is_set()) {
2700 local_var = obj + ": TThriftSet;";
2701 } else if (ttype->is_list()) {
2702 local_var = obj + ": TThriftList;";
2703 }
2704 local_vars << " " << local_var << endl;
2705 counter = tmp("_i");
2706 local_var = counter + ": System.Integer;";
2707 local_vars << " " << local_var << endl;
2708
2709 indent_impl(out) << name << " := " << type_name(ttype, true) << ".Create;" << endl;
2710
2711 if (ttype->is_map()) {
2712 indent_impl(out) << obj << " := iprot.ReadMapBegin();" << endl;
2713 } else if (ttype->is_set()) {
2714 indent_impl(out) << obj << " := iprot.ReadSetBegin();" << endl;
2715 } else if (ttype->is_list()) {
2716 indent_impl(out) << obj << " := iprot.ReadListBegin();" << endl;
2717 }
2718
2719 indent_impl(out) << "for " << counter << " := 0 to " << obj << ".Count - 1 do" << endl;
2720 indent_impl(out) << "begin" << endl;
2721 indent_up_impl();
2722 if (ttype->is_map()) {
2723 generate_deserialize_map_element(out, is_xception, (t_map*)ttype, name, local_vars);
2724 } else if (ttype->is_set()) {
2725 generate_deserialize_set_element(out, is_xception, (t_set*)ttype, name, local_vars);
2726 } else if (ttype->is_list()) {
2727 generate_deserialize_list_element(out, is_xception, (t_list*)ttype, name, local_vars);
2728 }
2729 indent_down_impl();
2730 indent_impl(out) << "end;" << endl;
2731
2732 if (ttype->is_map()) {
2733 indent_impl(out) << "iprot.ReadMapEnd();" << endl;
2734 } else if (ttype->is_set()) {
2735 indent_impl(out) << "iprot.ReadSetEnd();" << endl;
2736 } else if (ttype->is_list()) {
2737 indent_impl(out) << "iprot.ReadListEnd();" << endl;
2738 }
2739}
2740
2741void t_delphi_generator::generate_deserialize_map_element(ostream& out,
2742 bool is_xception,
2743 t_map* tmap,
2744 string prefix,
2745 ostream& local_vars) {
2746
2747 string key = tmp("_key");
2748 string val = tmp("_val");
2749 string local_var;
2750
2751 t_field fkey(tmap->get_key_type(), key);
2752 t_field fval(tmap->get_val_type(), val);
2753
2754 local_vars << " " << declare_field(&fkey) << endl;
2755 local_vars << " " << declare_field(&fval) << endl;
2756
2757 generate_deserialize_field(out, is_xception, &fkey, "", local_vars);
2758 generate_deserialize_field(out, is_xception, &fval, "", local_vars);
2759
2760 indent_impl(out) << prefix << ".AddOrSetValue( " << key << ", " << val << ");" << endl;
2761}
2762
2763void t_delphi_generator::generate_deserialize_set_element(ostream& out,
2764 bool is_xception,
2765 t_set* tset,
2766 string prefix,
2767 ostream& local_vars) {
2768 string elem = tmp("_elem");
2769 t_field felem(tset->get_elem_type(), elem);
2770 local_vars << " " << declare_field(&felem) << endl;
2771 generate_deserialize_field(out, is_xception, &felem, "", local_vars);
2772 indent_impl(out) << prefix << ".Add(" << elem << ");" << endl;
2773}
2774
2775void t_delphi_generator::generate_deserialize_list_element(ostream& out,
2776 bool is_xception,
2777 t_list* tlist,
2778 string prefix,
2779 ostream& local_vars) {
2780 string elem = tmp("_elem");
2781 t_field felem(tlist->get_elem_type(), elem);
2782 local_vars << " " << declare_field(&felem) << endl;
2783 generate_deserialize_field(out, is_xception, &felem, "", local_vars);
2784 indent_impl(out) << prefix << ".Add(" << elem << ");" << endl;
2785}
2786
2787void t_delphi_generator::generate_serialize_field(ostream& out,
2788 bool is_xception,
2789 t_field* tfield,
2790 string prefix,
2791 ostream& local_vars) {
2792 (void)local_vars;
2793
2794 t_type* type = tfield->get_type();
2795 while (type->is_typedef()) {
2796 type = ((t_typedef*)type)->get_type();
2797 }
2798
2799 string name = prefix + prop_name(tfield, is_xception);
2800
2801 if (type->is_void()) {
2802 throw "CANNOT GENERATE SERIALIZE CODE FOR void TYPE: " + name;
2803 }
2804
2805 if (type->is_struct() || type->is_xception()) {
2806 generate_serialize_struct(out, (t_struct*)type, name, local_vars);
2807 } else if (type->is_container()) {
2808 generate_serialize_container(out, is_xception, type, name, local_vars);
2809 } else if (type->is_base_type() || type->is_enum()) {
2810
2811 indent_impl(out) << "oprot.";
2812
2813 if (type->is_base_type()) {
2814 t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
2815
2816 switch (tbase) {
2817 case t_base_type::TYPE_VOID:
2818 throw "compiler error: cannot serialize void field in a struct: " + name;
2819 break;
2820 case t_base_type::TYPE_STRING:
2821 if (type->is_binary()) {
2822 if (ansistr_binary_) {
2823 out << "WriteAnsiString(";
2824 } else {
2825 out << "WriteBinary(";
2826 }
2827 } else {
2828 out << "WriteString(";
2829 }
2830 out << name << ");";
2831 break;
2832 case t_base_type::TYPE_BOOL:
2833 out << "WriteBool(" << name << ");";
2834 break;
2835 case t_base_type::TYPE_I8:
2836 out << "WriteByte(" << name << ");";
2837 break;
2838 case t_base_type::TYPE_I16:
2839 out << "WriteI16(" << name << ");";
2840 break;
2841 case t_base_type::TYPE_I32:
2842 out << "WriteI32(" << name << ");";
2843 break;
2844 case t_base_type::TYPE_I64:
2845 out << "WriteI64(" << name << ");";
2846 break;
2847 case t_base_type::TYPE_DOUBLE:
2848 out << "WriteDouble(" << name << ");";
2849 break;
2850 default:
2851 throw "compiler error: no Delphi name for base type " + t_base_type::t_base_name(tbase);
2852 }
2853 } else if (type->is_enum()) {
2854 out << "WriteI32(System.Integer(" << name << "));";
2855 }
2856 out << endl;
2857 } else {
2858 printf("DO NOT KNOW HOW TO SERIALIZE '%s%s' TYPE '%s'\n",
2859 prefix.c_str(),
2860 tfield->get_name().c_str(),
2861 type_name(type).c_str());
2862 }
2863}
2864
2865void t_delphi_generator::generate_serialize_struct(ostream& out,
2866 t_struct* tstruct,
2867 string prefix,
2868 ostream& local_vars) {
2869 (void)local_vars;
2870 (void)tstruct;
2871 out << indent_impl() << prefix << ".Write(oprot);" << endl;
2872}
2873
2874void t_delphi_generator::generate_serialize_container(ostream& out,
2875 bool is_xception,
2876 t_type* ttype,
2877 string prefix,
2878 ostream& local_vars) {
2879 string obj;
2880 if (ttype->is_map()) {
2881 obj = tmp("map");
2882 local_vars << " " << obj << " : TThriftMap;" << endl;
2883 indent_impl(out) << "Thrift.Protocol.Init( " << obj << ", "
2884 << type_to_enum(((t_map*)ttype)->get_key_type()) << ", "
2885 << type_to_enum(((t_map*)ttype)->get_val_type()) << ", " << prefix
2886 << ".Count);" << endl;
2887 indent_impl(out) << "oprot.WriteMapBegin( " << obj << ");" << endl;
2888 } else if (ttype->is_set()) {
2889 obj = tmp("set_");
2890 local_vars << " " << obj << " : TThriftSet;" << endl;
2891 indent_impl(out) << "Thrift.Protocol.Init( " << obj << ", "
2892 << type_to_enum(((t_set*)ttype)->get_elem_type()) << ", " << prefix
2893 << ".Count);" << endl;
2894 indent_impl(out) << "oprot.WriteSetBegin( " << obj << ");" << endl;
2895 } else if (ttype->is_list()) {
2896 obj = tmp("list_");
2897 local_vars << " " << obj << " : TThriftList;" << endl;
2898 indent_impl(out) << "Thrift.Protocol.Init( " << obj << ", "
2899 << type_to_enum(((t_list*)ttype)->get_elem_type()) << ", " << prefix
2900 << ".Count);" << endl;
2901 indent_impl(out) << "oprot.WriteListBegin( " << obj << ");" << endl;
2902 }
2903
2904 string iter = tmp("_iter");
2905 if (ttype->is_map()) {
2906 local_vars << " " << iter << ": " << type_name(((t_map*)ttype)->get_key_type()) << ";" << endl;
2907 indent_impl(out) << "for " << iter << " in " << prefix << ".Keys do" << endl;
2908 indent_impl(out) << "begin" << endl;
2909 indent_up_impl();
2910 } else if (ttype->is_set()) {
2911 local_vars << " " << iter << ": " << type_name(((t_set*)ttype)->get_elem_type()) << ";"
2912 << endl;
2913 indent_impl(out) << "for " << iter << " in " << prefix << " do" << endl;
2914 indent_impl(out) << "begin" << endl;
2915 indent_up_impl();
2916 } else if (ttype->is_list()) {
2917 local_vars << " " << iter << ": " << type_name(((t_list*)ttype)->get_elem_type()) << ";"
2918 << endl;
2919 indent_impl(out) << "for " << iter << " in " << prefix << " do" << endl;
2920 indent_impl(out) << "begin" << endl;
2921 indent_up_impl();
2922 }
2923
2924 if (ttype->is_map()) {
2925 generate_serialize_map_element(out, is_xception, (t_map*)ttype, iter, prefix, local_vars);
2926 } else if (ttype->is_set()) {
2927 generate_serialize_set_element(out, is_xception, (t_set*)ttype, iter, local_vars);
2928 } else if (ttype->is_list()) {
2929 generate_serialize_list_element(out, is_xception, (t_list*)ttype, iter, local_vars);
2930 }
2931
2932 indent_down_impl();
2933 indent_impl(out) << "end;" << endl;
2934
2935 if (ttype->is_map()) {
2936 indent_impl(out) << "oprot.WriteMapEnd();" << endl;
2937 } else if (ttype->is_set()) {
2938 indent_impl(out) << "oprot.WriteSetEnd();" << endl;
2939 } else if (ttype->is_list()) {
2940 indent_impl(out) << "oprot.WriteListEnd();" << endl;
2941 }
2942}
2943
2944void t_delphi_generator::generate_serialize_map_element(ostream& out,
2945 bool is_xception,
2946 t_map* tmap,
2947 string iter,
2948 string map,
2949 ostream& local_vars) {
2950 t_field kfield(tmap->get_key_type(), iter);
2951 generate_serialize_field(out, is_xception, &kfield, "", local_vars);
2952 t_field vfield(tmap->get_val_type(), map + "[" + iter + "]");
2953 generate_serialize_field(out, is_xception, &vfield, "", local_vars);
2954}
2955
2956void t_delphi_generator::generate_serialize_set_element(ostream& out,
2957 bool is_xception,
2958 t_set* tset,
2959 string iter,
2960 ostream& local_vars) {
2961 t_field efield(tset->get_elem_type(), iter);
2962 generate_serialize_field(out, is_xception, &efield, "", local_vars);
2963}
2964
2965void t_delphi_generator::generate_serialize_list_element(ostream& out,
2966 bool is_xception,
2967 t_list* tlist,
2968 string iter,
2969 ostream& local_vars) {
2970 t_field efield(tlist->get_elem_type(), iter);
2971 generate_serialize_field(out, is_xception, &efield, "", local_vars);
2972}
2973
2974void t_delphi_generator::generate_property(ostream& out,
2975 t_field* tfield,
2976 bool isPublic,
2977 bool is_xception) {
2978 generate_delphi_property(out, is_xception, tfield, isPublic, "Get");
2979}
2980
2981void t_delphi_generator::generate_delphi_property(ostream& out,
2982 bool struct_is_xception,
2983 t_field* tfield,
2984 bool isPublic,
2985 std::string fieldPrefix) {
2986 (void)isPublic;
2987
2988 t_type* ftype = tfield->get_type();
2989 bool is_xception = ftype->is_xception();
2990 generate_delphi_doc(out, tfield);
2991 indent(out) << "property " << prop_name(tfield, struct_is_xception) << ": "
2992 << type_name(ftype, false, true, is_xception, true) << " read "
2993 << fieldPrefix + prop_name(tfield, struct_is_xception) << " write Set"
2994 << prop_name(tfield, struct_is_xception) << ";" << endl;
2995}
2996
2997std::string t_delphi_generator::prop_name(t_field* tfield, bool is_xception) {
2998 return prop_name(tfield->get_name(), is_xception);
2999}
3000
3001std::string t_delphi_generator::prop_name(string name, bool is_xception) {
3002 string ret = name;
3003 ret[0] = toupper(ret[0]);
3004 return normalize_name(ret, true, is_xception);
3005}
3006
3007std::string t_delphi_generator::constructor_param_name(string name) {
3008 string ret = name;
3009 ret[0] = toupper(ret[0]);
3010 ret = "A" + ret;
3011 return normalize_name(ret, false, false);
3012}
3013
3014string t_delphi_generator::normalize_clsnm(string clsnm, string prefix, bool b_no_check_keyword) {
3015 if (clsnm.size() > 0) {
3016 clsnm[0] = toupper(clsnm[0]);
3017 }
3018 if (b_no_check_keyword) {
3019 return prefix + clsnm;
3020 } else {
3021 return normalize_name(prefix + clsnm);
3022 }
3023}
3024
3025string t_delphi_generator::type_name(t_type* ttype,
3026 bool b_cls,
3027 bool b_no_postfix,
3028 bool b_exception_factory,
3029 bool b_full_exception_factory) {
3030
3031 if (ttype->is_typedef()) {
3032 t_typedef* tdef = (t_typedef*)ttype;
3033 if (tdef->is_forward_typedef()) { // forward types according to THRIFT-2421
3034 if (tdef->get_type() != NULL) {
3035 return type_name(tdef->get_type(),
3036 b_cls,
3037 b_no_postfix,
3038 b_exception_factory,
3039 b_full_exception_factory);
3040 } else {
3041 throw "unresolved forward declaration: " + tdef->get_symbolic();
3042 }
3043 } else {
3044 return normalize_name("T" + tdef->get_symbolic());
3045 }
3046 }
3047
3048 string typ_nm;
3049
3050 string s_factory;
3051
3052 if (ttype->is_base_type()) {
3053 return base_type_name((t_base_type*)ttype);
3054 } else if (ttype->is_enum()) {
3055 b_cls = true;
3056 b_no_postfix = true;
3057 } else if (ttype->is_map()) {
3058 t_map* tmap = (t_map*)ttype;
3059 if (b_cls) {
3060 typ_nm = "TThriftDictionaryImpl";
3061 } else {
3062 typ_nm = "IThriftDictionary";
3063 }
3064 return typ_nm + "<" + type_name(tmap->get_key_type()) + ", " + type_name(tmap->get_val_type())
3065 + ">";
3066 } else if (ttype->is_set()) {
3067 t_set* tset = (t_set*)ttype;
3068 if (b_cls) {
3069 typ_nm = "THashSetImpl";
3070 } else {
3071 typ_nm = "IHashSet";
3072 }
3073 return typ_nm + "<" + type_name(tset->get_elem_type()) + ">";
3074 } else if (ttype->is_list()) {
3075 t_list* tlist = (t_list*)ttype;
3076 if (b_cls) {
3077 typ_nm = "TThriftListImpl";
3078 } else {
3079 typ_nm = "IThriftList";
3080 }
3081 return typ_nm + "<" + type_name(tlist->get_elem_type()) + ">";
3082 }
3083
3084 string type_prefix;
3085
3086 if (b_cls) {
3087 type_prefix = "T";
3088 } else {
3089 type_prefix = "I";
3090 }
3091
3092 string nm = normalize_clsnm(ttype->get_name(), type_prefix);
3093
3094 if (b_exception_factory) {
3095 nm = nm + "Factory";
3096 }
3097
3098 if (b_cls) {
3099 if (!b_no_postfix) {
3100 nm = nm + "Impl";
3101 }
3102 }
3103
3104 if (b_exception_factory && b_full_exception_factory) {
3105 return type_name(ttype, true, true, false, false) + "." + nm;
3106 }
3107
3108 return nm;
3109}
3110
3111// returns "const " for some argument types
3112string t_delphi_generator::input_arg_prefix(t_type* ttype) {
3113
3114 // base types
3115 if (ttype->is_base_type()) {
3116 switch (((t_base_type*)ttype)->get_base()) {
3117
3118 // these should be const'ed for optimal performamce
3119 case t_base_type::TYPE_STRING: // refcounted pointer
3120 case t_base_type::TYPE_I64: // larger than 32 bit
3121 case t_base_type::TYPE_DOUBLE: // larger than 32 bit
3122 return "const ";
3123
3124 // all others don't need to be
3125 case t_base_type::TYPE_I8:
3126 case t_base_type::TYPE_I16:
3127 case t_base_type::TYPE_I32:
3128 case t_base_type::TYPE_BOOL:
3129 case t_base_type::TYPE_VOID:
3130 return "";
3131
3132 // we better always report any unknown types
3133 default:
3134 throw "compiler error: no input_arg_prefix() for base type "
3135 + t_base_type::t_base_name(((t_base_type*)ttype)->get_base());
3136 }
3137
3138 // enums
3139 } else if (ttype->is_enum()) {
3140 return ""; // usually <= 32 bit
3141
3142 // containers
3143 } else if (ttype->is_map()) {
3144 return "const "; // refcounted pointer
3145
3146 } else if (ttype->is_set()) {
3147 return "const "; // refcounted pointer
3148
3149 } else if (ttype->is_list()) {
3150 return "const "; // refcounted pointer
3151 }
3152
3153 // any other type, either TSomething or ISomething
3154 return "const "; // possibly refcounted pointer
3155}
3156
3157string t_delphi_generator::base_type_name(t_base_type* tbase) {
3158 switch (tbase->get_base()) {
3159 case t_base_type::TYPE_VOID:
3160 // no "void" in Delphi language
3161 return "";
3162 case t_base_type::TYPE_STRING:
3163 if (tbase->is_binary()) {
3164 if (ansistr_binary_) {
3165 return "System.AnsiString";
3166 } else {
3167 return "SysUtils.TBytes";
3168 }
3169 } else {
3170 return "System.string";
3171 }
3172 case t_base_type::TYPE_BOOL:
3173 return "System.Boolean";
3174 case t_base_type::TYPE_I8:
3175 return "System.ShortInt";
3176 case t_base_type::TYPE_I16:
3177 return "System.SmallInt";
3178 case t_base_type::TYPE_I32:
3179 return "System.Integer";
3180 case t_base_type::TYPE_I64:
3181 return "System.Int64";
3182 case t_base_type::TYPE_DOUBLE:
3183 return "System.Double";
3184 default:
3185 throw "compiler error: no Delphi name for base type "
3186 + t_base_type::t_base_name(tbase->get_base());
3187 }
3188}
3189
3190string t_delphi_generator::declare_field(t_field* tfield,
3191 bool init,
3192 std::string prefix,
3193 bool is_xception_class) {
3194 (void)init;
3195
3196 t_type* ftype = tfield->get_type();
3197 bool is_xception = ftype->is_xception();
3198
3199 string result = prefix + prop_name(tfield, is_xception_class) + ": "
3200 + type_name(ftype, false, true, is_xception, true) + ";";
3201 return result;
3202}
3203
3204string t_delphi_generator::function_signature(t_function* tfunction,
3205 bool for_async,
3206 std::string full_cls,
3207 bool is_xception) {
3208 t_type* ttype = tfunction->get_returntype();
3209 string prefix;
3210 if (full_cls == "") {
3211 prefix = "";
3212 } else {
3213 prefix = full_cls + ".";
3214 }
3215
3216 if( for_async) {
3217 if (is_void(ttype)) {
3218 return "function " + prefix + normalize_name(tfunction->get_name(), true, is_xception) + "Async("
3219 + argument_list(tfunction->get_arglist()) + "): IFuture<Integer>;"; // no IFuture<void> in Delphi
3220 } else {
3221 return "function " + prefix + normalize_name(tfunction->get_name(), true, is_xception) + "Async("
3222 + argument_list(tfunction->get_arglist()) + "): IFuture<"
3223 + type_name(ttype, false, true, is_xception, true) + ">;";
3224 }
3225 } else {
3226 if (is_void(ttype)) {
3227 return "procedure " + prefix + normalize_name(tfunction->get_name(), true, is_xception) + "("
3228 + argument_list(tfunction->get_arglist()) + ");";
3229 } else {
3230 return "function " + prefix + normalize_name(tfunction->get_name(), true, is_xception) + "("
3231 + argument_list(tfunction->get_arglist()) + "): "
3232 + type_name(ttype, false, true, is_xception, true) + ";";
3233 }
3234 }
3235}
3236
3237string t_delphi_generator::argument_list(t_struct* tstruct) {
3238 string result = "";
3239 const vector<t_field*>& fields = tstruct->get_members();
3240 vector<t_field*>::const_iterator f_iter;
3241 bool first = true;
3242 t_type* tt;
3243
3244 for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
3245 if (first) {
3246 first = false;
3247 } else {
3248 result += "; ";
3249 }
3250
3251 tt = (*f_iter)->get_type();
3252 result += input_arg_prefix(tt); // const?
3253 result += normalize_name((*f_iter)->get_name()) + ": "
3254 + type_name(tt, false, true, tt->is_xception(), true);
3255 }
3256 return result;
3257}
3258
3259string t_delphi_generator::constructor_argument_list(t_struct* tstruct, string current_indent) {
3260 ostringstream result;
3261 const vector<t_field*>& fields = tstruct->get_members();
3262 vector<t_field*>::const_iterator f_iter;
3263 bool first = true;
3264 t_type* tt;
3265 string line = "";
3266 string newline_indent = current_indent + " ";
3267
3268 bool firstline = true;
3269
3270 for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
3271 if (first) {
3272 first = false;
3273 } else {
3274 line += ";";
3275 }
3276
3277 if (line.size() > 80) {
3278 if (firstline) {
3279 result << endl << newline_indent;
3280 firstline = false;
3281 }
3282 result << line << endl;
3283 line = newline_indent;
3284 } else if (line.size() > 0) {
3285 line += " ";
3286 }
3287
3288 tt = (*f_iter)->get_type();
3289 line += input_arg_prefix(tt); // const?
3290 line += constructor_param_name((*f_iter)->get_name()) + ": "
3291 + type_name(tt, false, true, tt->is_xception(), true);
3292 }
3293
3294 if (line.size() > 0) {
3295 result << line;
3296 }
3297
3298 string result_str;
3299
3300 if (firstline) {
3301 result_str = " " + result.str();
3302 } else {
3303 result_str = result.str();
3304 }
3305
3306 return result_str;
3307}
3308
3309string t_delphi_generator::type_to_enum(t_type* type) {
3310 while (type->is_typedef()) {
3311 type = ((t_typedef*)type)->get_type();
3312 }
3313
3314 if (type->is_base_type()) {
3315 t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
3316 switch (tbase) {
3317 case t_base_type::TYPE_VOID:
3318 throw "NO T_VOID CONSTRUCT";
3319 case t_base_type::TYPE_STRING:
3320 return "TType.String_";
3321 case t_base_type::TYPE_BOOL:
3322 return "TType.Bool_";
3323 case t_base_type::TYPE_I8:
3324 return "TType.Byte_";
3325 case t_base_type::TYPE_I16:
3326 return "TType.I16";
3327 case t_base_type::TYPE_I32:
3328 return "TType.I32";
3329 case t_base_type::TYPE_I64:
3330 return "TType.I64";
3331 case t_base_type::TYPE_DOUBLE:
3332 return "TType.Double_";
3333 }
3334 } else if (type->is_enum()) {
3335 return "TType.I32";
3336 } else if (type->is_struct() || type->is_xception()) {
3337 return "TType.Struct";
3338 } else if (type->is_map()) {
3339 return "TType.Map";
3340 } else if (type->is_set()) {
3341 return "TType.Set_";
3342 } else if (type->is_list()) {
3343 return "TType.List";
3344 }
3345
3346 throw "INVALID TYPE IN type_to_enum: " + type->get_name();
3347}
3348
3349string t_delphi_generator::empty_value(t_type* type) {
3350 while (type->is_typedef()) {
3351 type = ((t_typedef*)type)->get_type();
3352 }
3353
3354 if (type->is_base_type()) {
3355 t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
3356 switch (tbase) {
3357 case t_base_type::TYPE_VOID:
3358 return "0";
3359 case t_base_type::TYPE_STRING:
3360 if (type->is_binary()) {
3361 if (ansistr_binary_) {
3362 return "''";
3363 } else {
3364 return "nil";
3365 }
3366 } else {
3367 return "''";
3368 }
3369 case t_base_type::TYPE_BOOL:
3370 return "False";
3371 case t_base_type::TYPE_I8:
3372 case t_base_type::TYPE_I16:
3373 case t_base_type::TYPE_I32:
3374 case t_base_type::TYPE_I64:
3375 return "0";
3376 case t_base_type::TYPE_DOUBLE:
3377 return "0.0";
3378 }
3379 } else if (type->is_enum()) {
3380 return "T" + type->get_name() + "(0)";
3381 } else if (type->is_struct() || type->is_xception()) {
3382 return "nil";
3383 } else if (type->is_map()) {
3384 return "nil";
3385 } else if (type->is_set()) {
3386 return "nil";
3387 } else if (type->is_list()) {
3388 return "nil";
3389 }
3390
3391 throw "INVALID TYPE IN type_to_enum: " + type->get_name();
3392}
3393
3394void t_delphi_generator::generate_delphi_property_writer_definition(ostream& out,
3395 t_field* tfield,
3396 bool is_xception_class) {
3397 t_type* ftype = tfield->get_type();
3398 bool is_xception = ftype->is_xception();
3399
3400 indent(out) << "procedure Set" << prop_name(tfield, is_xception_class)
3401 << "( const Value: " << type_name(ftype, false, true, is_xception, true) << ");"
3402 << endl;
3403}
3404
3405void t_delphi_generator::generate_delphi_property_reader_definition(ostream& out,
3406 t_field* tfield,
3407 bool is_xception_class) {
3408 t_type* ftype = tfield->get_type();
3409 bool is_xception = ftype->is_xception();
3410
3411 indent(out) << "function Get" << prop_name(tfield, is_xception_class) << ": "
3412 << type_name(ftype, false, true, is_xception, true) << ";" << endl;
3413}
3414
3415void t_delphi_generator::generate_delphi_isset_reader_definition(ostream& out,
3416 t_field* tfield,
3417 bool is_xception) {
3418 indent(out) << "function Get__isset_" << prop_name(tfield, is_xception) << ": System.Boolean;" << endl;
3419}
3420
3421void t_delphi_generator::generate_delphi_clear_union_value(ostream& out,
3422 std::string cls_prefix,
3423 std::string name,
3424 t_type* type,
3425 t_field* tfield,
3426 std::string fieldPrefix,
3427 bool is_xception_class,
3428 bool is_union,
3429 bool is_xception_factory,
3430 std::string xception_factory_name) {
3431 (void)cls_prefix;
3432 (void)name;
3433 (void)type;
3434 (void)is_union;
3435 (void)is_xception_factory;
3436 (void)xception_factory_name;
3437
3438 t_type* ftype = tfield->get_type();
3439 bool is_xception = ftype->is_xception();
3440
3441 indent_impl(out) << "if F__isset_" << prop_name(tfield, is_xception_class) << " then begin"
3442 << endl;
3443 indent_up_impl();
3444 indent_impl(out) << "F__isset_" << prop_name(tfield, is_xception_class) << " := False;" << endl;
3445 indent_impl(out) << fieldPrefix << prop_name(tfield, is_xception_class) << " := "
3446 << "Default( " << type_name(ftype, false, true, is_xception, true) << ");"
3447 << endl;
3448 indent_down_impl();
3449 indent_impl(out) << "end;" << endl;
3450}
3451
3452void t_delphi_generator::generate_delphi_property_writer_impl(ostream& out,
3453 std::string cls_prefix,
3454 std::string name,
3455 t_type* type,
3456 t_field* tfield,
3457 std::string fieldPrefix,
3458 bool is_xception_class,
3459 bool is_union,
3460 bool is_xception_factory,
3461 std::string xception_factory_name) {
3462 (void)type;
3463
3464 t_type* ftype = tfield->get_type();
3465 bool is_xception = ftype->is_xception();
3466
3467 indent_impl(out) << "procedure " << cls_prefix << name << "."
3468 << "Set" << prop_name(tfield, is_xception_class)
3469 << "( const Value: " << type_name(ftype, false, true, is_xception, true) << ");"
3470 << endl;
3471 indent_impl(out) << "begin" << endl;
3472 indent_up_impl();
3473 if (is_union) {
3474 indent_impl(out) << "ClearUnionValues;" << endl;
3475 }
3476 if (tfield->get_req() != t_field::T_REQUIRED) {
3477 indent_impl(out) << "F__isset_" << prop_name(tfield, is_xception_class) << " := True;" << endl;
3478 }
3479 indent_impl(out) << fieldPrefix << prop_name(tfield, is_xception_class) << " := Value;" << endl;
3480
3481 if (is_xception_class && (!is_xception_factory)) {
3482 indent_impl(out) << xception_factory_name << "." << prop_name(tfield, is_xception_class)
3483 << " := Value;" << endl;
3484 }
3485
3486 indent_down_impl();
3487 indent_impl(out) << "end;" << endl << endl;
3488}
3489
3490void t_delphi_generator::generate_delphi_property_reader_impl(ostream& out,
3491 std::string cls_prefix,
3492 std::string name,
3493 t_type* type,
3494 t_field* tfield,
3495 std::string fieldPrefix,
3496 bool is_xception_class) {
3497 (void)type;
3498
3499 t_type* ftype = tfield->get_type();
3500 bool is_xception = ftype->is_xception();
3501
3502 indent_impl(out) << "function " << cls_prefix << name << "."
3503 << "Get" << prop_name(tfield, is_xception_class) << ": "
3504 << type_name(ftype, false, true, is_xception, true) << ";" << endl;
3505 indent_impl(out) << "begin" << endl;
3506 indent_up_impl();
3507 indent_impl(out) << "Result := " << fieldPrefix << prop_name(tfield, is_xception_class) << ";"
3508 << endl;
3509 indent_down_impl();
3510 indent_impl(out) << "end;" << endl << endl;
3511}
3512
3513void t_delphi_generator::generate_delphi_isset_reader_impl(ostream& out,
3514 std::string cls_prefix,
3515 std::string name,
3516 t_type* type,
3517 t_field* tfield,
3518 std::string fieldPrefix,
3519 bool is_xception) {
3520 (void)type;
3521
3522 string isset_name = "__isset_" + prop_name(tfield, is_xception);
3523 indent_impl(out) << "function " << cls_prefix << name << "."
3524 << "Get" << isset_name << ": System.Boolean;" << endl;
3525 indent_impl(out) << "begin" << endl;
3526 indent_up_impl();
3527 indent_impl(out) << "Result := " << fieldPrefix << isset_name << ";" << endl;
3528 indent_down_impl();
3529 indent_impl(out) << "end;" << endl << endl;
3530}
3531
3532void t_delphi_generator::generate_delphi_create_exception_impl(ostream& out,
3533 string cls_prefix,
3534 t_struct* tstruct,
3535 bool is_exception) {
3536 (void)cls_prefix;
3537
3538 string exception_cls_nm = type_name(tstruct, true, true);
3539 string cls_nm = type_name(tstruct, true, false, is_exception, is_exception);
3540
3541 indent_impl(out) << "function " << cls_nm << ".CreateException: " << exception_cls_nm << ";"
3542 << endl;
3543
3544 indent_impl(out) << "begin" << endl;
3545 indent_up_impl();
3546
3547 indent_impl(out) << "Result := " << exception_cls_nm << ".Create;" << endl;
3548 string factory_name = normalize_clsnm(tstruct->get_name(), "", true) + "Factory";
3549 indent_impl(out) << "Result.F" << factory_name << " := Self;" << endl;
3550
3551 const vector<t_field*>& fields = tstruct->get_members();
3552 vector<t_field*>::const_iterator f_iter;
3553
3554 string propname;
3555
3556 for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
3557 propname = prop_name(*f_iter, is_exception);
3558 if ((*f_iter)->get_req() != t_field::T_REQUIRED) {
3559 indent_impl(out) << "if __isset_" << propname << " then begin" << endl;
3560 indent_up_impl();
3561 }
3562 indent_impl(out) << "Result." << propname << " := " << propname << ";" << endl;
3563 if ((*f_iter)->get_req() != t_field::T_REQUIRED) {
3564 indent_down_impl();
3565 indent_impl(out) << "end;" << endl;
3566 }
3567 }
3568
3569 indent_impl(out) << "Result.UpdateMessageProperty;" << endl;
3570
3571 indent_down_impl();
3572 indent_impl(out) << "end;" << endl << endl;
3573}
3574
3575void t_delphi_generator::generate_delphi_struct_reader_impl(ostream& out,
3576 string cls_prefix,
3577 t_struct* tstruct,
3578 bool is_exception) {
3579
3580 ostringstream local_vars;
3581 ostringstream code_block;
3582
3583 const vector<t_field*>& fields = tstruct->get_members();
3584 vector<t_field*>::const_iterator f_iter;
3585
3586 indent_impl(code_block) << "begin" << endl;
3587 indent_up_impl();
3588
3589 indent_impl(local_vars) << "tracker : IProtocolRecursionTracker;" << endl;
3590 indent_impl(code_block) << "tracker := iprot.NextRecursionLevel;" << endl;
3591
3592 // local bools for required fields
3593 for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
3594 if ((*f_iter)->get_req() == t_field::T_REQUIRED) {
3595 indent_impl(local_vars) << "_req_isset_" << prop_name(*f_iter, is_exception) << " : System.Boolean;"
3596 << endl;
3597 indent_impl(code_block) << "_req_isset_" << prop_name(*f_iter, is_exception) << " := FALSE;"
3598 << endl;
3599 }
3600 }
3601
3602 indent_impl(code_block) << "struc := iprot.ReadStructBegin;" << endl;
3603
3604 indent_impl(code_block) << "try" << endl;
3605 indent_up_impl();
3606
3607 indent_impl(code_block) << "while (true) do" << endl;
3608 indent_impl(code_block) << "begin" << endl;
3609 indent_up_impl();
3610
3611 indent_impl(code_block) << "field_ := iprot.ReadFieldBegin();" << endl;
3612
3613 indent_impl(code_block) << "if (field_.Type_ = TType.Stop) then" << endl;
3614 indent_impl(code_block) << "begin" << endl;
3615 indent_up_impl();
3616 indent_impl(code_block) << "Break;" << endl;
3617 indent_down_impl();
3618 indent_impl(code_block) << "end;" << endl;
3619
3620 bool first = true;
3621
3622 for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
3623
3624 if (first) {
3625 indent_impl(code_block) << "case field_.ID of" << endl;
3626 indent_up_impl();
3627 }
3628
3629 first = false;
3630 if (f_iter != fields.begin()) {
3631 code_block << ";" << endl;
3632 }
3633 indent_impl(code_block) << (*f_iter)->get_key() << ": begin" << endl;
3634 indent_up_impl();
3635 indent_impl(code_block) << "if (field_.Type_ = " << type_to_enum((*f_iter)->get_type())
3636 << ") then begin" << endl;
3637 indent_up_impl();
3638
3639 generate_deserialize_field(code_block, is_exception, *f_iter, "Self.", local_vars);
3640
3641 // required field?
3642 if ((*f_iter)->get_req() == t_field::T_REQUIRED) {
3643 indent_impl(code_block) << "_req_isset_" << prop_name(*f_iter, is_exception) << " := TRUE;"
3644 << endl;
3645 }
3646
3647 indent_down_impl();
3648
3649 indent_impl(code_block) << "end else begin" << endl;
3650 indent_up_impl();
3651 indent_impl(code_block) << "TProtocolUtil.Skip(iprot, field_.Type_);" << endl;
3652 indent_down_impl();
3653 indent_impl(code_block) << "end;" << endl;
3654 indent_down_impl();
3655 indent_impl(code_block) << "end";
3656 }
3657
3658 if (!first) {
3659 code_block << endl;
3660 indent_impl(code_block) << "else begin" << endl;
3661 indent_up_impl();
3662 }
3663
3664 indent_impl(code_block) << "TProtocolUtil.Skip(iprot, field_.Type_);" << endl;
3665
3666 if (!first) {
3667 indent_down_impl();
3668 indent_impl(code_block) << "end;" << endl;
3669 indent_down_impl();
3670 indent_impl(code_block) << "end;" << endl;
3671 }
3672
3673 indent_impl(code_block) << "iprot.ReadFieldEnd;" << endl;
3674
3675 indent_down_impl();
3676
3677 indent_impl(code_block) << "end;" << endl;
3678 indent_down_impl();
3679
3680 indent_impl(code_block) << "finally" << endl;
3681 indent_up_impl();
3682 indent_impl(code_block) << "iprot.ReadStructEnd;" << endl;
3683 indent_down_impl();
3684 indent_impl(code_block) << "end;" << endl;
3685
3686 // all required fields have been read?
3687 for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
3688 if ((*f_iter)->get_req() == t_field::T_REQUIRED) {
3689 indent_impl(code_block) << "if not _req_isset_" << prop_name(*f_iter, is_exception) << endl;
3690 indent_impl(code_block)
3691 << "then raise TProtocolExceptionInvalidData.Create("
3692 << "'required field " << prop_name(*f_iter, is_exception) << " not set');"
3693 << endl;
3694 }
3695 }
3696
3697 indent_down_impl();
3698 indent_impl(code_block) << "end;" << endl << endl;
3699
3700 string cls_nm;
3701
3702 cls_nm = type_name(tstruct, true, false, is_exception, is_exception);
3703
3704 indent_impl(out) << "procedure " << cls_prefix << cls_nm << ".Read( const iprot: IProtocol);"
3705 << endl;
3706 indent_impl(out) << "var" << endl;
3707 indent_up_impl();
3708 indent_impl(out) << "field_ : TThriftField;" << endl;
3709 indent_impl(out) << "struc : TThriftStruct;" << endl;
3710 indent_down_impl();
3711 out << local_vars.str() << endl;
3712 out << code_block.str();
3713}
3714
3715void t_delphi_generator::generate_delphi_struct_result_writer_impl(ostream& out,
3716 string cls_prefix,
3717 t_struct* tstruct,
3718 bool is_exception) {
3719
3720 ostringstream local_vars;
3721 ostringstream code_block;
3722
3723 string name = tstruct->get_name();
3724 const vector<t_field*>& fields = tstruct->get_sorted_members();
3725 vector<t_field*>::const_iterator f_iter;
3726
3727 indent_impl(code_block) << "begin" << endl;
3728 indent_up_impl();
3729
3730 indent_impl(local_vars) << "tracker : IProtocolRecursionTracker;" << endl;
3731 indent_impl(code_block) << "tracker := oprot.NextRecursionLevel;" << endl;
3732
3733 indent_impl(code_block) << "Thrift.Protocol.Init( struc, '" << name << "');" << endl;
3734 indent_impl(code_block) << "oprot.WriteStructBegin(struc);" << endl;
3735
3736 if (fields.size() > 0) {
3737 indent_impl(code_block) << "Thrift.Protocol.Init( field_);" << endl;
3738 for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
3739 indent_impl(code_block) << "if (__isset_" << prop_name(*f_iter, is_exception) << ") then"
3740 << endl;
3741 indent_impl(code_block) << "begin" << endl;
3742 indent_up_impl();
3743 indent_impl(code_block) << "field_.Name := '" << (*f_iter)->get_name() << "';" << endl;
3744 indent_impl(code_block) << "field_.Type_ := " << type_to_enum((*f_iter)->get_type()) << ";"
3745 << endl;
3746 indent_impl(code_block) << "field_.ID := " << (*f_iter)->get_key() << ";" << endl;
3747 indent_impl(code_block) << "oprot.WriteFieldBegin(field_);" << endl;
3748 generate_serialize_field(code_block, is_exception, *f_iter, "Self.", local_vars);
3749 indent_impl(code_block) << "oprot.WriteFieldEnd();" << endl;
3750 indent_down_impl();
3751 }
3752 }
3753
3754 indent_impl(code_block) << "oprot.WriteFieldStop();" << endl;
3755 indent_impl(code_block) << "oprot.WriteStructEnd();" << endl;
3756
3757 indent_down_impl();
3758 indent_impl(code_block) << "end;" << endl << endl;
3759
3760 string cls_nm;
3761
3762 cls_nm = type_name(tstruct, true, false, is_exception, is_exception);
3763
3764 indent_impl(out) << "procedure " << cls_prefix << cls_nm << ".Write( const oprot: IProtocol);"
3765 << endl;
3766 indent_impl(out) << "var" << endl;
3767 indent_up_impl();
3768 indent_impl(out) << "struc : TThriftStruct;" << endl;
3769
3770 if (fields.size() > 0) {
3771 indent_impl(out) << "field_ : TThriftField;" << endl;
3772 }
3773
3774 out << local_vars.str();
3775 indent_down_impl();
3776 out << code_block.str();
3777}
3778
3779void t_delphi_generator::generate_delphi_struct_writer_impl(ostream& out,
3780 string cls_prefix,
3781 t_struct* tstruct,
3782 bool is_exception) {
3783
3784 ostringstream local_vars;
3785 ostringstream code_block;
3786
3787 string name = tstruct->get_name();
3788 const vector<t_field*>& fields = tstruct->get_sorted_members();
3789 vector<t_field*>::const_iterator f_iter;
3790
3791 indent_impl(code_block) << "begin" << endl;
3792 indent_up_impl();
3793
3794 indent_impl(local_vars) << "tracker : IProtocolRecursionTracker;" << endl;
3795 indent_impl(code_block) << "tracker := oprot.NextRecursionLevel;" << endl;
3796
3797 indent_impl(code_block) << "Thrift.Protocol.Init( struc, '" << name << "');" << endl;
3798 indent_impl(code_block) << "oprot.WriteStructBegin(struc);" << endl;
3799
3800 if (fields.size() > 0) {
3801 indent_impl(code_block) << "Thrift.Protocol.Init( field_);" << endl;
3802 }
3803
3804 for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
3805 string fieldname = prop_name((*f_iter), is_exception);
3806 bool null_allowed = type_can_be_null((*f_iter)->get_type());
3807 bool is_required = ((*f_iter)->get_req() == t_field::T_REQUIRED);
3808 bool has_isset = (!is_required);
3809 if (is_required && null_allowed) {
3810 null_allowed = false;
3811 indent_impl(code_block) << "if (Self." << fieldname << " = nil)" << endl;
3812 indent_impl(code_block) << "then raise TProtocolExceptionInvalidData.Create("
3813 << "'required field " << fieldname << " not set');"
3814 << endl;
3815 }
3816 if (null_allowed) {
3817 indent_impl(code_block) << "if (Self." << fieldname << " <> nil)";
3818 if (has_isset) {
3819 code_block << " and __isset_" << fieldname;
3820 }
3821 code_block << " then begin" << endl;
3822 indent_up_impl();
3823 } else {
3824 if (has_isset) {
3825 indent_impl(code_block) << "if (__isset_" << fieldname << ") then begin" << endl;
3826 indent_up_impl();
3827 }
3828 }
3829 indent_impl(code_block) << "field_.Name := '" << (*f_iter)->get_name() << "';" << endl;
3830 indent_impl(code_block) << "field_.Type_ := " << type_to_enum((*f_iter)->get_type()) << ";"
3831 << endl;
3832 indent_impl(code_block) << "field_.ID := " << (*f_iter)->get_key() << ";" << endl;
3833 indent_impl(code_block) << "oprot.WriteFieldBegin(field_);" << endl;
3834 generate_serialize_field(code_block, is_exception, *f_iter, "Self.", local_vars);
3835 indent_impl(code_block) << "oprot.WriteFieldEnd();" << endl;
3836 if (null_allowed || has_isset) {
3837 indent_down_impl();
3838 indent_impl(code_block) << "end;" << endl;
3839 }
3840 }
3841
3842 indent_impl(code_block) << "oprot.WriteFieldStop();" << endl;
3843 indent_impl(code_block) << "oprot.WriteStructEnd();" << endl;
3844
3845 indent_down_impl();
3846 indent_impl(code_block) << "end;" << endl << endl;
3847
3848 string cls_nm;
3849
3850 cls_nm = type_name(tstruct, true, false, is_exception, is_exception);
3851
3852 indent_impl(out) << "procedure " << cls_prefix << cls_nm << ".Write( const oprot: IProtocol);"
3853 << endl;
3854 indent_impl(out) << "var" << endl;
3855 indent_up_impl();
3856 indent_impl(out) << "struc : TThriftStruct;" << endl;
3857 if (fields.size() > 0) {
3858 indent_impl(out) << "field_ : TThriftField;" << endl;
3859 }
3860 out << local_vars.str();
3861 indent_down_impl();
3862 out << code_block.str();
3863}
3864
3865void t_delphi_generator::generate_delphi_struct_tostring_impl(ostream& out,
3866 string cls_prefix,
3867 t_struct* tstruct,
3868 bool is_exception,
3869 bool is_x_factory) {
3870
3871 const vector<t_field*>& fields = tstruct->get_members();
3872 vector<t_field*>::const_iterator f_iter;
3873
3874 string cls_nm;
3875
3876 if (is_exception) {
3877 cls_nm = type_name(tstruct, true, (!is_x_factory), is_x_factory, true);
3878 } else {
3879 cls_nm = type_name(tstruct, true, false);
3880 }
3881
3882 string tmp_sb = tmp("_sb");
3883 string tmp_first = tmp("_first");
3884 bool useFirstFlag = false;
3885
3886 indent_impl(out) << "function " << cls_prefix << cls_nm << ".ToString: string;" << endl;
3887 indent_impl(out) << "var" << endl;
3888 indent_up_impl();
3889 indent_impl(out) << tmp_sb << " : TThriftStringBuilder;" << endl;
3890 for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
3891 bool is_optional = ((*f_iter)->get_req() != t_field::T_REQUIRED);
3892 if (is_optional) {
3893 indent_impl(out) << tmp_first << " : System.Boolean;" << endl;
3894 useFirstFlag = true;
3895 }
3896 break;
3897 }
3898 indent_down_impl();
3899 indent_impl(out) << "begin" << endl;
3900 indent_up_impl();
3901
3902 indent_impl(out) << tmp_sb << " := TThriftStringBuilder.Create('(');" << endl;
3903 indent_impl(out) << "try" << endl;
3904 indent_up_impl();
3905
3906 if (useFirstFlag) {
3907 indent_impl(out) << tmp_first << " := TRUE;" << endl;
3908 }
3909
3910 bool had_required = false; // set to true after first required field has been processed
3911
3912 for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
3913 bool null_allowed = type_can_be_null((*f_iter)->get_type());
3914 bool is_optional = ((*f_iter)->get_req() != t_field::T_REQUIRED);
3915 if (null_allowed) {
3916 indent_impl(out) << "if (Self." << prop_name((*f_iter), is_exception) << " <> nil)";
3917 if (is_optional) {
3918 out << " and __isset_" << prop_name(*f_iter, is_exception);
3919 }
3920 out << " then begin" << endl;
3921 indent_up_impl();
3922 } else {
3923 if (is_optional) {
3924 indent_impl(out) << "if (__isset_" << prop_name(*f_iter, is_exception) << ") then begin"
3925 << endl;
3926 indent_up_impl();
3927 }
3928 }
3929
3930 if (useFirstFlag && (!had_required)) {
3931 indent_impl(out) << "if not " << tmp_first << " then " << tmp_sb << ".Append(',');" << endl;
3932 if (is_optional) {
3933 indent_impl(out) << tmp_first << " := FALSE;" << endl;
3934 }
3935 indent_impl(out) << tmp_sb << ".Append('" << prop_name((*f_iter), is_exception) << ": ');"
3936 << endl;
3937 } else {
3938 indent_impl(out) << tmp_sb << ".Append(', " << prop_name((*f_iter), is_exception) << ": ');"
3939 << endl;
3940 }
3941
3942 t_type* ttype = (*f_iter)->get_type();
3943 while (ttype->is_typedef()) {
3944 ttype = ((t_typedef*)ttype)->get_type();
3945 }
3946
3947 if (ttype->is_xception() || ttype->is_struct()) {
3948 indent_impl(out) << "if (Self." << prop_name((*f_iter), is_exception) << " = nil) then " << tmp_sb
3949 << ".Append('<null>') else " << tmp_sb << ".Append( Self."
3950 << prop_name((*f_iter), is_exception) << ".ToString());" << endl;
3951 } else if (ttype->is_enum()) {
3952 indent_impl(out) << tmp_sb << ".Append(EnumUtils<"
3953 << type_name(ttype, false, true, false, false)
3954 << ">.ToString( System.Ord( Self."
3955 << prop_name((*f_iter), is_exception) << ")));" << endl;
3956 } else {
3957 indent_impl(out) << tmp_sb << ".Append( Self." << prop_name((*f_iter), is_exception) << ");"
3958 << endl;
3959 }
3960
3961 if (null_allowed || is_optional) {
3962 indent_down_impl();
3963 indent_impl(out) << "end;" << endl;
3964 }
3965
3966 if (!is_optional) {
3967 had_required = true; // now __first must be false, so we don't need to check it anymore
3968 }
3969 }
3970
3971 indent_impl(out) << tmp_sb << ".Append(')');" << endl;
3972 indent_impl(out) << "Result := " << tmp_sb << ".ToString;" << endl;
3973 if (useFirstFlag) {
3974 indent_impl(out) << "if " << tmp_first << " then {prevent warning};" << endl;
3975 }
3976
3977 indent_down_impl();
3978 indent_impl(out) << "finally" << endl;
3979 indent_up_impl();
3980 indent_impl(out) << tmp_sb << ".Free;" << endl;
3981 indent_down_impl();
3982 indent_impl(out) << "end;" << endl;
3983
3984 indent_down_impl();
3985 indent_impl(out) << "end;" << endl << endl;
3986}
3987
3988bool t_delphi_generator::is_void(t_type* type) {
3989 while (type->is_typedef()) {
3990 type = ((t_typedef*)type)->get_type();
3991 }
3992
3993 if (type->is_base_type()) {
3994 t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
3995 if (tbase == t_base_type::TYPE_VOID) {
3996 return true;
3997 }
3998 }
3999 return false;
4000}
4001
4002THRIFT_REGISTER_GENERATOR(
4003 delphi,
4004 "delphi",
4005 " ansistr_binary: Use AnsiString for binary datatype (default is TBytes).\n"
4006 " register_types: Enable TypeRegistry, allows for creation of struct, union\n"
4007 " and container instances by interface or TypeInfo()\n"
4008 " constprefix: Name TConstants classes after IDL to reduce ambiguities\n"
4009 " events: Enable and use processing events in the generated code.\n"
4010 " xmldoc: Enable XMLDoc comments for Help Insight etc.\n"
4011 " async: Generate IAsync interface to use Parallel Programming Library (XE7+ only).\n")