From ac018e21b224097abf62a8b944093d729bf555b4 Mon Sep 17 00:00:00 2001 From: levlam Date: Mon, 26 Jun 2023 19:25:40 +0300 Subject: [PATCH] Add write_tl_to_multiple_files to allow C++ autogenerated header splitting. --- td/generate/tl_writer_c.h | 6 +- td/generate/tl_writer_dotnet.h | 4 ++ td/generate/tl_writer_h.cpp | 5 +- td/generate/tl_writer_java.cpp | 6 +- td/generate/tl_writer_java.h | 2 + td/generate/tl_writer_jni_h.cpp | 6 +- td/generate/tl_writer_td.cpp | 4 ++ td/generate/tl_writer_td.h | 1 + tdtl/td/tl/tl_generate.cpp | 115 ++++++++++++++++++++++++++++++++ tdtl/td/tl/tl_generate.h | 3 + tdtl/td/tl/tl_writer.h | 1 + 11 files changed, 144 insertions(+), 9 deletions(-) diff --git a/td/generate/tl_writer_c.h b/td/generate/tl_writer_c.h index 94efbe09c..aed154333 100644 --- a/td/generate/tl_writer_c.h +++ b/td/generate/tl_writer_c.h @@ -224,7 +224,7 @@ class TlWriterCCommon final : public tl::TL_writer { } std::string gen_output_begin(const std::string &additional_imports) const final { if (is_header_ == 1) { - return "#pragma once\n" + return "#pragma once\n\n" + additional_imports + "#ifdef __cplusplus\n" "extern \"C\" {\n" "#endif\n" @@ -300,6 +300,10 @@ class TlWriterCCommon final : public tl::TL_writer { } } + std::string gen_package_suffix() const final { + return ".h"; + } + std::string gen_forward_class_declaration(const std::string &class_name, bool is_proxy) const final { if (is_header_ != 1 || class_name == "") { return ""; diff --git a/td/generate/tl_writer_dotnet.h b/td/generate/tl_writer_dotnet.h index effd8c7af..c0226c4c3 100644 --- a/td/generate/tl_writer_dotnet.h +++ b/td/generate/tl_writer_dotnet.h @@ -206,6 +206,10 @@ class TlWriterDotNet final : public TL_writer { } } + std::string gen_package_suffix() const final { + return ".h"; + } + std::string gen_forward_class_declaration(const std::string &class_name, bool is_proxy) const final { if (!is_header_) { return ""; diff --git a/td/generate/tl_writer_h.cpp b/td/generate/tl_writer_h.cpp index cd3d73486..49f7f55f7 100644 --- a/td/generate/tl_writer_h.cpp +++ b/td/generate/tl_writer_h.cpp @@ -51,9 +51,8 @@ std::string TD_TL_writer_h::gen_output_begin(const std::string &additional_impor ext_include_str + "#include \n" "#include \n" - "#include \n\n" - "namespace td {\n" + - ext_forward_declaration + "namespace " + tl_name + " {\n\n"; + "#include \n\n" + + additional_imports + "namespace td {\n" + ext_forward_declaration + "namespace " + tl_name + " {\n\n"; } std::string TD_TL_writer_h::gen_output_begin_once() const { diff --git a/td/generate/tl_writer_java.cpp b/td/generate/tl_writer_java.cpp index 0cbbbdf76..5c024bd97 100644 --- a/td/generate/tl_writer_java.cpp +++ b/td/generate/tl_writer_java.cpp @@ -191,7 +191,7 @@ std::string TD_TL_writer_java::gen_int_const(const tl::tl_tree *tree_c, } std::string TD_TL_writer_java::gen_output_begin(const std::string &additional_imports) const { - return "package " + package_name + ";\n\n" + additional_imports; + return "package " + package_name + ";\n\n"; } std::string TD_TL_writer_java::gen_output_begin_once() const { @@ -218,6 +218,10 @@ std::string TD_TL_writer_java::gen_import_declaration(const std::string &name, b return "import " + name + ";\n"; } +std::string TD_TL_writer_java::gen_package_suffix() const { + return ""; +} + std::string TD_TL_writer_java::gen_forward_class_declaration(const std::string &class_name, bool is_proxy) const { return ""; } diff --git a/td/generate/tl_writer_java.h b/td/generate/tl_writer_java.h index de1a07102..67b900486 100644 --- a/td/generate/tl_writer_java.h +++ b/td/generate/tl_writer_java.h @@ -59,6 +59,8 @@ class TD_TL_writer_java final : public tl::TL_writer { std::string gen_import_declaration(const std::string &name, bool is_system) const final; + std::string gen_package_suffix() const final; + std::string gen_forward_class_declaration(const std::string &class_name, bool is_proxy) const final; std::string gen_class_begin(const std::string &class_name, const std::string &base_class_name, bool is_proxy, diff --git a/td/generate/tl_writer_jni_h.cpp b/td/generate/tl_writer_jni_h.cpp index 883a4ba15..867069326 100644 --- a/td/generate/tl_writer_jni_h.cpp +++ b/td/generate/tl_writer_jni_h.cpp @@ -69,11 +69,9 @@ std::string TD_TL_writer_jni_h::gen_output_begin(const std::string &additional_i "#include \n" "#include \n\n" "#include \n\n" + - ext_include_str + - "\n" + ext_include_str + "\n" + additional_imports + - "namespace td {\n" + - forward_declaration("TlStorerToString") + + "namespace td {\n" + forward_declaration("TlStorerToString") + "\n" "namespace " + tl_name + " {\n\n"; diff --git a/td/generate/tl_writer_td.cpp b/td/generate/tl_writer_td.cpp index 192276b6e..ff99fa1de 100644 --- a/td/generate/tl_writer_td.cpp +++ b/td/generate/tl_writer_td.cpp @@ -125,6 +125,10 @@ std::string TD_TL_writer::gen_import_declaration(const std::string &name, bool i } } +std::string TD_TL_writer::gen_package_suffix() const { + return ".h"; +} + std::string TD_TL_writer::gen_base_tl_class_name() const { return base_tl_class_name; } diff --git a/td/generate/tl_writer_td.h b/td/generate/tl_writer_td.h index e29ed7abc..bdf747104 100644 --- a/td/generate/tl_writer_td.h +++ b/td/generate/tl_writer_td.h @@ -46,6 +46,7 @@ class TD_TL_writer : public tl::TL_writer { std::vector get_storers() const override; std::string gen_import_declaration(const std::string &package_name, bool is_system) const override; + std::string gen_package_suffix() const override; std::string gen_base_tl_class_name() const override; std::string gen_base_type_class_name(int arity) const override; std::string gen_base_function_class_name() const override; diff --git a/tdtl/td/tl/tl_generate.cpp b/tdtl/td/tl/tl_generate.cpp index 84637d23c..6d3fe7698 100644 --- a/tdtl/td/tl/tl_generate.cpp +++ b/tdtl/td/tl/tl_generate.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -898,5 +899,119 @@ bool write_tl_to_file(const tl_config &config, const std::string &file_name, con return put_file_contents(file_name, out.get_result(), w.is_documentation_generated()); } +static std::string get_additional_imports(const std::map &types, const std::string base_class_name, + const std::string &file_name_prefix, const std::string &file_name_suffix, + const TL_writer &w) { + std::string result = + w.gen_import_declaration(file_name_prefix + "_" + base_class_name + w.gen_package_suffix(), false); + if (w.gen_package_suffix() != file_name_suffix) { + for (std::map::const_iterator it = types.begin(); it != types.end(); ++it) { + std::string package_name = file_name_prefix + "_" + w.gen_class_name(it->first) + w.gen_package_suffix(); + result += w.gen_import_declaration(package_name, false); + } + } + result += "\n"; + return result; +} + +bool write_tl_to_multiple_files(const tl_config &config, const std::string &file_name_prefix, + const std::string &file_name_suffix, const TL_writer &w) { + find_complex_types(config, w); + + std::map outs; + + tl_string_outputer *out = &outs["common"]; + out->append(w.gen_output_begin(std::string())); + out->append(w.gen_output_begin_once()); + out->append(w.gen_output_end()); + + std::set request_types; + std::set result_types; + for (std::size_t function = 0; function < config.get_function_count(); function++) { + const tl_combinator *t = config.get_function_by_num(function); + dfs_combinator(t, request_types, w); + dfs_tree(t->result, result_types, w); + } + + std::map object_types; + for (std::size_t type = 0; type < config.get_type_count(); type++) { + tl_type *t = config.get_type_by_num(type); + if (t->constructors_num == 0 || w.is_built_in_simple_type(t->name) || + w.is_built_in_complex_type(t->name)) { // built-in dummy or complex types + continue; + } + + if (t->flags & FLAG_COMPLEX) { + std::fprintf(stderr, "Can't generate class %s\n", t->name.c_str()); + continue; + } + + object_types[t->name] = (t->simple_constructors != 1); + out = &outs[w.gen_main_class_name(t)]; + auto additional_imports = + get_additional_imports(get_children_types(t, w), "Object", file_name_prefix, file_name_suffix, w); + out->append(w.gen_output_begin(additional_imports)); + write_class(*out, t, request_types, result_types, w); + out->append(w.gen_output_end()); + } + + std::map function_types; + for (std::size_t function = 0; function < config.get_function_count(); function++) { + tl_combinator *t = config.get_function_by_num(function); + if (!w.is_combinator_supported(t)) { + // std::fprintf(stderr, "Function %s is too hard to store\n", t->name.c_str()); + continue; + } + + function_types[t->name] = false; + out = &outs[w.gen_class_name(t->name)]; + auto additional_imports = + get_additional_imports(get_children_types(t, w), "Function", file_name_prefix, file_name_suffix, w); + out->append(w.gen_output_begin(additional_imports)); + write_function(*out, t, request_types, result_types, w); + out->append(w.gen_output_end()); + } + + for (std::size_t type = 0; type < config.get_type_count(); type++) { + tl_type *t = config.get_type_by_num(type); + if (t->flags & FLAG_COMPLEX) { + t->flags &= ~FLAG_COMPLEX; // remove temporary flag + } + } + + out = &outs["Object"]; + out->append( + w.gen_output_begin(get_additional_imports(object_types, "common", file_name_prefix, file_name_suffix, w))); + write_base_object_classes(config, *out, request_types, result_types, w); + out->append(w.gen_output_end()); + + out = &outs["Function"]; + out->append( + w.gen_output_begin(get_additional_imports(function_types, "common", file_name_prefix, file_name_suffix, w))); + write_base_function_class(config, *out, request_types, result_types, w); + out->append(w.gen_output_end()); + + std::string additional_main_imports; + for (std::map::const_iterator it = outs.begin(); it != outs.end(); ++it) { + std::string file_name = file_name_prefix + "_" + it->first + file_name_suffix; + if (!put_file_contents(file_name, it->second.get_result(), w.is_documentation_generated())) { + return false; + } + + if (file_name_suffix == w.gen_package_suffix()) { + additional_main_imports += w.gen_import_declaration(file_name, false); + } + } + if (!additional_main_imports.empty()) { + additional_main_imports += "\n"; + } + + tl_string_outputer main_out; + main_out.append(w.gen_output_begin(additional_main_imports)); + main_out.append(w.gen_output_end()); + + return put_file_contents(file_name_prefix + file_name_suffix, main_out.get_result(), w.is_documentation_generated()); +} + } // namespace tl } // namespace td diff --git a/tdtl/td/tl/tl_generate.h b/tdtl/td/tl/tl_generate.h index 2d64e3f1e..a0b924bd3 100644 --- a/tdtl/td/tl/tl_generate.h +++ b/tdtl/td/tl/tl_generate.h @@ -21,5 +21,8 @@ tl_config read_tl_config_from_file(const std::string &file_name); bool write_tl_to_file(const tl_config &config, const std::string &file_name, const TL_writer &w); +bool write_tl_to_multiple_files(const tl_config &config, const std::string &file_name_prefix, + const std::string &file_name_suffix, const TL_writer &w); + } // namespace tl } // namespace td diff --git a/tdtl/td/tl/tl_writer.h b/tdtl/td/tl/tl_writer.h index ed52ba206..1851aab9d 100644 --- a/tdtl/td/tl/tl_writer.h +++ b/tdtl/td/tl/tl_writer.h @@ -88,6 +88,7 @@ class TL_writer { virtual std::string gen_output_end() const = 0; virtual std::string gen_import_declaration(const std::string &name, bool is_system) const = 0; + virtual std::string gen_package_suffix() const = 0; virtual std::string gen_forward_class_declaration(const std::string &class_name, bool is_proxy) const = 0;