http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/d709f67d/depends/thirdparty/thrift/compiler/cpp/src/generate/t_delphi_generator.cc ---------------------------------------------------------------------- diff --git a/depends/thirdparty/thrift/compiler/cpp/src/generate/t_delphi_generator.cc b/depends/thirdparty/thrift/compiler/cpp/src/generate/t_delphi_generator.cc new file mode 100644 index 0000000..cdf49c6 --- /dev/null +++ b/depends/thirdparty/thrift/compiler/cpp/src/generate/t_delphi_generator.cc @@ -0,0 +1,3900 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + * Contains some contributions under the Thrift Software License. + * Please see doc/old-thrift-license.txt in the Thrift distribution for + * details. + */ + +#include <cassert> + +#include <string> +#include <fstream> +#include <iostream> +#include <vector> +#include <list> + +#include <stdlib.h> +#include <sys/stat.h> +#include <sstream> +#include <cctype> + +#include "platform.h" +#include "t_oop_generator.h" + +using std::map; +using std::ofstream; +using std::ostream; +using std::ostringstream; +using std::string; +using std::stringstream; +using std::vector; + +static const string endl = "\n"; // avoid ostream << std::endl flushes + +class t_delphi_generator : public t_oop_generator { +public: + t_delphi_generator(t_program* program, + const std::map<std::string, std::string>& parsed_options, + const std::string& option_string) + : t_oop_generator(program) { + (void)option_string; + indent_impl_ = 0; + has_forward = false; + has_enum = false; + has_const = false; + std::map<std::string, std::string>::const_iterator iter; + + iter = parsed_options.find("ansistr_binary"); + ansistr_binary_ = (iter != parsed_options.end()); + iter = parsed_options.find("register_types"); + register_types_ = (iter != parsed_options.end()); + iter = parsed_options.find("constprefix"); + constprefix_ = (iter != parsed_options.end()); + iter = parsed_options.find("events"); + events_ = (iter != parsed_options.end()); + iter = parsed_options.find("xmldoc"); + xmldoc_ = (iter != parsed_options.end()); + + out_dir_base_ = "gen-delphi"; + escape_.clear(); + escape_['\''] = "''"; + } + + void init_generator(); + void close_generator(); + + void generate_consts(std::vector<t_const*> consts); + + void generate_typedef(t_typedef* ttypedef); + void generate_enum(t_enum* tenum); + void generate_forward_declaration(t_struct* tstruct); + void generate_struct(t_struct* tstruct); + void generate_xception(t_struct* txception); + void generate_service(t_service* tservice); + void generate_property(ostream& out, t_field* tfield, bool isPublic, bool is_xception); + void generate_property_writer_(ostream& out, t_field* tfield, bool isPublic); + + void generate_delphi_property(ostream& out, + bool struct_is_exception, + t_field* tfield, + bool isPublic, + std::string fieldPrefix = ""); + void generate_delphi_isset_reader_definition(ostream& out, t_field* tfield, bool is_xception); + void generate_delphi_property_reader_definition(ostream& out, + t_field* tfield, + bool is_xception_class); + void generate_delphi_property_writer_definition(ostream& out, + t_field* tfield, + bool is_xception_class); + void generate_delphi_property_reader_impl(ostream& out, + std::string cls_prefix, + std::string name, + t_type* type, + t_field* tfield, + std::string fieldPrefix, + bool is_xception_class); + void generate_delphi_property_writer_impl(ostream& out, + std::string cls_prefix, + std::string name, + t_type* type, + t_field* tfield, + std::string fieldPrefix, + bool is_xception_class, + bool is_union, + bool is_xception_factory, + std::string xception_factroy_name); + void generate_delphi_clear_union_value(ostream& out, + std::string cls_prefix, + std::string name, + t_type* type, + t_field* tfield, + std::string fieldPrefix, + bool is_xception_class, + bool is_union, + bool is_xception_factory, + std::string xception_factroy_name); + void generate_delphi_isset_reader_impl(ostream& out, + std::string cls_prefix, + std::string name, + t_type* type, + t_field* tfield, + std::string fieldPrefix, + bool is_xception); + void generate_delphi_struct_writer_impl(ostream& out, + std::string cls_prefix, + t_struct* tstruct, + bool is_exception); + void generate_delphi_struct_result_writer_impl(ostream& out, + std::string cls_prefix, + t_struct* tstruct, + bool is_exception); + + void generate_delphi_struct_tostring_impl(ostream& out, + std::string cls_prefix, + t_struct* tstruct, + bool is_exception, + bool is_x_factory); + + void add_delphi_uses_list(string unitname); + + void generate_delphi_struct_reader_impl(ostream& out, + std::string cls_prefix, + t_struct* tstruct, + bool is_exception); + void generate_delphi_create_exception_impl(ostream& out, + string cls_prefix, + t_struct* tstruct, + bool is_exception); + + bool const_needs_var(t_type* type); + void print_const_prop(std::ostream& out, string name, t_type* type, t_const_value* value); + void print_private_field(std::ostream& out, string name, t_type* type, t_const_value* value); + void print_const_value(std::ostream& vars, + std::ostream& out, + std::string name, + t_type* type, + t_const_value* value); + void initialize_field(std::ostream& vars, + std::ostream& out, + std::string name, + t_type* type, + t_const_value* value); + void finalize_field(std::ostream& out, + std::string name, + t_type* type, + t_const_value* value, + std::string cls_nm = ""); + std::string render_const_value(std::ostream& local_vars, + std::ostream& out, + std::string name, + t_type* type, + t_const_value* value); + void print_const_def_value(std::ostream& vars, + std::ostream& out, + std::string name, + t_type* type, + t_const_value* value, + std::string cls_nm = ""); + std::string make_constants_classname(); + + void generate_delphi_struct(t_struct* tstruct, bool is_exception); + void generate_delphi_struct_impl(ostream& out, + std::string cls_prefix, + t_struct* tstruct, + bool is_exception, + bool is_result = false, + bool is_x_factory = false); + void print_delphi_struct_type_factory_func(ostream& out, t_struct* tstruct); + void generate_delphi_struct_type_factory(ostream& out, + std::string cls_prefix, + t_struct* tstruct, + bool is_exception, + bool is_result = false, + bool is_x_factory = false); + void generate_delphi_struct_type_factory_registration(ostream& out, + std::string cls_prefix, + t_struct* tstruct, + bool is_exception, + bool is_result = false, + bool is_x_factory = false); + void generate_delphi_struct_definition(std::ostream& out, + t_struct* tstruct, + bool is_xception = false, + bool in_class = false, + bool is_result = false, + bool is_x_factory = false); + void generate_delphi_struct_reader(std::ostream& out, t_struct* tstruct); + void generate_delphi_struct_result_writer(std::ostream& out, t_struct* tstruct); + void generate_delphi_struct_writer(std::ostream& out, t_struct* tstruct); + void generate_delphi_struct_tostring(std::ostream& out, t_struct* tstruct); + + void generate_function_helpers(t_function* tfunction); + void generate_service_interface(t_service* tservice); + void generate_service_helpers(t_service* tservice); + void generate_service_client(t_service* tservice); + void generate_service_server(t_service* tservice); + void generate_process_function(t_service* tservice, t_function* function); + + void generate_deserialize_field(std::ostream& out, + bool is_xception, + t_field* tfield, + std::string prefix, + std::ostream& local_vars); + void generate_deserialize_struct(std::ostream& out, + t_struct* tstruct, + std::string name, + std::string prefix); + void generate_deserialize_container(ostream& out, + bool is_xception, + t_type* ttype, + string name, + std::ostream& local_vars); + + void generate_deserialize_set_element(std::ostream& out, + bool is_xception, + t_set* tset, + std::string prefix, + std::ostream& local_vars); + void generate_deserialize_map_element(std::ostream& out, + bool is_xception, + t_map* tmap, + std::string prefix, + std::ostream& local_vars); + void generate_deserialize_list_element(std::ostream& out, + bool is_xception, + t_list* list, + std::string prefix, + std::ostream& local_vars); + + void generate_serialize_field(std::ostream& out, + bool is_xception, + t_field* tfield, + std::string prefix, + std::ostream& local_vars); + void generate_serialize_struct(std::ostream& out, + t_struct* tstruct, + std::string prefix, + std::ostream& local_vars); + void generate_serialize_container(std::ostream& out, + bool is_xception, + t_type* ttype, + std::string prefix, + std::ostream& local_vars); + void generate_serialize_map_element(std::ostream& out, + bool is_xception, + t_map* tmap, + std::string iter, + std::string map, + std::ostream& local_vars); + void generate_serialize_set_element(std::ostream& out, + bool is_xception, + t_set* tmap, + std::string iter, + std::ostream& local_vars); + void generate_serialize_list_element(std::ostream& out, + bool is_xception, + t_list* tlist, + std::string iter, + std::ostream& local_vars); + + void delphi_type_usings(std::ostream& out); + std::string delphi_thrift_usings(); + + std::string type_name(t_type* ttype, + bool b_cls = false, + bool b_no_postfix = false, + bool b_exception_factory = false, + bool b_full_exception_factory = false); + std::string normalize_clsnm(std::string name, + std::string prefix, + bool b_no_check_keyword = false); + std::string make_valid_delphi_identifier(std::string const& fromName); + std::string input_arg_prefix(t_type* ttype); + + std::string base_type_name(t_base_type* tbase); + std::string declare_field(t_field* tfield, + bool init = false, + std::string prefix = "", + bool is_xception_class = false); + std::string function_signature(t_function* tfunction, + std::string full_cls = "", + bool is_xception = false); + std::string argument_list(t_struct* tstruct); + std::string constructor_argument_list(t_struct* tstruct, std::string current_indent); + std::string type_to_enum(t_type* ttype); + std::string prop_name(t_field* tfield, bool is_xception = false); + std::string prop_name(std::string name, bool is_xception = false); + std::string constructor_param_name(string name); + + void write_enum(std::string line); + void write_forward_decr(std::string line); + void write_const(std::string line); + void write_struct(std::string line); + void write_service(std::string line); + + virtual std::string autogen_comment() { + return std::string("(**\n") + " * Autogenerated by Thrift Compiler (" + THRIFT_VERSION + ")\n" + + " *\n" + " * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n" + + " *)\n"; + } + + string replace_all(string contents, string search, string replace); + string xml_encode(string contents); + string xmldoc_encode(string contents); + string xmlattrib_encode(string contents); + void generate_delphi_doc(std::ostream& out, t_field* field); + void generate_delphi_doc(std::ostream& out, t_doc* tdoc); + void generate_delphi_doc(std::ostream& out, t_function* tdoc); + void generate_delphi_docstring_comment(std::ostream& out, string contents); + + bool type_can_be_null(t_type* ttype) { + while (ttype->is_typedef()) { + ttype = ((t_typedef*)ttype)->get_type(); + } + + return ttype->is_container() || ttype->is_struct() || ttype->is_xception(); + } + +private: + std::string namespace_name_; + std::ostringstream s_forward_decr; + std::ostringstream s_enum; + std::ostringstream s_const; + std::ostringstream s_struct; + std::ostringstream s_service; + std::ostringstream s_const_impl; + std::ostringstream s_struct_impl; + std::ostringstream s_service_impl; + std::ostringstream s_type_factory_registration; + std::ostringstream s_type_factory_funcs; + bool has_forward; + bool has_enum; + bool has_const; + std::string namespace_dir_; + std::map<std::string, int> delphi_keywords; + std::map<std::string, int> delphi_reserved_method; + std::map<std::string, int> delphi_reserved_method_exception; + std::map<std::string, int> types_known; + std::list<t_typedef*> typedefs_pending; + std::vector<std::string> uses_list; + void create_keywords(); + bool find_keyword(std::map<std::string, int>& keyword_map, std::string name); + std::string normalize_name(std::string name, + bool b_method = false, + bool b_exception_method = false); + std::string empty_value(t_type* type); + bool is_fully_defined_type(t_type* ttype); + void add_defined_type(t_type* ttype); + void init_known_types_list(); + bool is_void(t_type* type); + int indent_impl_; + bool ansistr_binary_; + bool register_types_; + bool constprefix_; + bool events_; + bool xmldoc_; + void indent_up_impl() { ++indent_impl_; }; + void indent_down_impl() { --indent_impl_; }; + std::string indent_impl() { + std::string ind = ""; + int i; + for (i = 0; i < indent_impl_; ++i) { + ind += " "; + } + return ind; + }; + std::ostream& indent_impl(std::ostream& os) { return os << indent_impl(); }; +}; + +string t_delphi_generator::replace_all(string contents, string search, string repl) { + string str(contents); + + size_t slen = search.length(); + size_t rlen = repl.length(); + size_t incr = (rlen > 0) ? rlen : 1; + + if (slen > 0) { + size_t found = str.find(search); + while ((found != string::npos) && (found < str.length())) { + str.replace(found, slen, repl); + found = str.find(search, found + incr); + } + } + + return str; +} + +// XML encoding +string t_delphi_generator::xml_encode(string contents) { + string str(contents); + + // escape the escape + str = replace_all(str, "&", "&"); + + // other standard XML entities + str = replace_all(str, "<", "<"); + str = replace_all(str, ">", ">"); + + return str; +} + +// XML attribute encoding +string t_delphi_generator::xmlattrib_encode(string contents) { + string str(xml_encode(contents)); + + // our attribs are enclosed in " + str = replace_all(str, "\"", "\\\""); + + return str; +} + +// XML encoding for doc comments +string t_delphi_generator::xmldoc_encode(string contents) { + string str(xml_encode(contents)); + + // XMLDoc specific: convert linebreaks into <para>graphs</para> + str = replace_all(str, "\r\n", "\r"); + str = replace_all(str, "\n", "\r"); + str = replace_all(str, "\r", "</para>\n<para>"); + + return str; +} + +void t_delphi_generator::generate_delphi_docstring_comment(ostream& out, string contents) { + if (xmldoc_) { + generate_docstring_comment(out, + "{$REGION 'XMLDoc'}/// <summary>\n", + "/// ", + "<para>" + contents + "</para>", + "/// </summary>\n{$ENDREGION}\n"); + } +} + +void t_delphi_generator::generate_delphi_doc(ostream& out, t_field* field) { + if (xmldoc_) { + if (field->get_type()->is_enum()) { + string combined_message = xmldoc_encode(field->get_doc()) + "\n<seealso cref=\"" + + xmldoc_encode(type_name(field->get_type())) + "\"/>"; + generate_delphi_docstring_comment(out, combined_message); + } else { + generate_delphi_doc(out, (t_doc*)field); + } + } +} + +void t_delphi_generator::generate_delphi_doc(ostream& out, t_doc* tdoc) { + if (tdoc->has_doc() && xmldoc_) { + generate_delphi_docstring_comment(out, xmldoc_encode(tdoc->get_doc())); + } +} + +void t_delphi_generator::generate_delphi_doc(ostream& out, t_function* tfunction) { + if (tfunction->has_doc() && xmldoc_) { + stringstream ps; + const vector<t_field*>& fields = tfunction->get_arglist()->get_members(); + vector<t_field*>::const_iterator p_iter; + for (p_iter = fields.begin(); p_iter != fields.end(); ++p_iter) { + t_field* p = *p_iter; + ps << "\n<param name=\"" << xmlattrib_encode(p->get_name()) << "\">"; + if (p->has_doc()) { + std::string str = p->get_doc(); + str.erase(std::remove(str.begin(), str.end(), '\n'), + str.end()); // remove the newlines that appear from the parser + ps << xmldoc_encode(str); + } + ps << "</param>"; + } + generate_docstring_comment(out, + "{$REGION 'XMLDoc'}", + "/// ", + "<summary><para>" + xmldoc_encode(tfunction->get_doc()) + + "</para></summary>" + ps.str(), + "{$ENDREGION}\n"); + } +} + +bool t_delphi_generator::find_keyword(std::map<std::string, int>& keyword_map, std::string name) { + std::string::size_type len = name.length(); + + if (len <= 0) { + return false; + } + + std::string::size_type nlast = name.find_last_of('_'); + + if (nlast >= 1) { + if (nlast == (len - 1)) { + string new_name(name, 0, nlast); + return find_keyword(keyword_map, new_name); + } + } + return (keyword_map[name] == 1); +} + +std::string t_delphi_generator::normalize_name(std::string name, + bool b_method, + bool b_exception_method) { + string tmp(name); + std::transform(tmp.begin(), tmp.end(), tmp.begin(), static_cast<int (*)(int)>(std::tolower)); + + bool b_found = false; + + if (find_keyword(delphi_keywords, tmp)) { + b_found = true; + } else if (b_method && find_keyword(delphi_reserved_method, tmp)) { + b_found = true; + } else if (b_exception_method && find_keyword(delphi_reserved_method_exception, tmp)) { + b_found = true; + } + + if (b_found) { + return name + "_"; + } else { + return name; + } +} + +void t_delphi_generator::create_keywords() { + delphi_keywords["and"] = 1; + delphi_keywords["end"] = 1; + delphi_keywords["interface"] = 1; + delphi_keywords["raise"] = 1; + delphi_keywords["uses"] = 1; + delphi_keywords["array"] = 1; + delphi_keywords["except"] = 1; + delphi_keywords["is"] = 1; + delphi_keywords["record"] = 1; + delphi_keywords["var"] = 1; + delphi_keywords["as"] = 1; + delphi_keywords["exports"] = 1; + delphi_keywords["label"] = 1; + delphi_keywords["repeat"] = 1; + delphi_keywords["while"] = 1; + delphi_keywords["asm"] = 1; + delphi_keywords["file"] = 1; + delphi_keywords["library"] = 1; + delphi_keywords["resourcestring"] = 1; + delphi_keywords["with"] = 1; + delphi_keywords["begin"] = 1; + delphi_keywords["finalization"] = 1; + delphi_keywords["mod"] = 1; + delphi_keywords["set"] = 1; + delphi_keywords["xor"] = 1; + delphi_keywords["case"] = 1; + delphi_keywords["finally"] = 1; + delphi_keywords["nil"] = 1; + delphi_keywords["shl"] = 1; + delphi_keywords["class"] = 1; + delphi_keywords["for"] = 1; + delphi_keywords["not"] = 1; + delphi_keywords["shr"] = 1; + delphi_keywords["const"] = 1; + delphi_keywords["function"] = 1; + delphi_keywords["object"] = 1; + delphi_keywords["string"] = 1; + delphi_keywords["constructor"] = 1; + delphi_keywords["goto"] = 1; + delphi_keywords["of"] = 1; + delphi_keywords["then"] = 1; + delphi_keywords["destructor"] = 1; + delphi_keywords["if"] = 1; + delphi_keywords["or"] = 1; + delphi_keywords["threadvar"] = 1; + delphi_keywords["dispinterface"] = 1; + delphi_keywords["implementation"] = 1; + delphi_keywords["out"] = 1; + delphi_keywords["to"] = 1; + delphi_keywords["div"] = 1; + delphi_keywords["in"] = 1; + delphi_keywords["packed"] = 1; + delphi_keywords["try"] = 1; + delphi_keywords["do"] = 1; + delphi_keywords["inherited"] = 1; + delphi_keywords["procedure"] = 1; + delphi_keywords["type"] = 1; + delphi_keywords["downto"] = 1; + delphi_keywords["initialization"] = 1; + delphi_keywords["program"] = 1; + delphi_keywords["unit"] = 1; + delphi_keywords["else"] = 1; + delphi_keywords["inline"] = 1; + delphi_keywords["property"] = 1; + delphi_keywords["until"] = 1; + delphi_keywords["private"] = 1; + delphi_keywords["protected"] = 1; + delphi_keywords["public"] = 1; + delphi_keywords["published"] = 1; + delphi_keywords["automated"] = 1; + delphi_keywords["at"] = 1; + delphi_keywords["on"] = 1; + + // reserved/predefined variables and types (lowercase!) + delphi_keywords["result"] = 1; + delphi_keywords["tbytes"] = 1; + delphi_keywords["tobject"] = 1; + delphi_keywords["tclass"] = 1; + delphi_keywords["tinterfacedobject"] = 1; + + delphi_reserved_method["create"] = 1; + delphi_reserved_method["free"] = 1; + delphi_reserved_method["initinstance"] = 1; + delphi_reserved_method["cleanupinstance"] = 1; + delphi_reserved_method["classtype"] = 1; + delphi_reserved_method["classname"] = 1; + delphi_reserved_method["classnameis"] = 1; + delphi_reserved_method["classparent"] = 1; + delphi_reserved_method["classinfo"] = 1; + delphi_reserved_method["instancesize"] = 1; + delphi_reserved_method["inheritsfrom"] = 1; + delphi_reserved_method["methodaddress"] = 1; + delphi_reserved_method["methodaddress"] = 1; + delphi_reserved_method["methodname"] = 1; + delphi_reserved_method["fieldaddress"] = 1; + delphi_reserved_method["fieldaddress"] = 1; + delphi_reserved_method["getinterface"] = 1; + delphi_reserved_method["getinterfaceentry"] = 1; + delphi_reserved_method["getinterfacetable"] = 1; + delphi_reserved_method["unitname"] = 1; + delphi_reserved_method["equals"] = 1; + delphi_reserved_method["gethashcode"] = 1; + delphi_reserved_method["tostring"] = 1; + delphi_reserved_method["safecallexception"] = 1; + delphi_reserved_method["afterconstruction"] = 1; + delphi_reserved_method["beforedestruction"] = 1; + delphi_reserved_method["dispatch"] = 1; + delphi_reserved_method["defaulthandler"] = 1; + delphi_reserved_method["newinstance"] = 1; + delphi_reserved_method["freeinstance"] = 1; + delphi_reserved_method["destroy"] = 1; + delphi_reserved_method["read"] = 1; + delphi_reserved_method["write"] = 1; + + delphi_reserved_method_exception["setinnerexception"] = 1; + delphi_reserved_method_exception["setstackinfo"] = 1; + delphi_reserved_method_exception["getstacktrace"] = 1; + delphi_reserved_method_exception["raisingexception"] = 1; + delphi_reserved_method_exception["createfmt"] = 1; + delphi_reserved_method_exception["createres"] = 1; + delphi_reserved_method_exception["createresfmt"] = 1; + delphi_reserved_method_exception["createhelp"] = 1; + delphi_reserved_method_exception["createfmthelp"] = 1; + delphi_reserved_method_exception["createreshelp"] = 1; + delphi_reserved_method_exception["createresfmthelp"] = 1; + delphi_reserved_method_exception["getbaseexception"] = 1; + delphi_reserved_method_exception["baseexception"] = 1; + delphi_reserved_method_exception["helpcontext"] = 1; + delphi_reserved_method_exception["innerexception"] = 1; + delphi_reserved_method_exception["message"] = 1; + delphi_reserved_method_exception["stacktrace"] = 1; + delphi_reserved_method_exception["stackinfo"] = 1; + delphi_reserved_method_exception["getexceptionstackinfoproc"] = 1; + delphi_reserved_method_exception["getstackinfostringproc"] = 1; + delphi_reserved_method_exception["cleanupstackinfoproc"] = 1; + delphi_reserved_method_exception["raiseouterexception"] = 1; + delphi_reserved_method_exception["throwouterexception"] = 1; +} + +void t_delphi_generator::add_delphi_uses_list(string unitname) { + vector<std::string>::const_iterator s_iter; + bool found = false; + for (s_iter = uses_list.begin(); s_iter != uses_list.end(); ++s_iter) { + if ((*s_iter) == unitname) { + found = true; + break; + } + } + if (!found) { + uses_list.push_back(unitname); + } +} + +void t_delphi_generator::init_generator() { + indent_impl_ = 0; + namespace_name_ = program_->get_namespace("delphi"); + has_forward = false; + has_enum = false; + has_const = false; + create_keywords(); + add_delphi_uses_list("Classes"); + add_delphi_uses_list("SysUtils"); + add_delphi_uses_list("Generics.Collections"); + add_delphi_uses_list("Thrift"); + add_delphi_uses_list("Thrift.Utils"); + add_delphi_uses_list("Thrift.Collections"); + add_delphi_uses_list("Thrift.Protocol"); + add_delphi_uses_list("Thrift.Transport"); + + if (register_types_) { + add_delphi_uses_list("Thrift.TypeRegistry"); + } + + init_known_types_list(); + + string unitname, nsname; + const vector<t_program*>& includes = program_->get_includes(); + for (size_t i = 0; i < includes.size(); ++i) { + unitname = includes[i]->get_name(); + nsname = includes[i]->get_namespace("delphi"); + if ("" != nsname) { + unitname = nsname; + } + add_delphi_uses_list(unitname); + } + + MKDIR(get_out_dir().c_str()); +} + +void t_delphi_generator::close_generator() { + std::string unitname = program_name_; + if ("" != namespace_name_) { + unitname = namespace_name_; + } + + for (int i = 0; i < (int)unitname.size(); i++) { + if (unitname[i] == ' ') { + unitname.replace(i, 1, "_"); + } + } + + std::string f_name = get_out_dir() + "/" + unitname + ".pas"; + std::ofstream f_all; + + f_all.open(f_name.c_str()); + + f_all << autogen_comment() << endl; + generate_delphi_doc(f_all, program_); + f_all << "unit " << unitname << ";" << endl << endl; + f_all << "interface" << endl << endl; + f_all << "uses" << endl; + + indent_up(); + + vector<std::string>::const_iterator s_iter; + for (s_iter = uses_list.begin(); s_iter != uses_list.end(); ++s_iter) { + if (s_iter != uses_list.begin()) { + f_all << ","; + f_all << endl; + } + indent(f_all) << *s_iter; + } + + f_all << ";" << endl << endl; + + indent_down(); + + string tmp_unit(unitname); + for (int i = 0; i < (int)tmp_unit.size(); i++) { + if (tmp_unit[i] == '.') { + tmp_unit.replace(i, 1, "_"); + } + } + + f_all << "const" << endl; + indent_up(); + indent(f_all) << "c" << tmp_unit + << "_Option_AnsiStr_Binary = " << (ansistr_binary_ ? "True" : "False") << ";" + << endl; + indent(f_all) << "c" << tmp_unit + << "_Option_Register_Types = " << (register_types_ ? "True" : "False") << ";" + << endl; + indent(f_all) << "c" << tmp_unit + << "_Option_ConstPrefix = " << (constprefix_ ? "True" : "False") << ";" << endl; + indent(f_all) << "c" << tmp_unit << "_Option_Events = " << (events_ ? "True" : "False") + << ";" << endl; + indent(f_all) << "c" << tmp_unit << "_Option_XmlDoc = " << (xmldoc_ ? "True" : "False") + << ";" << endl; + indent_down(); + + f_all << endl; + f_all << "type" << endl; + if (has_forward) { + f_all << s_forward_decr.str() << endl; + } + if (has_enum) { + indent(f_all) << endl; + indent(f_all) << "{$SCOPEDENUMS ON}" << endl << endl; + f_all << s_enum.str(); + indent(f_all) << "{$SCOPEDENUMS OFF}" << endl << endl; + } + f_all << s_struct.str(); + f_all << s_service.str(); + f_all << s_const.str(); + f_all << "implementation" << endl << endl; + f_all << s_struct_impl.str(); + f_all << s_service_impl.str(); + f_all << s_const_impl.str(); + + if (register_types_) { + f_all << endl; + f_all << "// Type factory methods and registration" << endl; + f_all << s_type_factory_funcs.str(); + f_all << "procedure RegisterTypeFactories;" << endl; + f_all << "begin" << endl; + f_all << s_type_factory_registration.str(); + f_all << "end;" << endl; + } + f_all << endl; + + string constants_class = make_constants_classname(); + + f_all << "initialization" << endl; + if (has_const) { + f_all << "{$IF CompilerVersion < 21.0} // D2010" << endl; + f_all << " " << constants_class.c_str() << "_Initialize;" << endl; + f_all << "{$IFEND}" << endl; + } + if (register_types_) { + f_all << " RegisterTypeFactories;" << endl; + } + f_all << endl; + + f_all << "finalization" << endl; + if (has_const) { + f_all << "{$IF CompilerVersion < 21.0} // D2010" << endl; + f_all << " " << constants_class.c_str() << "_Finalize;" << endl; + f_all << "{$IFEND}" << endl; + } + f_all << endl << endl; + + f_all << "end." << endl; + f_all.close(); + + if (!typedefs_pending.empty()) { + pwarning(0, "%d typedefs with unresolved type references left:\n", typedefs_pending.size()); + for (std::list<t_typedef*>::iterator iter = typedefs_pending.begin(); + typedefs_pending.end() != iter; + ++iter) { + pwarning(0, "- %s\n", (*iter)->get_symbolic().c_str()); + } + } +} + +void t_delphi_generator::delphi_type_usings(ostream& out) { + indent_up(); + indent(out) << "Classes, SysUtils, Generics.Collections, Thrift.Collections, Thrift.Protocol," + << endl; + indent(out) << "Thrift.Transport;" << endl << endl; + indent_down(); +} + +void t_delphi_generator::generate_forward_declaration(t_struct* tstruct) { + // Forward declare struct def + has_forward = true; + pverbose("forward declaration of %s\n", type_name(tstruct).c_str()); + + string what = tstruct->is_xception() ? "class" : "interface"; + + indent_up(); + indent(s_forward_decr) << type_name(tstruct, tstruct->is_xception(), true) << " = " << what << ";" + << endl; + indent_down(); + + add_defined_type(tstruct); +} + +void t_delphi_generator::generate_typedef(t_typedef* ttypedef) { + t_type* type = ttypedef->get_type(); + + // write now or save for later? + if (!is_fully_defined_type(type)) { + pverbose("typedef %s: unresolved dependencies found\n", type_name(ttypedef).c_str()); + typedefs_pending.push_back(ttypedef); + return; + } + + indent_up(); + generate_delphi_doc(s_struct, ttypedef); + indent(s_struct) << type_name(ttypedef) << " = "; + + // commented out: the benefit is not big enough to risk breaking existing code + // bool container = type->is_list() || type->is_map() || type->is_set(); + // if( ! container) + // s_struct << "type "; //the "type A = type B" syntax leads to E2574 with generics + + s_struct << type_name(ttypedef->get_type()) << ";" << endl << endl; + indent_down(); + + add_defined_type(ttypedef); +} + +bool t_delphi_generator::is_fully_defined_type(t_type* ttype) { + if ((NULL != ttype->get_program()) && (ttype->get_program() != program_)) { + t_scope* scope = ttype->get_program()->scope(); + if (NULL != scope->get_type(ttype->get_name())) { + // printf("type %s found in included scope %s\n", ttype->get_name().c_str(), + // ttype->get_program()->get_name().c_str()); + return true; + } + } + + if (ttype->is_typedef()) { + return (1 == types_known[type_name(ttype)]); + } + + if (ttype->is_base_type()) { + return (1 == types_known[base_type_name((t_base_type*)ttype)]); + } else if (ttype->is_enum()) { + return true; // enums are written first, before all other types + } else if (ttype->is_map()) { + t_map* tmap = (t_map*)ttype; + return is_fully_defined_type(tmap->get_key_type()) + && is_fully_defined_type(tmap->get_val_type()); + } else if (ttype->is_set()) { + t_set* tset = (t_set*)ttype; + return is_fully_defined_type(tset->get_elem_type()); + } else if (ttype->is_list()) { + t_list* tlist = (t_list*)ttype; + return is_fully_defined_type(tlist->get_elem_type()); + } + + return (1 == types_known[type_name(ttype)]); +} + +void t_delphi_generator::add_defined_type(t_type* ttype) { + // mark as known type + types_known[type_name(ttype)] = 1; + + // check all pending typedefs + std::list<t_typedef*>::iterator iter; + bool more = true; + while (more && (!typedefs_pending.empty())) { + more = false; + + for (iter = typedefs_pending.begin(); typedefs_pending.end() != iter; ++iter) { + t_typedef* ttypedef = (*iter); + if (is_fully_defined_type(ttypedef->get_type())) { + pverbose("typedef %s: all pending references are now resolved\n", + type_name(ttypedef).c_str()); + typedefs_pending.erase(iter); + generate_typedef(ttypedef); + more = true; + break; + } + } + } +} + +void t_delphi_generator::init_known_types_list() { + // known base types + types_known[type_name(g_type_string)] = 1; + types_known[type_name(g_type_binary)] = 1; + types_known[type_name(g_type_bool)] = 1; + types_known[type_name(g_type_byte)] = 1; + types_known[type_name(g_type_i16)] = 1; + types_known[type_name(g_type_i32)] = 1; + types_known[type_name(g_type_i64)] = 1; + types_known[type_name(g_type_double)] = 1; +} + +void t_delphi_generator::generate_enum(t_enum* tenum) { + has_enum = true; + indent_up(); + generate_delphi_doc(s_enum, tenum); + indent(s_enum) << type_name(tenum, true, true) << " = " + << "(" << endl; + indent_up(); + vector<t_enum_value*> constants = tenum->get_constants(); + if (constants.empty()) { + indent(s_enum) << "dummy = 0 // empty enums are not allowed"; + } else { + vector<t_enum_value*>::iterator c_iter; + for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) { + int value = (*c_iter)->get_value(); + if (c_iter != constants.begin()) { + s_enum << ","; + s_enum << endl; + } + generate_delphi_doc(s_enum, *c_iter); + indent(s_enum) << normalize_name((*c_iter)->get_name()) << " = " << value; + } + } + s_enum << endl; + indent_down(); + indent(s_enum) << ");" << endl << endl; + indent_down(); +} + +std::string t_delphi_generator::make_valid_delphi_identifier(std::string const& fromName) { + std::string str = fromName; + if (str.empty()) { + return str; + } + + // tests rely on this + assert(('A' < 'Z') && ('a' < 'z') && ('0' < '9')); + + // if the first letter is a number, we add an additional underscore in front of it + char c = str.at(0); + if (('0' <= c) && (c <= '9')) { + str = "_" + str; + } + + // following chars: letter, number or underscore + for (size_t i = 0; i < str.size(); ++i) { + c = str.at(i); + if ((('A' > c) || (c > 'Z')) && (('a' > c) || (c > 'z')) && (('0' > c) || (c > '9')) + && ('_' != c)) { + str.replace(i, 1, "_"); + } + } + + return str; +} + +std::string t_delphi_generator::make_constants_classname() { + if (constprefix_) { + return make_valid_delphi_identifier("T" + program_name_ + "Constants"); + } else { + return "TConstants"; // compatibility + } +} + +void t_delphi_generator::generate_consts(std::vector<t_const*> consts) { + if (consts.empty()) { + return; + } + + has_const = true; + string constants_class = make_constants_classname(); + + indent_up(); + indent(s_const) << constants_class.c_str() << " = class" << endl; + indent(s_const) << "private" << endl; + indent_up(); + vector<t_const*>::iterator c_iter; + for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) { + if (const_needs_var((*c_iter)->get_type())) { + print_private_field(s_const, + normalize_name((*c_iter)->get_name()), + (*c_iter)->get_type(), + (*c_iter)->get_value()); + } + } + indent_down(); + indent(s_const) << "public" << endl; + indent_up(); + for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) { + generate_delphi_doc(s_const, *c_iter); + print_const_prop(s_const, + normalize_name((*c_iter)->get_name()), + (*c_iter)->get_type(), + (*c_iter)->get_value()); + } + indent(s_const) << "{$IF CompilerVersion >= 21.0}" << endl; + indent(s_const) << "class constructor Create;" << endl; + indent(s_const) << "class destructor Destroy;" << endl; + indent(s_const) << "{$IFEND}" << endl; + indent_down(); + indent(s_const) << "end;" << endl << endl; + indent_down(); + + std::ostringstream vars, code; + + indent_up_impl(); + for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) { + initialize_field(vars, + code, + "F" + prop_name((*c_iter)->get_name()), + (*c_iter)->get_type(), + (*c_iter)->get_value()); + } + indent_down_impl(); + + indent_impl(s_const_impl) << "{$IF CompilerVersion >= 21.0}" << endl; + indent_impl(s_const_impl) << "class constructor " << constants_class.c_str() << ".Create;" + << endl; + + if (!vars.str().empty()) { + indent_impl(s_const_impl) << "var" << endl; + s_const_impl << vars.str(); + } + indent_impl(s_const_impl) << "begin" << endl; + if (!code.str().empty()) { + s_const_impl << code.str(); + } + indent_impl(s_const_impl) << "end;" << endl << endl; + indent_impl(s_const_impl) << "class destructor " << constants_class.c_str() << ".Destroy;" + << endl; + indent_impl(s_const_impl) << "begin" << endl; + indent_up_impl(); + for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) { + if (const_needs_var((*c_iter)->get_type())) { + finalize_field(s_const_impl, + normalize_name((*c_iter)->get_name()), + (*c_iter)->get_type(), + (*c_iter)->get_value()); + } + } + indent_impl(s_const_impl) << "inherited;" << endl; + indent_down_impl(); + indent_impl(s_const_impl) << "end;" << endl; + indent_impl(s_const_impl) << "{$ELSE}" << endl; + + vars.str(""); + code.str(""); + + indent_up_impl(); + for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) { + if (const_needs_var((*c_iter)->get_type())) { + initialize_field(vars, + code, + constants_class + ".F" + prop_name((*c_iter)->get_name()), + (*c_iter)->get_type(), + (*c_iter)->get_value()); + } + } + indent_down_impl(); + + indent_impl(s_const_impl) << "procedure " << constants_class.c_str() << "_Initialize;" << endl; + if (!vars.str().empty()) { + indent_impl(s_const_impl) << "var" << endl; + s_const_impl << vars.str(); + } + indent_impl(s_const_impl) << "begin" << endl; + if (!code.str().empty()) { + s_const_impl << code.str(); + } + indent_impl(s_const_impl) << "end;" << endl << endl; + + indent_impl(s_const_impl) << "procedure " << constants_class.c_str() << "_Finalize;" << endl; + indent_impl(s_const_impl) << "begin" << endl; + indent_up_impl(); + for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) { + finalize_field(s_const_impl, + normalize_name((*c_iter)->get_name()), + (*c_iter)->get_type(), + (*c_iter)->get_value(), + constants_class); + } + indent_down_impl(); + indent_impl(s_const_impl) << "end;" << endl; + indent_impl(s_const_impl) << "{$IFEND}" << endl << endl; +} + +void t_delphi_generator::print_const_def_value(std::ostream& vars, + std::ostream& out, + string name, + t_type* type, + t_const_value* value, + string cls_nm) { + + string cls_prefix; + + if (cls_nm == "") { + cls_prefix = ""; + } else { + cls_prefix = cls_nm + "."; + } + + if (type->is_struct() || type->is_xception()) { + const vector<t_field*>& fields = ((t_struct*)type)->get_members(); + vector<t_field*>::const_iterator f_iter; + const map<t_const_value*, t_const_value*>& val = value->get_map(); + map<t_const_value*, t_const_value*>::const_iterator v_iter; + for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { + t_type* field_type = NULL; + for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { + if ((*f_iter)->get_name() == v_iter->first->get_string()) { + field_type = (*f_iter)->get_type(); + } + } + if (field_type == NULL) { + throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string(); + } + string val = render_const_value(vars, out, name, field_type, v_iter->second); + indent_impl(out) << cls_prefix << normalize_name(name) << "." + << prop_name(v_iter->first->get_string(), type->is_xception()) + << " := " << val << ";" << endl; + } + } else if (type->is_map()) { + t_type* ktype = ((t_map*)type)->get_key_type(); + t_type* vtype = ((t_map*)type)->get_val_type(); + const map<t_const_value*, t_const_value*>& val = value->get_map(); + map<t_const_value*, t_const_value*>::const_iterator v_iter; + for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { + string key = render_const_value(vars, out, name, ktype, v_iter->first); + string val = render_const_value(vars, out, name, vtype, v_iter->second); + indent_impl(out) << cls_prefix << normalize_name(name) << "[" << key << "]" + << " := " << val << ";" << endl; + } + } else if (type->is_list() || type->is_set()) { + t_type* etype; + if (type->is_list()) { + etype = ((t_list*)type)->get_elem_type(); + } else { + etype = ((t_set*)type)->get_elem_type(); + } + + const vector<t_const_value*>& val = value->get_list(); + vector<t_const_value*>::const_iterator v_iter; + for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { + string val = render_const_value(vars, out, name, etype, *v_iter); + indent_impl(out) << cls_prefix << normalize_name(name) << ".Add(" << val << ");" << endl; + } + } +} + +void t_delphi_generator::print_private_field(std::ostream& out, + string name, + t_type* type, + t_const_value* value) { + (void)value; + indent(out) << "class var F" << name << ": " << type_name(type) << ";" << endl; +} + +bool t_delphi_generator::const_needs_var(t_type* type) { + t_type* truetype = type; + while (truetype->is_typedef()) { + truetype = ((t_typedef*)truetype)->get_type(); + } + return (!truetype->is_base_type()); +} + +void t_delphi_generator::print_const_prop(std::ostream& out, + string name, + t_type* type, + t_const_value* value) { + (void)value; + if (const_needs_var(type)) { + indent(out) << "class property " << name << ": " << type_name(type) << " read F" << name << ";" + << endl; + } else { + std::ostringstream vars; // dummy + string v2 = render_const_value(vars, out, name, type, value); + indent(out) << "const " << name << " = " << v2 << ";" << endl; + } +} + +void t_delphi_generator::print_const_value(std::ostream& vars, + std::ostream& out, + string name, + t_type* type, + t_const_value* value) { + t_type* truetype = type; + while (truetype->is_typedef()) { + truetype = ((t_typedef*)truetype)->get_type(); + } + + if (truetype->is_base_type()) { + // already done + // string v2 = render_const_value( vars, out, name, type, value); + // indent_impl(out) << name << " := " << v2 << ";" << endl; + } else if (truetype->is_enum()) { + indent_impl(out) << name << " := " << type_name(type) << "." << value->get_identifier_name() + << ";" << endl; + } else { + string typname; + typname = type_name(truetype, true, false, type->is_xception(), type->is_xception()); + indent_impl(out) << name << " := " << typname << ".Create;" << endl; + print_const_def_value(vars, out, name, truetype, value); + } +} + +void t_delphi_generator::initialize_field(std::ostream& vars, + std::ostream& out, + string name, + t_type* type, + t_const_value* value) { + print_const_value(vars, out, name, type, value); +} + +void t_delphi_generator::finalize_field(std::ostream& out, + string name, + t_type* type, + t_const_value* value, + string cls_nm) { + (void)out; + (void)name; + (void)type; + (void)value; + (void)cls_nm; +} + +string t_delphi_generator::render_const_value(ostream& vars, + ostream& out, + string name, + t_type* type, + t_const_value* value) { + (void)name; + + t_type* truetype = type; + while (truetype->is_typedef()) { + truetype = ((t_typedef*)truetype)->get_type(); + } + + std::ostringstream render; + + if (truetype->is_base_type()) { + t_base_type::t_base tbase = ((t_base_type*)truetype)->get_base(); + switch (tbase) { + case t_base_type::TYPE_STRING: + render << "'" << get_escaped_string(value) << "'"; + break; + case t_base_type::TYPE_BOOL: + render << ((value->get_integer() > 0) ? "True" : "False"); + break; + case t_base_type::TYPE_BYTE: + render << "ShortInt( " << value->get_integer() << ")"; + break; + case t_base_type::TYPE_I16: + render << "SmallInt( " << value->get_integer() << ")"; + break; + case t_base_type::TYPE_I32: + render << "LongInt( " << value->get_integer() << ")"; + break; + case t_base_type::TYPE_I64: + render << "Int64( " << value->get_integer() << ")"; + break; + case t_base_type::TYPE_DOUBLE: + if (value->get_type() == t_const_value::CV_INTEGER) { + render << value->get_integer() << ".0"; // make it a double constant by adding ".0" + } else { + render << value->get_double(); + } + break; + default: + throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase); + } + } else if (truetype->is_enum()) { + render << type_name(type, false) << "." << value->get_identifier_name(); + } else { + string t = tmp("tmp"); + vars << " " << t << " : " << type_name(type) << ";" << endl; + print_const_value(vars, out, t, type, value); + render << t; + } + + return render.str(); +} + +void t_delphi_generator::generate_struct(t_struct* tstruct) { + generate_delphi_struct(tstruct, false); +} + +void t_delphi_generator::generate_xception(t_struct* txception) { + generate_delphi_struct(txception, true); +} + +void t_delphi_generator::generate_delphi_struct(t_struct* tstruct, bool is_exception) { + indent_up(); + generate_delphi_struct_definition(s_struct, tstruct, is_exception); + indent_down(); + + add_defined_type(tstruct); + + generate_delphi_struct_impl(s_struct_impl, "", tstruct, is_exception); + if (register_types_) { + generate_delphi_struct_type_factory(s_type_factory_funcs, "", tstruct, is_exception); + generate_delphi_struct_type_factory_registration(s_type_factory_registration, + "", + tstruct, + is_exception); + } +} + +void t_delphi_generator::generate_delphi_struct_impl(ostream& out, + string cls_prefix, + t_struct* tstruct, + bool is_exception, + bool is_result, + bool is_x_factory) { + + if (is_exception && (!is_x_factory)) { + generate_delphi_struct_impl(out, cls_prefix, tstruct, is_exception, is_result, true); + } + + string cls_nm; + + string exception_factory_name; + + if (is_exception) { + exception_factory_name = normalize_clsnm(tstruct->get_name(), "", true) + "Factory"; + } + + if (is_exception) { + cls_nm = type_name(tstruct, true, (!is_x_factory), is_x_factory, true); + } else { + cls_nm = type_name(tstruct, true, false); + } + + std::ostringstream vars, code; + + const vector<t_field*>& members = tstruct->get_members(); + vector<t_field*>::const_iterator m_iter; + + indent_up_impl(); + for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { + t_type* t = (*m_iter)->get_type(); + while (t->is_typedef()) { + t = ((t_typedef*)t)->get_type(); + } + if ((*m_iter)->get_value() != NULL) { + initialize_field(vars, + code, + "F" + prop_name((*m_iter)->get_name(), is_exception), + t, + (*m_iter)->get_value()); + if ((*m_iter)->get_req() != t_field::T_REQUIRED) { + indent_impl(code) << "F__isset_" << prop_name((*m_iter), is_exception) << " := True;" + << endl; + } + } + } + indent_down_impl(); + + indent_impl(out) << "constructor " << cls_prefix << cls_nm << "." + << "Create;" << endl; + + if (!vars.str().empty()) { + out << "var" << endl; + out << vars.str(); + } + + indent_impl(out) << "begin" << endl; + indent_up_impl(); + if (is_exception && (!is_x_factory)) { + indent_impl(out) << "inherited Create('');" << endl; + indent_impl(out) << "F" << exception_factory_name << " := T" << exception_factory_name + << "Impl.Create;" << endl; + } else { + indent_impl(out) << "inherited;" << endl; + } + + if (!code.str().empty()) { + out << code.str(); + } + + indent_down_impl(); + indent_impl(out) << "end;" << endl << endl; + + if ((members.size() > 0) && is_exception && (!is_x_factory)) { + indent_impl(out) << "constructor " << cls_prefix << cls_nm << "." + << "Create(" << constructor_argument_list(tstruct, indent_impl()) << ");" + << endl; + indent_impl(out) << "begin" << endl; + indent_up_impl(); + indent_impl(out) << "Create;" << endl; + for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { + string propname = prop_name((*m_iter)->get_name(), is_exception); + string param_name = constructor_param_name((*m_iter)->get_name()); + indent_impl(out) << propname << " := " << param_name << ";" << endl; + } + indent_impl(out) << "UpdateMessageProperty;" << endl; + indent_down_impl(); + indent_impl(out) << "end;" << endl << endl; + } + + indent_impl(out) << "destructor " << cls_prefix << cls_nm << "." + << "Destroy;" << endl; + indent_impl(out) << "begin" << endl; + indent_up_impl(); + + for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { + t_type* t = (*m_iter)->get_type(); + while (t->is_typedef()) { + t = ((t_typedef*)t)->get_type(); + } + finalize_field(out, prop_name(*m_iter, is_exception), t, (*m_iter)->get_value()); + } + + indent_impl(out) << "inherited;" << endl; + indent_down_impl(); + indent_impl(out) << "end;" << endl << endl; + + if (tstruct->is_union()) { + indent_impl(out) << "procedure " << cls_prefix << cls_nm << "." + << "ClearUnionValues;" << endl; + indent_impl(out) << "begin" << endl; + indent_up_impl(); + for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { + t_type* t = (*m_iter)->get_type(); + while (t->is_typedef()) { + t = ((t_typedef*)t)->get_type(); + } + + generate_delphi_clear_union_value(out, + cls_prefix, + cls_nm, + t, + *m_iter, + "F", + is_exception, + tstruct->is_union(), + is_x_factory, + exception_factory_name); + } + indent_down_impl(); + indent_impl(out) << "end;" << endl << endl; + } + + for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { + t_type* t = (*m_iter)->get_type(); + while (t->is_typedef()) { + t = ((t_typedef*)t)->get_type(); + } + generate_delphi_property_reader_impl(out, cls_prefix, cls_nm, t, *m_iter, "F", is_exception); + generate_delphi_property_writer_impl(out, + cls_prefix, + cls_nm, + t, + *m_iter, + "F", + is_exception, + tstruct->is_union(), + is_x_factory, + exception_factory_name); + if ((*m_iter)->get_req() != t_field::T_REQUIRED) { + generate_delphi_isset_reader_impl(out, cls_prefix, cls_nm, t, *m_iter, "F", is_exception); + } + } + + if ((!is_exception) || is_x_factory) { + generate_delphi_struct_reader_impl(out, cls_prefix, tstruct, is_exception); + if (is_result) { + generate_delphi_struct_result_writer_impl(out, cls_prefix, tstruct, is_exception); + } else { + generate_delphi_struct_writer_impl(out, cls_prefix, tstruct, is_exception); + } + } + generate_delphi_struct_tostring_impl(out, cls_prefix, tstruct, is_exception, is_x_factory); + + if (is_exception && is_x_factory) { + generate_delphi_create_exception_impl(out, cls_prefix, tstruct, is_exception); + } +} + +void t_delphi_generator::print_delphi_struct_type_factory_func(ostream& out, t_struct* tstruct) { + string struct_intf_name = type_name(tstruct); + out << "Create_"; + out << struct_intf_name; + out << "_Impl"; +} + +void t_delphi_generator::generate_delphi_struct_type_factory(ostream& out, + string cls_prefix, + t_struct* tstruct, + bool is_exception, + bool is_result, + bool is_x_factory) { + (void)cls_prefix; + if (is_exception) + return; + if (is_result) + return; + if (is_x_factory) + return; + + string struct_intf_name = type_name(tstruct); + string cls_nm = type_name(tstruct, true, false); + + out << "function "; + print_delphi_struct_type_factory_func(out, tstruct); + out << ": "; + out << struct_intf_name; + out << ";" << endl; + out << "begin" << endl; + indent_up(); + indent(out) << "Result := " << cls_nm << ".Create;" << endl; + indent_down(); + out << "end;" << endl << endl; +} + +void t_delphi_generator::generate_delphi_struct_type_factory_registration(ostream& out, + string cls_prefix, + t_struct* tstruct, + bool is_exception, + bool is_result, + bool is_x_factory) { + (void)cls_prefix; + if (is_exception) + return; + if (is_result) + return; + if (is_x_factory) + return; + + string struct_intf_name = type_name(tstruct); + + indent(out) << " TypeRegistry.RegisterTypeFactory<" << struct_intf_name << ">("; + print_delphi_struct_type_factory_func(out, tstruct); + out << ");"; + out << endl; +} + +void t_delphi_generator::generate_delphi_struct_definition(ostream& out, + t_struct* tstruct, + bool is_exception, + bool in_class, + bool is_result, + bool is_x_factory) { + bool is_final = (tstruct->annotations_.find("final") != tstruct->annotations_.end()); + string struct_intf_name; + string struct_name; + string isset_name; + const vector<t_field*>& members = tstruct->get_members(); + vector<t_field*>::const_iterator m_iter; + + string exception_factory_name = normalize_clsnm(tstruct->get_name(), "", true) + "Factory"; + + if (is_exception) { + struct_intf_name = type_name(tstruct, false, false, true); + } else { + struct_intf_name = type_name(tstruct); + } + + if (is_exception) { + struct_name = type_name(tstruct, true, (!is_x_factory), is_x_factory); + } else { + struct_name = type_name(tstruct, true); + } + + if ((!is_exception) || is_x_factory) { + + generate_delphi_doc(out, tstruct); + indent(out) << struct_intf_name << " = interface(IBase)" << endl; + indent_up(); + + for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { + generate_delphi_property_reader_definition(out, *m_iter, is_exception); + generate_delphi_property_writer_definition(out, *m_iter, is_exception); + } + + if (is_x_factory) { + out << endl; + indent(out) << "// Create Exception Object" << endl; + indent(out) << "function CreateException: " << type_name(tstruct, true, true) << ";" << endl; + } + + if (members.size() > 0) { + out << endl; + for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { + generate_property(out, *m_iter, true, is_exception); + } + } + + if (members.size() > 0) { + out << endl; + for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { + if ((*m_iter)->get_req() != t_field::T_REQUIRED) { + generate_delphi_isset_reader_definition(out, *m_iter, is_exception); + } + } + } + + if (members.size() > 0) { + out << endl; + for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { + if ((*m_iter)->get_req() != t_field::T_REQUIRED) { + isset_name = "__isset_" + prop_name(*m_iter, is_exception); + indent(out) << "property " << isset_name << ": Boolean read Get" << isset_name << ";" + << endl; + } + } + } + + indent_down(); + indent(out) << "end;" << endl << endl; + } + + generate_delphi_doc(out, tstruct); + indent(out) << struct_name << " = "; + if (is_final) { + out << "sealed "; + } + out << "class("; + if (is_exception && (!is_x_factory)) { + out << "TException"; + } else { + out << "TInterfacedObject, IBase, " << struct_intf_name; + } + out << ")" << endl; + + if (is_exception && (!is_x_factory)) { + indent(out) << "public" << endl; + indent_up(); + indent(out) << "type" << endl; + indent_up(); + generate_delphi_struct_definition(out, tstruct, is_exception, in_class, is_result, true); + indent_down(); + indent_down(); + } + + indent(out) << "private" << endl; + indent_up(); + + if (is_exception && (!is_x_factory)) { + indent(out) << "F" << exception_factory_name << " :" << struct_intf_name << ";" << endl << endl; + } + + for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { + indent(out) << declare_field(*m_iter, false, "F", is_exception) << endl; + } + + if (members.size() > 0) { + indent(out) << endl; + for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { + if ((*m_iter)->get_req() != t_field::T_REQUIRED) { + isset_name = "F__isset_" + prop_name(*m_iter, is_exception); + indent(out) << isset_name << ": Boolean;" << endl; + } + } + } + + indent(out) << endl; + + for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { + generate_delphi_property_reader_definition(out, *m_iter, is_exception); + generate_delphi_property_writer_definition(out, *m_iter, is_exception); + } + + if (tstruct->is_union()) { + out << endl; + indent(out) << "// Clear values(for union's property setter)" << endl; + indent(out) << "procedure ClearUnionValues;" << endl; + } + + if (members.size() > 0) { + out << endl; + for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { + if ((*m_iter)->get_req() != t_field::T_REQUIRED) { + isset_name = "__isset_" + prop_name(*m_iter, is_exception); + indent(out) << "function Get" << isset_name << ": Boolean;" << endl; + } + } + } + + indent_down(); + + indent(out) << "public" << endl; + indent_up(); + + if ((members.size() > 0) && is_exception && (!is_x_factory)) { + indent(out) << "constructor Create; overload;" << endl; + indent(out) << "constructor Create(" << constructor_argument_list(tstruct, indent()) + << "); overload;" << endl; + } else { + indent(out) << "constructor Create;" << endl; + } + + indent(out) << "destructor Destroy; override;" << endl; + + out << endl; + indent(out) << "function ToString: string; override;" << endl; + + if (is_exception && (!is_x_factory)) { + out << endl; + indent(out) << "// Exception Factory" << endl; + indent(out) << "property " << exception_factory_name << ": " << struct_intf_name << " read F" + << exception_factory_name << " write F" << exception_factory_name << ";" << endl; + } + + if ((!is_exception) || is_x_factory) { + out << endl; + indent(out) << "// IBase" << endl; + indent(out) << "procedure Read( const iprot: IProtocol);" << endl; + indent(out) << "procedure Write( const oprot: IProtocol);" << endl; + } + + if (is_exception && is_x_factory) { + out << endl; + indent(out) << "// Create Exception Object" << endl; + indent(out) << "function CreateException: " << type_name(tstruct, true, true) << ";" << endl; + } + + if (members.size() > 0) { + out << endl; + indent(out) << "// Properties" << endl; + for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { + generate_property(out, *m_iter, true, is_exception); + } + } + + if (members.size() > 0) { + out << endl; + indent(out) << "// isset" << endl; + for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { + if ((*m_iter)->get_req() != t_field::T_REQUIRED) { + isset_name = "__isset_" + prop_name(*m_iter, is_exception); + indent(out) << "property " << isset_name << ": Boolean read Get" << isset_name << ";" + << endl; + } + } + } + + indent_down(); + indent(out) << "end;" << endl << endl; +} + +void t_delphi_generator::generate_service(t_service* tservice) { + indent_up(); + generate_delphi_doc(s_service, tservice); + indent(s_service) << normalize_clsnm(service_name_, "T") << " = class" << endl; + indent(s_service) << "public" << endl; + indent_up(); + indent(s_service) << "type" << endl; + generate_service_interface(tservice); + generate_service_client(tservice); + generate_service_server(tservice); + generate_service_helpers(tservice); + indent_down(); + indent_down(); + indent(s_service) << "end;" << endl; + indent(s_service) << endl; + indent_down(); +} + +void t_delphi_generator::generate_service_interface(t_service* tservice) { + string extends = ""; + string extends_iface = ""; + + indent_up(); + + generate_delphi_doc(s_service, tservice); + if (tservice->get_extends() != NULL) { + extends = type_name(tservice->get_extends(), true, true); + extends_iface = extends + ".Iface"; + generate_delphi_doc(s_service, tservice); + indent(s_service) << "Iface = interface(" << extends_iface << ")" << endl; + } else { + indent(s_service) << "Iface = interface" << endl; + } + + indent_up(); + vector<t_function*> functions = tservice->get_functions(); + vector<t_function*>::iterator f_iter; + for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { + generate_delphi_doc(s_service, *f_iter); + indent(s_service) << function_signature(*f_iter) << endl; + } + indent_down(); + indent(s_service) << "end;" << endl << endl; + + indent_down(); +} + +void t_delphi_generator::generate_service_helpers(t_service* tservice) { + vector<t_function*> functions = tservice->get_functions(); + vector<t_function*>::iterator f_iter; + + for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { + t_struct* ts = (*f_iter)->get_arglist(); + generate_delphi_struct_definition(s_service, ts, false, true); + generate_delphi_struct_impl(s_service_impl, + normalize_clsnm(service_name_, "T") + ".", + ts, + false); + generate_function_helpers(*f_iter); + } +} + +void t_delphi_generator::generate_service_client(t_service* tservice) { + indent_up(); + string extends = ""; + string extends_client = ""; + if (tservice->get_extends() != NULL) { + extends = type_name(tservice->get_extends()); + extends_client = extends + ".Client, "; + } + + generate_delphi_doc(s_service, tservice); + if (tservice->get_extends() != NULL) { + extends = type_name(tservice->get_extends(), true, true); + extends_client = extends + ".TClient"; + indent(s_service) << "TClient = class(" << extends_client << ", Iface)" << endl; + } else { + indent(s_service) << "TClient = class( TInterfacedObject, Iface)" << endl; + } + + indent(s_service) << "public" << endl; + indent_up(); + + indent(s_service) << "constructor Create( prot: IProtocol); overload;" << endl; + + indent_impl(s_service_impl) << "constructor " << normalize_clsnm(service_name_, "T") + << ".TClient.Create( prot: IProtocol);" << endl; + indent_impl(s_service_impl) << "begin" << endl; + indent_up_impl(); + indent_impl(s_service_impl) << "Create( prot, prot );" << endl; + indent_down_impl(); + indent_impl(s_service_impl) << "end;" << endl << endl; + + indent(s_service) + << "constructor Create( const iprot: IProtocol; const oprot: IProtocol); overload;" << endl; + + indent_impl(s_service_impl) << "constructor " << normalize_clsnm(service_name_, "T") + << ".TClient.Create( const iprot: IProtocol; const oprot: IProtocol);" + << endl; + indent_impl(s_service_impl) << "begin" << endl; + indent_up_impl(); + indent_impl(s_service_impl) << "inherited Create;" << endl; + indent_impl(s_service_impl) << "iprot_ := iprot;" << endl; + indent_impl(s_service_impl) << "oprot_ := oprot;" << endl; + indent_down_impl(); + indent_impl(s_service_impl) << "end;" << endl << endl; + + indent_down(); + + if (extends.empty()) { + indent(s_service) << "protected" << endl; + indent_up(); + indent(s_service) << "iprot_: IProtocol;" << endl; + indent(s_service) << "oprot_: IProtocol;" << endl; + indent(s_service) << "seqid_: Integer;" << endl; + indent_down(); + + indent(s_service) << "public" << endl; + indent_up(); + indent(s_service) << "property InputProtocol: IProtocol read iprot_;" << endl; + indent(s_service) << "property OutputProtocol: IProtocol read oprot_;" << endl; + indent_down(); + } + + vector<t_function*> functions = tservice->get_functions(); + vector<t_function*>::const_iterator f_iter; + + indent(s_service) << "protected" << endl; + indent_up(); + indent(s_service) << "// Iface" << endl; + for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { + string funname = (*f_iter)->get_name(); + generate_delphi_doc(s_service, *f_iter); + indent(s_service) << function_signature(*f_iter) << endl; + } + indent_down(); + + indent(s_service) << "public" << endl; + indent_up(); + + string full_cls = normalize_clsnm(service_name_, "T") + ".TClient"; + + for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { + string funname = (*f_iter)->get_name(); + + indent_impl(s_service_impl) << function_signature(*f_iter, full_cls) << endl; + indent_impl(s_service_impl) << "begin" << endl; + indent_up_impl(); + indent_impl(s_service_impl) << "send_" << funname << "("; + + t_struct* arg_struct = (*f_iter)->get_arglist(); + + const vector<t_field*>& fields = arg_struct->get_members(); + vector<t_field*>::const_iterator fld_iter; + bool first = true; + for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) { + if (first) { + first = false; + } else { + s_service_impl << ", "; + } + s_service_impl << normalize_name((*fld_iter)->get_name()); + } + s_service_impl << ");" << endl; + + if (!(*f_iter)->is_oneway()) { + s_service_impl << indent_impl(); + if (!(*f_iter)->get_returntype()->is_void()) { + s_service_impl << "Result := "; + } + s_service_impl << "recv_" << funname << "();" << endl; + } + + indent_down_impl(); + indent_impl(s_service_impl) << "end;" << endl << endl; + + t_function send_function(g_type_void, + string("send_") + (*f_iter)->get_name(), + (*f_iter)->get_arglist()); + + string argsname = (*f_iter)->get_name() + "_args"; + string args_clsnm = normalize_clsnm(argsname, "T"); + string args_intfnm = normalize_clsnm(argsname, "I"); + + string argsvar = tmp("_args"); + string msgvar = tmp("_msg"); + + indent(s_service) << function_signature(&send_function) << endl; + indent_impl(s_service_impl) << function_signature(&send_function, full_cls) << endl; + indent_impl(s_service_impl) << "var" << endl; + indent_up_impl(); + indent_impl(s_service_impl) << argsvar << " : " << args_intfnm << ";" << endl; + indent_impl(s_service_impl) << msgvar << " : Thrift.Protocol.IMessage;" << endl; + indent_down_impl(); + indent_impl(s_service_impl) << "begin" << endl; + indent_up_impl(); + + indent_impl(s_service_impl) << "seqid_ := seqid_ + 1;" << endl; + indent_impl(s_service_impl) << msgvar << " := Thrift.Protocol.TMessageImpl.Create('" << funname + << "', " << ((*f_iter)->is_oneway() ? "TMessageType.Oneway" + : "TMessageType.Call") + << ", seqid_);" << endl; + + indent_impl(s_service_impl) << "oprot_.WriteMessageBegin( " << msgvar << " );" << endl; + indent_impl(s_service_impl) << argsvar << " := " << args_clsnm << "Impl.Create();" << endl; + + for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) { + indent_impl(s_service_impl) << argsvar << "." << prop_name(*fld_iter) + << " := " << normalize_name((*fld_iter)->get_name()) << ";" + << endl; + } + indent_impl(s_service_impl) << argsvar << ".Write(oprot_);" << endl; + for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) { + indent_impl(s_service_impl) << argsvar << "." << prop_name(*fld_iter) + << " := " << empty_value((*fld_iter)->get_type()) << ";" << endl; + } + + indent_impl(s_service_impl) << "oprot_.WriteMessageEnd();" << endl; + indent_impl(s_service_impl) << "oprot_.Transport.Flush();" << endl; + + indent_down_impl(); + indent_impl(s_service_impl) << "end;" << endl << endl; + + if (!(*f_iter)->is_oneway()) { + string org_resultname = (*f_iter)->get_name() + "_result"; + string result_clsnm = normalize_clsnm(org_resultname, "T"); + string result_intfnm = normalize_clsnm(org_resultname, "I"); + + t_struct noargs(program_); + t_function recv_function((*f_iter)->get_returntype(), + string("recv_") + (*f_iter)->get_name(), + &noargs, + (*f_iter)->get_xceptions()); + + t_struct* xs = (*f_iter)->get_xceptions(); + const std::vector<t_field*>& xceptions = xs->get_members(); + + string exceptvar = tmp("_ex"); + string appexvar = tmp("_ax"); + string retvar = tmp("_ret"); + + indent(s_service) << function_signature(&recv_function) << endl; + indent_impl(s_service_impl) << function_signature(&recv_function, full_cls) << endl; + indent_impl(s_service_impl) << "var" << endl; + indent_up_impl(); + indent_impl(s_service_impl) << msgvar << " : Thrift.Protocol.IMessage;" << endl; + if (xceptions.size() > 0) { + indent_impl(s_service_impl) << exceptvar << " : Exception;" << endl; + } + indent_impl(s_service_impl) << appexvar << " : TApplicationException;" << endl; + indent_impl(s_service_impl) << retvar << " : " << result_intfnm << ";" << endl; + + indent_down_impl(); + indent_impl(s_service_impl) << "begin" << endl; + indent_up_impl(); + indent_impl(s_service_impl) << msgvar << " := iprot_.ReadMessageBegin();" << endl; + indent_impl(s_service_impl) << "if (" << msgvar << ".Type_ = TMessageType.Exception) then" + << endl; + indent_impl(s_service_impl) << "begin" << endl; + indent_up_impl(); + indent_impl(s_service_impl) << appexvar << " := TApplicationException.Read(iprot_);" << endl; + indent_impl(s_service_impl) << "iprot_.ReadMessageEnd();" << endl; + indent_impl(s_service_impl) << "raise " << appexvar << ";" << endl; + indent_down_impl(); + indent_impl(s_service_impl) << "end;" << endl; + + indent_impl(s_service_impl) << retvar << " := " << result_clsnm << "Impl.Create();" << endl; + indent_impl(s_service_impl) << retvar << ".Read(iprot_);" << endl; + indent_impl(s_service_impl) << "iprot_.ReadMessageEnd();" << endl; + + if (!(*f_iter)->get_returntype()->is_void()) { + indent_impl(s_service_impl) << "if (" << retvar << ".__isset_success) then" << endl; + indent_impl(s_service_impl) << "begin" << endl; + indent_up_impl(); + indent_impl(s_service_impl) << "Result := " << retvar << ".Success;" << endl; + t_type* type = (*f_iter)->get_returntype(); + if (type->is_struct() || type->is_xception() || type->is_map() || type->is_list() + || type->is_set()) { + indent_impl(s_service_impl) << retvar << ".Success := nil;" << endl; + } + indent_impl(s_service_impl) << "Exit;" << endl; + indent_down_impl(); + indent_impl(s_service_impl) << "end;" << endl; + } + + vector<t_field*>::const_iterator x_iter; + for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { + indent_impl(s_service_impl) << "if (" << retvar << ".__isset_" << prop_name(*x_iter) + << ") then" << endl; + indent_impl(s_service_impl) << "begin" << endl; + indent_up_impl(); + indent_impl(s_service_impl) << exceptvar << " := " << retvar << "." << prop_name(*x_iter) + << ".CreateException;" << endl; + indent_impl(s_service_impl) << "raise " << exceptvar << ";" << endl; + indent_down_impl(); + indent_impl(s_service_impl) << "end;" << endl; + } + + if (!(*f_iter)->get_returntype()->is_void()) { + indent_impl(s_service_impl) + << "raise " + "TApplicationException.Create(TApplicationException.TExceptionType.MissingResult, '" + << (*f_iter)->get_name() << " failed: unknown result');" << endl; + } + + indent_down_impl(); + indent_impl(s_service_impl) << "end;" << endl << endl; + } + } + + indent_down(); + indent(s_service) << "end;" << endl << endl; +} + +void t_delphi_generator::generate_service_server(t_service* tservice) { + vector<t_function*> functions = tservice->get_functions(); + vector<t_function*>::iterator f_iter; + + string extends = ""; + string extends_processor = ""; + + string full_cls = normalize_clsnm(service_name_, "T") + ".TProcessorImpl"; + + if (tservice->get_extends() != NULL) { + extends = type_name(tservice->get_extends(), true, true); + extends_processor = extends + ".TProcessorImpl"; + indent(s_service) << "TProcessorImpl = class(" << extends_processor << ", IProcessor)" << endl; + } else { + indent(s_service) << "TProcessorImpl = class( TInterfacedObject, IProcessor)" << endl; + } + + indent(s_service) << "public" << endl; + indent_up(); + indent(s_service) << "constructor Create( iface_: Iface );" << endl; + indent(s_service) << "destructor Destroy; override;" << endl; + indent_down(); + + indent_impl(s_service_impl) << "constructor " << full_cls << ".Create( iface_: Iface );" << endl; + indent_impl(s_service_impl) << "begin" << endl; + indent_up_impl(); + if (tservice->get_extends() != NULL) { + indent_impl(s_service_impl) << "inherited Create( iface_);" << endl; + } else { + indent_impl(s_service_impl) << "inherited Create;" << endl; + } + indent_impl(s_service_impl) << "Self.iface_ := iface_;" << endl; + if (tservice->get_extends() != NULL) { + indent_impl(s_service_impl) << "ASSERT( processMap_ <> nil); // inherited" << endl; + } else { + indent_impl(s_service_impl) + << "processMap_ := TThriftDictionaryImpl<string, TProcessFunction>.Create;" << endl; + } + + for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { + indent_impl(s_service_impl) << "processMap_.AddOrSetValue( '" << (*f_iter)->get_name() << "', " + << (*f_iter)->get_name() << "_Process);" << endl; + } + indent_down_impl(); + indent_impl(s_service_impl) << "end;" << endl << endl; + + indent_impl(s_service_impl) << "destructor " << full_cls << ".Destroy;" << endl; + indent_impl(s_service_impl) << "begin" << endl; + indent_up_impl(); + indent_impl(s_service_impl) << "inherited;" << endl; + indent_down_impl(); + indent_impl(s_service_impl) << "end;" << endl << endl; + + indent(s_service) << "private" << endl; + indent_up(); + indent(s_service) << "iface_: Iface;" << endl; + indent_down(); + + if (tservice->get_extends() == NULL) { + indent(s_service) << "protected" << endl; + indent_up(); + indent(s_service) << "type" << endl; + indent_up(); + indent(s_service) << "TProcessFunction = reference to procedure( seqid: Integer; const iprot: " + "IProtocol; const oprot: IProtocol" + << (events_ ? "; const events : IRequestEvents" : "") << ");" << endl; + indent_down(); + indent_down(); + indent(s_service) << "protected" << endl; + indent_up(); + indent(s_service) << "processMap_: IThriftDictionary<string, TProcessFunction>;" << endl; + indent_down(); + } + + indent(s_service) << "public" << endl; + indent_up(); + if (extends.empty()) { + indent(s_service) << "function Process( const iprot: IProtocol; const oprot: IProtocol; const " + "events : IProcessorEvents): Boolean;" << endl; + } else { + indent(s_service) << "function Process( const iprot: IProtocol; const oprot: IProtocol; const " + "events : IProcessorEvents): Boolean; reintroduce;" << endl; + } + + indent_impl(s_service_impl) << "function " << full_cls << ".Process( const iprot: IProtocol; " + "const oprot: IProtocol; const events " + ": IProcessorEvents): Boolean;" << endl; + ; + indent_impl(s_service_impl) << "var" << endl; + indent_up_impl(); + indent_impl(s_service_impl) << "msg : Thrift.Protocol.IMessage;" << endl; + indent_impl(s_service_impl) << "fn : TProcessFunction;" << endl; + indent_impl(s_service_impl) << "x : TApplicationException;" << endl; + if (events_) { + indent_impl(s_service_impl) << "context : IRequestEvents;" << endl; + } + indent_down_impl(); + indent_impl(s_service_impl) << "begin" << endl; + indent_up_impl(); + indent_impl(s_service_impl) << "try" << endl; + indent_up_impl(); + indent_impl(s_service_impl) << "msg := iprot.ReadMessageBegin();" << endl; + indent_impl(s_service_impl) << "fn := nil;" << endl; + indent_impl(s_service_impl) << "if not processMap_.TryGetValue(msg.Name, fn)" << endl; + indent_impl(s_service_impl) << "or not Assigned(fn) then" << endl; + indent_impl(s_service_impl) << "begin" << endl; + indent_up_impl(); + indent_impl(s_service_impl) << "TProtocolUtil.Skip(iprot, TType.Struct);" << endl; + indent_impl(s_service_impl) << "iprot.ReadMessageEnd();" << endl; + indent_impl(s_service_impl) << "x := " + "TApplicationException.Create(TApplicationException." + "TExceptionType.UnknownMethod, 'Invalid method name: ''' + " + "msg.Name + '''');" << endl; + indent_impl(s_service_impl) + << "msg := Thrift.Protocol.TMessageImpl.Create(msg.Name, TMessageType.Exception, msg.SeqID);" + << endl; + indent_impl(s_service_impl) << "oprot.WriteMessageBegin( msg);" << endl; + indent_impl(s_service_impl) << "x.Write(oprot);" << endl; + indent_impl(s_service_impl) << "oprot.WriteMessageEnd();" << endl; + indent_impl(s_service_impl) << "oprot.Transport.Flush();" << endl; + indent_impl(s_service_impl) << "Result := True;" << endl; + indent_impl(s_service_impl) << "Exit;" << endl; + indent_down_impl(); + indent_impl(s_service_impl) << "end;" << endl; + if (events_) { + indent_impl(s_service_impl) << "if events <> nil" << endl; + indent_impl(s_service_impl) << "then context := events.CreateRequestContext(msg.Name)" << endl; + indent_impl(s_service_impl) << "else context := nil;" << endl; + indent_impl(s_service_impl) << "try" << endl; + indent_up_impl(); + indent_impl(s_service_impl) << "fn(msg.SeqID, iprot, oprot, context);" << endl; + indent_down_impl(); + indent_impl(s_service_impl) << "finally" << endl; + indent_up_impl(); + indent_impl(s_service_impl) << "if context <> nil then begin" << endl; + indent_up_impl(); + indent_impl(s_service_impl) << "context.CleanupContext;" << endl; + indent_impl(s_service_impl) << "context := nil;" << endl; + indent_down_impl(); + indent_impl(s_service_impl) << "end;" << endl; + indent_down_impl(); + indent_impl(s_service_impl) << "end;" << endl; + } else { + indent_impl(s_service_impl) << "fn(msg.SeqID, iprot, oprot);" << endl; + } + inde
<TRUNCATED>
