You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@thrift.apache.org by ns...@apache.org on 2016/09/25 16:43:05 UTC
[16/55] [abbrv] [partial] thrift git commit: THRIFT-2835 Add
possibility to distribute generators separately from thrift core,
and load them dynamically
http://git-wip-us.apache.org/repos/asf/thrift/blob/052abc39/compiler/cpp/src/thrift/generate/t_delphi_generator.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/thrift/generate/t_delphi_generator.cc b/compiler/cpp/src/thrift/generate/t_delphi_generator.cc
new file mode 100644
index 0000000..8b1a445
--- /dev/null
+++ b/compiler/cpp/src/thrift/generate/t_delphi_generator.cc
@@ -0,0 +1,3920 @@
+/*
+ * 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 "thrift/platform.h"
+#include "thrift/generate/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;
+
+ ansistr_binary_ = false;
+ register_types_ = false;
+ constprefix_ = false;
+ events_ = false;
+ xmldoc_ = false;
+ for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
+ if( iter->first.compare("ansistr_binary") == 0) {
+ ansistr_binary_ = true;
+ } else if( iter->first.compare("register_types") == 0) {
+ register_types_ = true;
+ } else if( iter->first.compare("constprefix") == 0) {
+ constprefix_ = true;
+ } else if( iter->first.compare("events") == 0) {
+ events_ = true;
+ } else if( iter->first.compare("xmldoc") == 0) {
+ xmldoc_ = true;
+ } else {
+ throw "unknown option delphi:" + iter->first;
+ }
+ }
+
+ 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_i8)] = 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_I8:
+ 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 TApplicationExceptionMissingResult.Create('"
+ << (*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 := "
+ "TApplicationExceptionUnknownMethod.Create("
+ "'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;
+ }
+ indent_down_i
<TRUNCATED>