From 329688cea65a89525513c5d3ceac3563c4cf1aad Mon Sep 17 00:00:00 2001 From: Jonathan Carvalhosa Date: Tue, 13 Oct 2026 16:33:21 -0300 Subject: [PATCH 1/2] C# flags: keep the underlying type in the bitwise operators and RemoveFlags The C# flags template cast the result of &, |, ^ and the complement in RemoveFlags to byte, whatever the declared base type. For a flags type on int32 (the default) or any type wider than a byte, combining two values above 0xFF lost them (0x400 | 0x1000 gave 0) and RemoveFlags cleared every flag from 0x100 up. The casts now use _FLAGS_TYPE_, as the constructor and the deserializer already do; byte-based flags generate the same code as before. Co-Authored-By: Claude Opus 5.5 --- projects/CSharp/Proto/com.chronoxor.test.cs | 24 ++++++++++----------- source/generator_csharp.cpp | 8 +++---- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/projects/CSharp/Proto/com.chronoxor.test.cs b/projects/CSharp/Proto/com.chronoxor.test.cs index 8b25c6304..7739abfac 100644 --- a/projects/CSharp/Proto/com.chronoxor.test.cs +++ b/projects/CSharp/Proto/com.chronoxor.test.cs @@ -798,7 +798,7 @@ public FlagsSimple SetFlags(FlagsSimple flags) public FlagsSimple RemoveFlags(FlagsSimple flags) { - Value &= (byte)~flags.Value; + Value &= (int)~flags.Value; return this; } @@ -839,17 +839,17 @@ public override int GetHashCode() public static FlagsSimple operator&(FlagsSimple flags1, FlagsSimple flags2) { - return new FlagsSimple((byte)(flags1.Value & flags2.Value)); + return new FlagsSimple((int)(flags1.Value & flags2.Value)); } public static FlagsSimple operator|(FlagsSimple flags1, FlagsSimple flags2) { - return new FlagsSimple((byte)(flags1.Value | flags2.Value)); + return new FlagsSimple((int)(flags1.Value | flags2.Value)); } public static FlagsSimple operator^(FlagsSimple flags1, FlagsSimple flags2) { - return new FlagsSimple((byte)(flags1.Value ^ flags2.Value)); + return new FlagsSimple((int)(flags1.Value ^ flags2.Value)); } public static FlagsSimple Default => new FlagsSimple(); @@ -1090,7 +1090,7 @@ public FlagsTyped SetFlags(FlagsTyped flags) public FlagsTyped RemoveFlags(FlagsTyped flags) { - Value &= (byte)~flags.Value; + Value &= (ulong)~flags.Value; return this; } @@ -1131,17 +1131,17 @@ public override int GetHashCode() public static FlagsTyped operator&(FlagsTyped flags1, FlagsTyped flags2) { - return new FlagsTyped((byte)(flags1.Value & flags2.Value)); + return new FlagsTyped((ulong)(flags1.Value & flags2.Value)); } public static FlagsTyped operator|(FlagsTyped flags1, FlagsTyped flags2) { - return new FlagsTyped((byte)(flags1.Value | flags2.Value)); + return new FlagsTyped((ulong)(flags1.Value | flags2.Value)); } public static FlagsTyped operator^(FlagsTyped flags1, FlagsTyped flags2) { - return new FlagsTyped((byte)(flags1.Value ^ flags2.Value)); + return new FlagsTyped((ulong)(flags1.Value ^ flags2.Value)); } public static FlagsTyped Default => new FlagsTyped(); @@ -1410,7 +1410,7 @@ public FlagsEmpty SetFlags(FlagsEmpty flags) public FlagsEmpty RemoveFlags(FlagsEmpty flags) { - Value &= (byte)~flags.Value; + Value &= (int)~flags.Value; return this; } @@ -1451,17 +1451,17 @@ public override int GetHashCode() public static FlagsEmpty operator&(FlagsEmpty flags1, FlagsEmpty flags2) { - return new FlagsEmpty((byte)(flags1.Value & flags2.Value)); + return new FlagsEmpty((int)(flags1.Value & flags2.Value)); } public static FlagsEmpty operator|(FlagsEmpty flags1, FlagsEmpty flags2) { - return new FlagsEmpty((byte)(flags1.Value | flags2.Value)); + return new FlagsEmpty((int)(flags1.Value | flags2.Value)); } public static FlagsEmpty operator^(FlagsEmpty flags1, FlagsEmpty flags2) { - return new FlagsEmpty((byte)(flags1.Value ^ flags2.Value)); + return new FlagsEmpty((int)(flags1.Value ^ flags2.Value)); } public static FlagsEmpty Default => new FlagsEmpty(); diff --git a/source/generator_csharp.cpp b/source/generator_csharp.cpp index 9f2245754..550c0507c 100644 --- a/source/generator_csharp.cpp +++ b/source/generator_csharp.cpp @@ -4909,7 +4909,7 @@ void GeneratorCSharp::GenerateFlags(const std::string& domain, const std::shared public _FLAGS_NAME_ RemoveFlags(_FLAGS_NAME_ flags) { - Value &= (byte)~flags.Value; + Value &= (_FLAGS_TYPE_)~flags.Value; return this; } @@ -4950,17 +4950,17 @@ void GeneratorCSharp::GenerateFlags(const std::string& domain, const std::shared public static _FLAGS_NAME_ operator&(_FLAGS_NAME_ flags1, _FLAGS_NAME_ flags2) { - return new _FLAGS_NAME_((byte)(flags1.Value & flags2.Value)); + return new _FLAGS_NAME_((_FLAGS_TYPE_)(flags1.Value & flags2.Value)); } public static _FLAGS_NAME_ operator|(_FLAGS_NAME_ flags1, _FLAGS_NAME_ flags2) { - return new _FLAGS_NAME_((byte)(flags1.Value | flags2.Value)); + return new _FLAGS_NAME_((_FLAGS_TYPE_)(flags1.Value | flags2.Value)); } public static _FLAGS_NAME_ operator^(_FLAGS_NAME_ flags1, _FLAGS_NAME_ flags2) { - return new _FLAGS_NAME_((byte)(flags1.Value ^ flags2.Value)); + return new _FLAGS_NAME_((_FLAGS_TYPE_)(flags1.Value ^ flags2.Value)); } public static _FLAGS_NAME_ Default => new _FLAGS_NAME_(); From a6ed090835a53cb4cb43e97d2386a21d783c4ad0 Mon Sep 17 00:00:00 2001 From: jccarvalhosa Date: Tue, 13 Oct 2026 19:48:08 +0000 Subject: [PATCH 2/2] Update generated documentation --- documents/html/annotated.html | 121 + .../class_f_b_e_1_1_generator-members.html | 111 + documents/html/class_f_b_e_1_1_generator.html | 666 + documents/html/class_f_b_e_1_1_generator.png | Bin 0 -> 3848 bytes ...s_f_b_e_1_1_generator_c_sharp-members.html | 117 + .../class_f_b_e_1_1_generator_c_sharp.html | 380 + .../class_f_b_e_1_1_generator_c_sharp.png | Bin 0 -> 622 bytes ...class_f_b_e_1_1_generator_cpp-members.html | 119 + .../html/class_f_b_e_1_1_generator_cpp.html | 436 + .../html/class_f_b_e_1_1_generator_cpp.png | Bin 0 -> 535 bytes .../class_f_b_e_1_1_generator_go-members.html | 117 + .../html/class_f_b_e_1_1_generator_go.html | 380 + .../html/class_f_b_e_1_1_generator_go.png | Bin 0 -> 517 bytes ...lass_f_b_e_1_1_generator_java-members.html | 119 + .../html/class_f_b_e_1_1_generator_java.html | 436 + .../html/class_f_b_e_1_1_generator_java.png | Bin 0 -> 530 bytes ...b_e_1_1_generator_java_script-members.html | 117 + ...class_f_b_e_1_1_generator_java_script.html | 380 + .../class_f_b_e_1_1_generator_java_script.png | Bin 0 -> 639 bytes ...ss_f_b_e_1_1_generator_kotlin-members.html | 119 + .../class_f_b_e_1_1_generator_kotlin.html | 436 + .../html/class_f_b_e_1_1_generator_kotlin.png | Bin 0 -> 538 bytes ...ss_f_b_e_1_1_generator_python-members.html | 117 + .../class_f_b_e_1_1_generator_python.html | 380 + .../html/class_f_b_e_1_1_generator_python.png | Bin 0 -> 593 bytes ...lass_f_b_e_1_1_generator_ruby-members.html | 117 + .../html/class_f_b_e_1_1_generator_ruby.html | 380 + .../html/class_f_b_e_1_1_generator_ruby.png | Bin 0 -> 534 bytes ...ass_f_b_e_1_1_generator_swift-members.html | 117 + .../html/class_f_b_e_1_1_generator_swift.html | 380 + .../html/class_f_b_e_1_1_generator_swift.png | Bin 0 -> 554 bytes documents/html/classes.html | 112 + documents/html/clipboard.js | 61 + documents/html/cookie.js | 58 + .../dir_b2f33c71d4aa5e7af42a1ca61ff5af1b.html | 116 + .../dir_d44c64559bbebec7f509842c48db8b23.html | 119 + documents/html/doxygen.css | 2540 ++++ documents/html/doxygen.svg | 28 + documents/html/doxygen_crawl.html | 341 + documents/html/dynsections.js | 198 + documents/html/fbe_8cpp.html | 109 + documents/html/fbe_8cpp_source.html | 416 + documents/html/fbe_8h.html | 193 + documents/html/fbe_8h_source.html | 456 + documents/html/fbe_8l.html | 356 + documents/html/fbe_8l_source.html | 493 + documents/html/files.html | 116 + documents/html/functions.html | 251 + documents/html/functions_func.html | 159 + documents/html/functions_vars.html | 210 + documents/html/generator_8cpp.html | 109 + documents/html/generator_8cpp_source.html | 160 + documents/html/generator_8h.html | 115 + documents/html/generator_8h_source.html | 156 + documents/html/generator_8inl.html | 108 + documents/html/generator_8inl_source.html | 194 + documents/html/generator__cpp_8cpp.html | 109 + .../html/generator__cpp_8cpp_source.html | 10740 ++++++++++++++++ documents/html/generator__cpp_8h.html | 114 + documents/html/generator__cpp_8h_source.html | 290 + documents/html/generator__csharp_8cpp.html | 109 + .../html/generator__csharp_8cpp_source.html | 8835 +++++++++++++ documents/html/generator__csharp_8h.html | 114 + .../html/generator__csharp_8h_source.html | 215 + documents/html/generator__go_8cpp.html | 109 + documents/html/generator__go_8cpp_source.html | 8757 +++++++++++++ documents/html/generator__go_8h.html | 114 + documents/html/generator__go_8h_source.html | 222 + documents/html/generator__java_8cpp.html | 109 + .../html/generator__java_8cpp_source.html | 8107 ++++++++++++ documents/html/generator__java_8h.html | 114 + documents/html/generator__java_8h_source.html | 238 + .../html/generator__javascript_8cpp.html | 109 + .../generator__javascript_8cpp_source.html | 10626 +++++++++++++++ documents/html/generator__javascript_8h.html | 114 + .../html/generator__javascript_8h_source.html | 227 + documents/html/generator__kotlin_8cpp.html | 109 + .../html/generator__kotlin_8cpp_source.html | 9008 +++++++++++++ documents/html/generator__kotlin_8h.html | 114 + .../html/generator__kotlin_8h_source.html | 250 + documents/html/generator__python_8cpp.html | 109 + .../html/generator__python_8cpp_source.html | 5607 ++++++++ documents/html/generator__python_8h.html | 114 + .../html/generator__python_8h_source.html | 208 + documents/html/generator__ruby_8cpp.html | 109 + .../html/generator__ruby_8cpp_source.html | 6435 +++++++++ documents/html/generator__ruby_8h.html | 114 + documents/html/generator__ruby_8h_source.html | 214 + documents/html/generator__swift_8cpp.html | 110 + .../html/generator__swift_8cpp_source.html | 8589 ++++++++++++ documents/html/generator__swift_8h.html | 114 + .../html/generator__swift_8h_source.html | 237 + documents/html/globals.html | 95 + documents/html/globals_func.html | 92 + documents/html/globals_vars.html | 87 + documents/html/hierarchy.html | 120 + documents/html/index.html | 86 + documents/html/jquery.js | 204 + documents/html/menu.js | 131 + documents/html/menudata.js | 98 + documents/html/namespace_f_b_e.html | 144 + documents/html/namespacemembers.html | 85 + documents/html/namespacemembers_vars.html | 85 + documents/html/namespaces.html | 90 + documents/html/navtree.css | 327 + documents/html/search/all_0.js | 9 + documents/html/search/all_1.js | 14 + documents/html/search/all_10.js | 5 + documents/html/search/all_11.js | 10 + documents/html/search/all_12.js | 18 + documents/html/search/all_13.js | 4 + documents/html/search/all_14.js | 9 + documents/html/search/all_15.js | 9 + documents/html/search/all_16.js | 13 + documents/html/search/all_2.js | 5 + documents/html/search/all_3.js | 4 + documents/html/search/all_4.js | 5 + documents/html/search/all_5.js | 10 + documents/html/search/all_6.js | 16 + documents/html/search/all_7.js | 36 + documents/html/search/all_8.js | 5 + documents/html/search/all_9.js | 9 + documents/html/search/all_a.js | 4 + documents/html/search/all_b.js | 5 + documents/html/search/all_c.js | 5 + documents/html/search/all_d.js | 9 + documents/html/search/all_e.js | 5 + documents/html/search/all_f.js | 5 + documents/html/search/classes_0.js | 4 + documents/html/search/classes_1.js | 7 + documents/html/search/classes_2.js | 7 + documents/html/search/classes_3.js | 13 + documents/html/search/classes_4.js | 4 + documents/html/search/classes_5.js | 4 + documents/html/search/classes_6.js | 12 + documents/html/search/classes_7.js | 4 + documents/html/search/files_0.js | 6 + documents/html/search/files_1.js | 24 + documents/html/search/files_2.js | 4 + documents/html/search/functions_0.js | 11 + documents/html/search/functions_1.js | 4 + documents/html/search/functions_2.js | 4 + documents/html/search/functions_3.js | 5 + documents/html/search/functions_4.js | 5 + documents/html/search/functions_5.js | 4 + documents/html/search/functions_6.js | 4 + documents/html/search/functions_7.js | 5 + documents/html/search/functions_8.js | 5 + documents/html/search/functions_9.js | 6 + documents/html/search/functions_a.js | 4 + documents/html/search/functions_b.js | 9 + documents/html/search/functions_c.js | 10 + documents/html/search/namespaces_0.js | 4 + documents/html/search/search.css | 377 + documents/html/search/search.js | 708 + documents/html/search/searchdata.js | 30 + documents/html/search/variables_0.js | 9 + documents/html/search/variables_1.js | 5 + documents/html/search/variables_10.js | 7 + documents/html/search/variables_11.js | 4 + documents/html/search/variables_12.js | 7 + documents/html/search/variables_13.js | 6 + documents/html/search/variables_2.js | 5 + documents/html/search/variables_3.js | 4 + documents/html/search/variables_4.js | 5 + documents/html/search/variables_5.js | 5 + documents/html/search/variables_6.js | 7 + documents/html/search/variables_7.js | 4 + documents/html/search/variables_8.js | 5 + documents/html/search/variables_9.js | 6 + documents/html/search/variables_a.js | 5 + documents/html/search/variables_b.js | 4 + documents/html/search/variables_c.js | 7 + documents/html/search/variables_d.js | 5 + documents/html/search/variables_e.js | 5 + documents/html/search/variables_f.js | 10 + .../struct_f_b_e_1_1_attributes-members.html | 95 + .../html/struct_f_b_e_1_1_attributes.html | 165 + .../struct_f_b_e_1_1_enum_body-members.html | 94 + .../html/struct_f_b_e_1_1_enum_body.html | 148 + .../struct_f_b_e_1_1_enum_const-members.html | 94 + .../html/struct_f_b_e_1_1_enum_const.html | 139 + .../struct_f_b_e_1_1_enum_type-members.html | 96 + .../html/struct_f_b_e_1_1_enum_type.html | 173 + .../struct_f_b_e_1_1_enum_value-members.html | 95 + .../html/struct_f_b_e_1_1_enum_value.html | 156 + .../struct_f_b_e_1_1_flags_body-members.html | 94 + .../html/struct_f_b_e_1_1_flags_body.html | 148 + .../struct_f_b_e_1_1_flags_const-members.html | 94 + .../html/struct_f_b_e_1_1_flags_const.html | 139 + .../struct_f_b_e_1_1_flags_type-members.html | 96 + .../html/struct_f_b_e_1_1_flags_type.html | 173 + .../struct_f_b_e_1_1_flags_value-members.html | 95 + .../html/struct_f_b_e_1_1_flags_value.html | 156 + .../html/struct_f_b_e_1_1_import-members.html | 94 + documents/html/struct_f_b_e_1_1_import.html | 148 + .../struct_f_b_e_1_1_package-members.html | 101 + documents/html/struct_f_b_e_1_1_package.html | 283 + .../struct_f_b_e_1_1_statement-members.html | 95 + .../html/struct_f_b_e_1_1_statement.html | 156 + .../struct_f_b_e_1_1_statements-members.html | 99 + .../html/struct_f_b_e_1_1_statements.html | 242 + .../struct_f_b_e_1_1_struct_body-members.html | 94 + .../html/struct_f_b_e_1_1_struct_body.html | 148 + ...struct_f_b_e_1_1_struct_field-members.html | 109 + .../html/struct_f_b_e_1_1_struct_field.html | 403 + ...truct_f_b_e_1_1_struct_reject-members.html | 94 + .../html/struct_f_b_e_1_1_struct_reject.html | 139 + ...ruct_f_b_e_1_1_struct_rejects-members.html | 94 + .../html/struct_f_b_e_1_1_struct_rejects.html | 152 + .../html/struct_f_b_e_1_1_struct_request.html | 97 + ...uct_f_b_e_1_1_struct_response-members.html | 93 + .../struct_f_b_e_1_1_struct_response.html | 122 + .../struct_f_b_e_1_1_struct_type-members.html | 106 + .../html/struct_f_b_e_1_1_struct_type.html | 368 + .../struct_f_b_e_1_1_version-members.html | 96 + documents/html/struct_f_b_e_1_1_version.html | 191 + documents/html/tabs.css | 1 + documents/html/version_8h.html | 113 + documents/html/version_8h_source.html | 104 + 220 files changed, 102781 insertions(+) create mode 100644 documents/html/annotated.html create mode 100644 documents/html/class_f_b_e_1_1_generator-members.html create mode 100644 documents/html/class_f_b_e_1_1_generator.html create mode 100644 documents/html/class_f_b_e_1_1_generator.png create mode 100644 documents/html/class_f_b_e_1_1_generator_c_sharp-members.html create mode 100644 documents/html/class_f_b_e_1_1_generator_c_sharp.html create mode 100644 documents/html/class_f_b_e_1_1_generator_c_sharp.png create mode 100644 documents/html/class_f_b_e_1_1_generator_cpp-members.html create mode 100644 documents/html/class_f_b_e_1_1_generator_cpp.html create mode 100644 documents/html/class_f_b_e_1_1_generator_cpp.png create mode 100644 documents/html/class_f_b_e_1_1_generator_go-members.html create mode 100644 documents/html/class_f_b_e_1_1_generator_go.html create mode 100644 documents/html/class_f_b_e_1_1_generator_go.png create mode 100644 documents/html/class_f_b_e_1_1_generator_java-members.html create mode 100644 documents/html/class_f_b_e_1_1_generator_java.html create mode 100644 documents/html/class_f_b_e_1_1_generator_java.png create mode 100644 documents/html/class_f_b_e_1_1_generator_java_script-members.html create mode 100644 documents/html/class_f_b_e_1_1_generator_java_script.html create mode 100644 documents/html/class_f_b_e_1_1_generator_java_script.png create mode 100644 documents/html/class_f_b_e_1_1_generator_kotlin-members.html create mode 100644 documents/html/class_f_b_e_1_1_generator_kotlin.html create mode 100644 documents/html/class_f_b_e_1_1_generator_kotlin.png create mode 100644 documents/html/class_f_b_e_1_1_generator_python-members.html create mode 100644 documents/html/class_f_b_e_1_1_generator_python.html create mode 100644 documents/html/class_f_b_e_1_1_generator_python.png create mode 100644 documents/html/class_f_b_e_1_1_generator_ruby-members.html create mode 100644 documents/html/class_f_b_e_1_1_generator_ruby.html create mode 100644 documents/html/class_f_b_e_1_1_generator_ruby.png create mode 100644 documents/html/class_f_b_e_1_1_generator_swift-members.html create mode 100644 documents/html/class_f_b_e_1_1_generator_swift.html create mode 100644 documents/html/class_f_b_e_1_1_generator_swift.png create mode 100644 documents/html/classes.html create mode 100644 documents/html/clipboard.js create mode 100644 documents/html/cookie.js create mode 100644 documents/html/dir_b2f33c71d4aa5e7af42a1ca61ff5af1b.html create mode 100644 documents/html/dir_d44c64559bbebec7f509842c48db8b23.html create mode 100644 documents/html/doxygen.css create mode 100644 documents/html/doxygen.svg create mode 100644 documents/html/doxygen_crawl.html create mode 100644 documents/html/dynsections.js create mode 100644 documents/html/fbe_8cpp.html create mode 100644 documents/html/fbe_8cpp_source.html create mode 100644 documents/html/fbe_8h.html create mode 100644 documents/html/fbe_8h_source.html create mode 100644 documents/html/fbe_8l.html create mode 100644 documents/html/fbe_8l_source.html create mode 100644 documents/html/files.html create mode 100644 documents/html/functions.html create mode 100644 documents/html/functions_func.html create mode 100644 documents/html/functions_vars.html create mode 100644 documents/html/generator_8cpp.html create mode 100644 documents/html/generator_8cpp_source.html create mode 100644 documents/html/generator_8h.html create mode 100644 documents/html/generator_8h_source.html create mode 100644 documents/html/generator_8inl.html create mode 100644 documents/html/generator_8inl_source.html create mode 100644 documents/html/generator__cpp_8cpp.html create mode 100644 documents/html/generator__cpp_8cpp_source.html create mode 100644 documents/html/generator__cpp_8h.html create mode 100644 documents/html/generator__cpp_8h_source.html create mode 100644 documents/html/generator__csharp_8cpp.html create mode 100644 documents/html/generator__csharp_8cpp_source.html create mode 100644 documents/html/generator__csharp_8h.html create mode 100644 documents/html/generator__csharp_8h_source.html create mode 100644 documents/html/generator__go_8cpp.html create mode 100644 documents/html/generator__go_8cpp_source.html create mode 100644 documents/html/generator__go_8h.html create mode 100644 documents/html/generator__go_8h_source.html create mode 100644 documents/html/generator__java_8cpp.html create mode 100644 documents/html/generator__java_8cpp_source.html create mode 100644 documents/html/generator__java_8h.html create mode 100644 documents/html/generator__java_8h_source.html create mode 100644 documents/html/generator__javascript_8cpp.html create mode 100644 documents/html/generator__javascript_8cpp_source.html create mode 100644 documents/html/generator__javascript_8h.html create mode 100644 documents/html/generator__javascript_8h_source.html create mode 100644 documents/html/generator__kotlin_8cpp.html create mode 100644 documents/html/generator__kotlin_8cpp_source.html create mode 100644 documents/html/generator__kotlin_8h.html create mode 100644 documents/html/generator__kotlin_8h_source.html create mode 100644 documents/html/generator__python_8cpp.html create mode 100644 documents/html/generator__python_8cpp_source.html create mode 100644 documents/html/generator__python_8h.html create mode 100644 documents/html/generator__python_8h_source.html create mode 100644 documents/html/generator__ruby_8cpp.html create mode 100644 documents/html/generator__ruby_8cpp_source.html create mode 100644 documents/html/generator__ruby_8h.html create mode 100644 documents/html/generator__ruby_8h_source.html create mode 100644 documents/html/generator__swift_8cpp.html create mode 100644 documents/html/generator__swift_8cpp_source.html create mode 100644 documents/html/generator__swift_8h.html create mode 100644 documents/html/generator__swift_8h_source.html create mode 100644 documents/html/globals.html create mode 100644 documents/html/globals_func.html create mode 100644 documents/html/globals_vars.html create mode 100644 documents/html/hierarchy.html create mode 100644 documents/html/index.html create mode 100644 documents/html/jquery.js create mode 100644 documents/html/menu.js create mode 100644 documents/html/menudata.js create mode 100644 documents/html/namespace_f_b_e.html create mode 100644 documents/html/namespacemembers.html create mode 100644 documents/html/namespacemembers_vars.html create mode 100644 documents/html/namespaces.html create mode 100644 documents/html/navtree.css create mode 100644 documents/html/search/all_0.js create mode 100644 documents/html/search/all_1.js create mode 100644 documents/html/search/all_10.js create mode 100644 documents/html/search/all_11.js create mode 100644 documents/html/search/all_12.js create mode 100644 documents/html/search/all_13.js create mode 100644 documents/html/search/all_14.js create mode 100644 documents/html/search/all_15.js create mode 100644 documents/html/search/all_16.js create mode 100644 documents/html/search/all_2.js create mode 100644 documents/html/search/all_3.js create mode 100644 documents/html/search/all_4.js create mode 100644 documents/html/search/all_5.js create mode 100644 documents/html/search/all_6.js create mode 100644 documents/html/search/all_7.js create mode 100644 documents/html/search/all_8.js create mode 100644 documents/html/search/all_9.js create mode 100644 documents/html/search/all_a.js create mode 100644 documents/html/search/all_b.js create mode 100644 documents/html/search/all_c.js create mode 100644 documents/html/search/all_d.js create mode 100644 documents/html/search/all_e.js create mode 100644 documents/html/search/all_f.js create mode 100644 documents/html/search/classes_0.js create mode 100644 documents/html/search/classes_1.js create mode 100644 documents/html/search/classes_2.js create mode 100644 documents/html/search/classes_3.js create mode 100644 documents/html/search/classes_4.js create mode 100644 documents/html/search/classes_5.js create mode 100644 documents/html/search/classes_6.js create mode 100644 documents/html/search/classes_7.js create mode 100644 documents/html/search/files_0.js create mode 100644 documents/html/search/files_1.js create mode 100644 documents/html/search/files_2.js create mode 100644 documents/html/search/functions_0.js create mode 100644 documents/html/search/functions_1.js create mode 100644 documents/html/search/functions_2.js create mode 100644 documents/html/search/functions_3.js create mode 100644 documents/html/search/functions_4.js create mode 100644 documents/html/search/functions_5.js create mode 100644 documents/html/search/functions_6.js create mode 100644 documents/html/search/functions_7.js create mode 100644 documents/html/search/functions_8.js create mode 100644 documents/html/search/functions_9.js create mode 100644 documents/html/search/functions_a.js create mode 100644 documents/html/search/functions_b.js create mode 100644 documents/html/search/functions_c.js create mode 100644 documents/html/search/namespaces_0.js create mode 100644 documents/html/search/search.css create mode 100644 documents/html/search/search.js create mode 100644 documents/html/search/searchdata.js create mode 100644 documents/html/search/variables_0.js create mode 100644 documents/html/search/variables_1.js create mode 100644 documents/html/search/variables_10.js create mode 100644 documents/html/search/variables_11.js create mode 100644 documents/html/search/variables_12.js create mode 100644 documents/html/search/variables_13.js create mode 100644 documents/html/search/variables_2.js create mode 100644 documents/html/search/variables_3.js create mode 100644 documents/html/search/variables_4.js create mode 100644 documents/html/search/variables_5.js create mode 100644 documents/html/search/variables_6.js create mode 100644 documents/html/search/variables_7.js create mode 100644 documents/html/search/variables_8.js create mode 100644 documents/html/search/variables_9.js create mode 100644 documents/html/search/variables_a.js create mode 100644 documents/html/search/variables_b.js create mode 100644 documents/html/search/variables_c.js create mode 100644 documents/html/search/variables_d.js create mode 100644 documents/html/search/variables_e.js create mode 100644 documents/html/search/variables_f.js create mode 100644 documents/html/struct_f_b_e_1_1_attributes-members.html create mode 100644 documents/html/struct_f_b_e_1_1_attributes.html create mode 100644 documents/html/struct_f_b_e_1_1_enum_body-members.html create mode 100644 documents/html/struct_f_b_e_1_1_enum_body.html create mode 100644 documents/html/struct_f_b_e_1_1_enum_const-members.html create mode 100644 documents/html/struct_f_b_e_1_1_enum_const.html create mode 100644 documents/html/struct_f_b_e_1_1_enum_type-members.html create mode 100644 documents/html/struct_f_b_e_1_1_enum_type.html create mode 100644 documents/html/struct_f_b_e_1_1_enum_value-members.html create mode 100644 documents/html/struct_f_b_e_1_1_enum_value.html create mode 100644 documents/html/struct_f_b_e_1_1_flags_body-members.html create mode 100644 documents/html/struct_f_b_e_1_1_flags_body.html create mode 100644 documents/html/struct_f_b_e_1_1_flags_const-members.html create mode 100644 documents/html/struct_f_b_e_1_1_flags_const.html create mode 100644 documents/html/struct_f_b_e_1_1_flags_type-members.html create mode 100644 documents/html/struct_f_b_e_1_1_flags_type.html create mode 100644 documents/html/struct_f_b_e_1_1_flags_value-members.html create mode 100644 documents/html/struct_f_b_e_1_1_flags_value.html create mode 100644 documents/html/struct_f_b_e_1_1_import-members.html create mode 100644 documents/html/struct_f_b_e_1_1_import.html create mode 100644 documents/html/struct_f_b_e_1_1_package-members.html create mode 100644 documents/html/struct_f_b_e_1_1_package.html create mode 100644 documents/html/struct_f_b_e_1_1_statement-members.html create mode 100644 documents/html/struct_f_b_e_1_1_statement.html create mode 100644 documents/html/struct_f_b_e_1_1_statements-members.html create mode 100644 documents/html/struct_f_b_e_1_1_statements.html create mode 100644 documents/html/struct_f_b_e_1_1_struct_body-members.html create mode 100644 documents/html/struct_f_b_e_1_1_struct_body.html create mode 100644 documents/html/struct_f_b_e_1_1_struct_field-members.html create mode 100644 documents/html/struct_f_b_e_1_1_struct_field.html create mode 100644 documents/html/struct_f_b_e_1_1_struct_reject-members.html create mode 100644 documents/html/struct_f_b_e_1_1_struct_reject.html create mode 100644 documents/html/struct_f_b_e_1_1_struct_rejects-members.html create mode 100644 documents/html/struct_f_b_e_1_1_struct_rejects.html create mode 100644 documents/html/struct_f_b_e_1_1_struct_request.html create mode 100644 documents/html/struct_f_b_e_1_1_struct_response-members.html create mode 100644 documents/html/struct_f_b_e_1_1_struct_response.html create mode 100644 documents/html/struct_f_b_e_1_1_struct_type-members.html create mode 100644 documents/html/struct_f_b_e_1_1_struct_type.html create mode 100644 documents/html/struct_f_b_e_1_1_version-members.html create mode 100644 documents/html/struct_f_b_e_1_1_version.html create mode 100644 documents/html/tabs.css create mode 100644 documents/html/version_8h.html create mode 100644 documents/html/version_8h_source.html diff --git a/documents/html/annotated.html b/documents/html/annotated.html new file mode 100644 index 000000000..0590ecb61 --- /dev/null +++ b/documents/html/annotated.html @@ -0,0 +1,121 @@ + + + + + + + +FastBinaryEncoding: Class List + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + +
+
+ +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
Class List
+
+
+
Here are the classes, structs, unions and interfaces with brief descriptions:
+
+ + +
+ + diff --git a/documents/html/class_f_b_e_1_1_generator-members.html b/documents/html/class_f_b_e_1_1_generator-members.html new file mode 100644 index 000000000..bf2532c1a --- /dev/null +++ b/documents/html/class_f_b_e_1_1_generator-members.html @@ -0,0 +1,111 @@ + + + + + + + +FastBinaryEncoding: Member List + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+
FBE::Generator Member List
+
+
+ +

This is the complete list of members for FBE::Generator, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + +
_bufferFBE::Generatorprotected
_cursorFBE::Generatorprotected
_indentFBE::Generatorprotected
_inputFBE::Generatorprotected
_outputFBE::Generatorprotected
_spaceFBE::Generatorprotected
EndLine()FBE::Generatorinlineprotectedstatic
Generate(const std::shared_ptr< Package > &package)=0FBE::Generatorpure virtual
Generator(const std::string &input, const std::string &output, int indent, char space)FBE::Generatorinline
Indent(int count)FBE::Generatorinlineprotected
Store(const CppCommon::Path &filename)FBE::Generatorprotected
Write(const std::string &str)FBE::Generatorinlineprotected
WriteBegin()FBE::Generatorinlineprotected
WriteEnd()FBE::Generatorinlineprotected
WriteIndent()FBE::Generatorinlineprotected
WriteIndent(const std::string &str)FBE::Generatorinlineprotected
WriteLine()FBE::Generatorinlineprotected
WriteLine(const std::string &str)FBE::Generatorinlineprotected
WriteLineIndent(const std::string &str)FBE::Generatorinlineprotected
+ + +
+ + diff --git a/documents/html/class_f_b_e_1_1_generator.html b/documents/html/class_f_b_e_1_1_generator.html new file mode 100644 index 000000000..d521570db --- /dev/null +++ b/documents/html/class_f_b_e_1_1_generator.html @@ -0,0 +1,666 @@ + + + + + + + +FastBinaryEncoding: FBE::Generator Class Reference + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+ +
+ +

#include <generator.h>

+
+Inheritance diagram for FBE::Generator:
+
+
+ + +FBE::GeneratorCSharp +FBE::GeneratorCpp +FBE::GeneratorGo +FBE::GeneratorJava +FBE::GeneratorJavaScript +FBE::GeneratorKotlin +FBE::GeneratorPython +FBE::GeneratorRuby +FBE::GeneratorSwift + +
+ + + + +

+Public Member Functions

 Generator (const std::string &input, const std::string &output, int indent, char space)
virtual void Generate (const std::shared_ptr< Package > &package)=0
+ + + + + + + + + + + +

+Protected Member Functions

void Indent (int count)
void WriteBegin ()
void Write (const std::string &str)
void WriteIndent ()
void WriteIndent (const std::string &str)
void WriteLine ()
void WriteLine (const std::string &str)
void WriteLineIndent (const std::string &str)
void WriteEnd ()
void Store (const CppCommon::Path &filename)
+ + +

+Static Protected Member Functions

static std::string EndLine ()
+ + + + + + + +

+Protected Attributes

std::string _buffer
std::string _input
std::string _output
int _cursor {0}
int _indent
char _space
+

Detailed Description

+
+

Definition at line 16 of file generator.h.

+

Constructor & Destructor Documentation

+ +

◆ Generator()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
FBE::Generator::Generator (const std::string & input,
const std::string & output,
int indent,
char space )
+
+inline
+
+ +

Definition at line 11 of file generator.inl.

+ +
+
+

Member Function Documentation

+ +

◆ EndLine()

+ +
+
+ + + + + +
+ + + + + + + +
std::string FBE::Generator::EndLine ()
+
+inlinestaticprotected
+
+ +

Definition at line 68 of file generator.inl.

+ +
+
+ +

◆ Generate()

+ +
+
+ + + + + +
+ + + + + + + +
virtual void FBE::Generator::Generate (const std::shared_ptr< Package > & package)
+
+pure virtual
+
+
+ +

◆ Indent()

+ +
+
+ + + + + +
+ + + + + + + +
void FBE::Generator::Indent (int count)
+
+inlineprotected
+
+ +

Definition at line 19 of file generator.inl.

+ +
+
+ +

◆ Store()

+ +
+
+ + + + + +
+ + + + + + + +
void FBE::Generator::Store (const CppCommon::Path & filename)
+
+protected
+
+ +

Definition at line 17 of file generator.cpp.

+ +
+
+ +

◆ Write()

+ +
+
+ + + + + +
+ + + + + + + +
void FBE::Generator::Write (const std::string & str)
+
+inlineprotected
+
+ +

Definition at line 29 of file generator.inl.

+ +
+
+ +

◆ WriteBegin()

+ +
+
+ + + + + +
+ + + + + + + +
void FBE::Generator::WriteBegin ()
+
+inlineprotected
+
+ +

Definition at line 24 of file generator.inl.

+ +
+
+ +

◆ WriteEnd()

+ +
+
+ + + + + +
+ + + + + + + +
void FBE::Generator::WriteEnd ()
+
+inlineprotected
+
+ +

Definition at line 64 of file generator.inl.

+ +
+
+ +

◆ WriteIndent() [1/2]

+ +
+
+ + + + + +
+ + + + + + + +
void FBE::Generator::WriteIndent ()
+
+inlineprotected
+
+ +

Definition at line 34 of file generator.inl.

+ +
+
+ +

◆ WriteIndent() [2/2]

+ +
+
+ + + + + +
+ + + + + + + +
void FBE::Generator::WriteIndent (const std::string & str)
+
+inlineprotected
+
+ +

Definition at line 40 of file generator.inl.

+ +
+
+ +

◆ WriteLine() [1/2]

+ +
+
+ + + + + +
+ + + + + + + +
void FBE::Generator::WriteLine ()
+
+inlineprotected
+
+ +

Definition at line 47 of file generator.inl.

+ +
+
+ +

◆ WriteLine() [2/2]

+ +
+
+ + + + + +
+ + + + + + + +
void FBE::Generator::WriteLine (const std::string & str)
+
+inlineprotected
+
+ +

Definition at line 52 of file generator.inl.

+ +
+
+ +

◆ WriteLineIndent()

+ +
+
+ + + + + +
+ + + + + + + +
void FBE::Generator::WriteLineIndent (const std::string & str)
+
+inlineprotected
+
+ +

Definition at line 58 of file generator.inl.

+ +
+
+

Member Data Documentation

+ +

◆ _buffer

+ +
+
+ + + + + +
+ + + + +
std::string FBE::Generator::_buffer
+
+protected
+
+ +

Definition at line 24 of file generator.h.

+ +
+
+ +

◆ _cursor

+ +
+
+ + + + + +
+ + + + +
int FBE::Generator::_cursor {0}
+
+protected
+
+ +

Definition at line 27 of file generator.h.

+ +
+
+ +

◆ _indent

+ +
+
+ + + + + +
+ + + + +
int FBE::Generator::_indent
+
+protected
+
+ +

Definition at line 28 of file generator.h.

+ +
+
+ +

◆ _input

+ +
+
+ + + + + +
+ + + + +
std::string FBE::Generator::_input
+
+protected
+
+ +

Definition at line 25 of file generator.h.

+ +
+
+ +

◆ _output

+ +
+
+ + + + + +
+ + + + +
std::string FBE::Generator::_output
+
+protected
+
+ +

Definition at line 26 of file generator.h.

+ +
+
+ +

◆ _space

+ +
+
+ + + + + +
+ + + + +
char FBE::Generator::_space
+
+protected
+
+ +

Definition at line 29 of file generator.h.

+ +
+
+
The documentation for this class was generated from the following files: +
+ + +
+ + diff --git a/documents/html/class_f_b_e_1_1_generator.png b/documents/html/class_f_b_e_1_1_generator.png new file mode 100644 index 0000000000000000000000000000000000000000..a1421146bbc90cdc5a1b921766cf0455a47f9e09 GIT binary patch literal 3848 zcmd5^gt0Ywthz^FCY`@BKW# z`~LlYcOeoHzQK8mGYACQ5OE+31p+z1L7+8ny}s7A^T1giYzrR9Nc29d)oNQleP$q* z+^Y}V2~Kfm{PI+#QrY%*cgNJ&esem7LL36w-WMOpn)3gEKrZJZ!ahc4I7|*s5QZPE zSwEEC_|M)2*z`Mlt31B&N%*k+I`(F#qV+w?{$7h%ZhQP3r#>@n5v67g!h?!O+#Bd4 zfyJdSEfvKx{PT$Z&WskCr)ZjInHTmiMEi5Yds98#SYmx(@kj@JeuFyXqNWelPd?>| zPy%@AGu!qE^vuk21EsKe#EEbbD%>y{I?B4eAvp$|ICjhULfpq=IL4L#Va zL85lU*_N!xgeIvS8LGw@rJtt&Lz&l9Y-@C|2*tLP!yC3V(AiOqbav^|(jLZQqg^_7 z@>4($nc+@T(PbOoMS&gu@=8Ll&Nu&vdwfvNiKrTM_TY=0Y+05na%U#=yAs_-)Kr=F ziI-lwNm)Q>3H^axBsuoE;Yk0N)U4rpWKZ=N)7)GcE*jEjTZl{nGq5r>D4M9uJj4|G zhxLq*P0v3%Z+wF}vqQ;maAZ)ghiP`9KY&nT67P@pi{b z{d2*60%a>(e>V}~;;i~n&=rAxC$_}v-b6~})Eog537X_t!0B3OMM zTjlS3v*QiNwR4-LW0a&=P|CnW3_^1+!srnf%&n_!E7F2$(ee!+1@snKSq? zEOh#;FQb23L+c#24&!}0bX4R+bzaRaK;L8`n?%X%(#ad|^-Zq}I>=JKrem6)&4kH< z1#)|de|oh&=0va&Q?v=A)knL|@ps^od&D{_4xfbNY{w)U*L8IarDP!3MiW?V3Q~p$ zn)W+Q(Jji&&!^W?%L$p6$14>j1RaNeWvipyO=;SFXV1}Fr?pXNfwUjVws6Z(yHQ}w zw%>%_rpxyJ9Rd>9^O&JR)P*rxy>9Lb-07_bI;ixOgfTL`W9OSqo_lZlpxA9m zt5XyHYneR65=sq)=ixXQs=dD(nAT51Q2y4_E7d*g>g$cy;lOSX@%#%K+1-us!6W*M z-5gGC6EsqEevvA-38ND85rc#r?b9*zwJJmL*MUy_;N%&OZA{@+lZ& zJ+^dypVcV+Vc}uD%ahc{K<2C@ zeXCc#)HrX~+1iO>@maEVI}P8}y)9_)m=9x~S$?J{7wC&1w2<0z#_J&D*d*@B_T7)2 z69H(N;u3$MZSMPJOw?qde`H)&=gHa67%X8pIndKZ5ajN{GTI-_6VP3pc zm-qE&Ez}4LX_=N{S7<4Yq|VB-{J&Gga_8^M1{3(A0tI>Y(-;BY$ zn}ZBqU<~WY)<{EoEm|Olm3~k=F0hn-1;*@J&AR3tT}Rx{xVgOhMCa=OWxp~duziTK z)vot`HoY&Tvzy{pX;rTW@_#Uh&VC$>v{`x-ak?e45&CSJT#G$gp?%@!fj+ewQ9h>U zv6u9K7x11=Kc9I0?vrkRusr-q5{0qCL^e;q3s8U5Mr4lHxsvY!m@&$^Zlv_y%~~wC zjfmlfem9d6=*c`c-nQ&5X%n1*HopM#K6p;OUK=|la-HMSf%RkOd?DJdiQegilzSh^w3rS*!Pb)_Ex{ca2f4E_RlEx@ns{u;-@iojt;PKG!VTe z3;lc8`TzHy`Vc$vu{Pv4fiZaQ3y*J4ja2n~k2%slP~i={+m4BnV0Zj zsQf!7S#McXask~sDu1xt++kLL*J$RnIEA!8IWSbS& zk`=B|lu3Wt_-)?pH2g0J?hSkotAw@)L|Q!4II$*e?c)G0OBk_4J%;_TS}Y7G&-*GW z2%khrvk>7qfS$If%_4gFr_kI*ZDu|i>~wC+pmFS`Q!b)L&C6p_a)47MD8u^I*Z$HQ ieqYd=9aHzruC<35xqI^q(6*Ts6tNEx#`)xn)Bgnm>n+3p literal 0 HcmV?d00001 diff --git a/documents/html/class_f_b_e_1_1_generator_c_sharp-members.html b/documents/html/class_f_b_e_1_1_generator_c_sharp-members.html new file mode 100644 index 000000000..68a5aa470 --- /dev/null +++ b/documents/html/class_f_b_e_1_1_generator_c_sharp-members.html @@ -0,0 +1,117 @@ + + + + + + + +FastBinaryEncoding: Member List + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+
FBE::GeneratorCSharp Member List
+
+
+ +

This is the complete list of members for FBE::GeneratorCSharp, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
_bufferFBE::Generatorprotected
_cursorFBE::Generatorprotected
_indentFBE::Generatorprotected
_inputFBE::Generatorprotected
_outputFBE::Generatorprotected
_spaceFBE::Generatorprotected
EndLine()FBE::Generatorinlineprotectedstatic
Final() const noexceptFBE::GeneratorCSharpinline
Final(bool final) noexceptFBE::GeneratorCSharpinline
Generate(const std::shared_ptr< Package > &package) overrideFBE::GeneratorCSharpvirtual
Generator(const std::string &input, const std::string &output, int indent, char space)FBE::GeneratorCSharpinline
Indent(int count)FBE::Generatorinlineprotected
JSON() const noexceptFBE::GeneratorCSharpinline
JSON(bool json) noexceptFBE::GeneratorCSharpinline
Proto() const noexceptFBE::GeneratorCSharpinline
Proto(bool proto) noexceptFBE::GeneratorCSharpinline
Store(const CppCommon::Path &filename)FBE::Generatorprotected
Write(const std::string &str)FBE::Generatorinlineprotected
WriteBegin()FBE::Generatorinlineprotected
WriteEnd()FBE::Generatorinlineprotected
WriteIndent()FBE::Generatorinlineprotected
WriteIndent(const std::string &str)FBE::Generatorinlineprotected
WriteLine()FBE::Generatorinlineprotected
WriteLine(const std::string &str)FBE::Generatorinlineprotected
WriteLineIndent(const std::string &str)FBE::Generatorinlineprotected
+ + +
+ + diff --git a/documents/html/class_f_b_e_1_1_generator_c_sharp.html b/documents/html/class_f_b_e_1_1_generator_c_sharp.html new file mode 100644 index 000000000..dd3ced5b0 --- /dev/null +++ b/documents/html/class_f_b_e_1_1_generator_c_sharp.html @@ -0,0 +1,380 @@ + + + + + + + +FastBinaryEncoding: FBE::GeneratorCSharp Class Reference + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+ +
FBE::GeneratorCSharp Class Reference
+
+
+ +

#include <generator_csharp.h>

+
+Inheritance diagram for FBE::GeneratorCSharp:
+
+
+ + +FBE::Generator + +
+ + + + + + + + + + + + +

+Public Member Functions

bool Final () const noexcept
GeneratorCSharp & Final (bool final) noexcept
bool JSON () const noexcept
GeneratorCSharp & JSON (bool json) noexcept
bool Proto () const noexcept
GeneratorCSharp & Proto (bool proto) noexcept
void Generate (const std::shared_ptr< Package > &package) override
 Generator (const std::string &input, const std::string &output, int indent, char space)
Public Member Functions inherited from FBE::Generator
 Generator (const std::string &input, const std::string &output, int indent, char space)
+ + + + + + + + + + + + + + + + + + + + + +

+Additional Inherited Members

Protected Member Functions inherited from FBE::Generator
void Indent (int count)
void WriteBegin ()
void Write (const std::string &str)
void WriteIndent ()
void WriteIndent (const std::string &str)
void WriteLine ()
void WriteLine (const std::string &str)
void WriteLineIndent (const std::string &str)
void WriteEnd ()
void Store (const CppCommon::Path &filename)
Static Protected Member Functions inherited from FBE::Generator
static std::string EndLine ()
Protected Attributes inherited from FBE::Generator
std::string _buffer
std::string _input
std::string _output
int _cursor {0}
int _indent
char _space
+

Detailed Description

+
+

Definition at line 16 of file generator_csharp.h.

+

Member Function Documentation

+ +

◆ Final() [1/2]

+ +
+
+ + + + + +
+ + + + + + + +
bool FBE::GeneratorCSharp::Final () const
+
+inlinenoexcept
+
+ +

Definition at line 22 of file generator_csharp.h.

+ +
+
+ +

◆ Final() [2/2]

+ +
+
+ + + + + +
+ + + + + + + +
GeneratorCSharp & FBE::GeneratorCSharp::Final (bool final)
+
+inlinenoexcept
+
+ +

Definition at line 23 of file generator_csharp.h.

+ +
+
+ +

◆ Generate()

+ +
+
+ + + + + +
+ + + + + + + +
void FBE::GeneratorCSharp::Generate (const std::shared_ptr< Package > & package)
+
+overridevirtual
+
+ +

Implements FBE::Generator.

+ +

Definition at line 13 of file generator_csharp.cpp.

+ +
+
+ +

◆ Generator()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
FBE::Generator::Generator (const std::string & input,
const std::string & output,
int indent,
char space )
+
+inline
+
+ +

Definition at line 19 of file generator.inl.

+ +
+
+ +

◆ JSON() [1/2]

+ +
+
+ + + + + +
+ + + + + + + +
bool FBE::GeneratorCSharp::JSON () const
+
+inlinenoexcept
+
+ +

Definition at line 26 of file generator_csharp.h.

+ +
+
+ +

◆ JSON() [2/2]

+ +
+
+ + + + + +
+ + + + + + + +
GeneratorCSharp & FBE::GeneratorCSharp::JSON (bool json)
+
+inlinenoexcept
+
+ +

Definition at line 27 of file generator_csharp.h.

+ +
+
+ +

◆ Proto() [1/2]

+ +
+
+ + + + + +
+ + + + + + + +
bool FBE::GeneratorCSharp::Proto () const
+
+inlinenoexcept
+
+ +

Definition at line 30 of file generator_csharp.h.

+ +
+
+ +

◆ Proto() [2/2]

+ +
+
+ + + + + +
+ + + + + + + +
GeneratorCSharp & FBE::GeneratorCSharp::Proto (bool proto)
+
+inlinenoexcept
+
+ +

Definition at line 31 of file generator_csharp.h.

+ +
+
+
The documentation for this class was generated from the following files: +
+ + +
+ + diff --git a/documents/html/class_f_b_e_1_1_generator_c_sharp.png b/documents/html/class_f_b_e_1_1_generator_c_sharp.png new file mode 100644 index 0000000000000000000000000000000000000000..84e72017537d4b7feec2f61ff8efcbe44895f197 GIT binary patch literal 622 zcmeAS@N?(olHy`uVBq!ia0vp^eLx(*!3-pSi0@4WQqloFA+G=b{|7Q(y!l$%e`vXd zfo6fk^fNCWJa_;UH$5A+1SrQ@666=m0OW&#In(Sb3=E7vJzX3_Dj46+eZB6n0#8eO zXUN&#_8*t2HuyfuJHNI)cIT;+t(GkUy9-YpUCeC|2<@oyy z-}`-&pWOd4=`y#)w!O&{O~Q>QKMCH;n*OD4@9o0xV zck;YHu4&zTdCif{5`Ob^7&@j}FbHTCGAIN+VsKb;gt5V+lbKl|3g~`RTq{Z2I@zi>gT_YbOWKzVXN_Xhmc4;kz4E zX0D#8`f_EOy!d;W@JV~)j!5qP*7tYn>w>%C)vK@B6&|rao3kvu;ML;pUlAK-XQv%M zar4%_#pavOfA|aygr<2no=@aU=@GA!_qw*?%RbL#cE3GZjB~pe|JLa{Khyu==DQmU z^=s_fiUSoLFIcvQt7p%v47Gk{oS41b{g(CKrZ?02P37g@rLf+gYqmLguKzTZzmwh^ wH!D=xnQb_y{(*e#q`G*JC(7moc}2R_Gjx0^<;e4R4N5f(p00i_>zopr0PFTD_5c6? literal 0 HcmV?d00001 diff --git a/documents/html/class_f_b_e_1_1_generator_cpp-members.html b/documents/html/class_f_b_e_1_1_generator_cpp-members.html new file mode 100644 index 000000000..6e054cfac --- /dev/null +++ b/documents/html/class_f_b_e_1_1_generator_cpp-members.html @@ -0,0 +1,119 @@ + + + + + + + +FastBinaryEncoding: Member List + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+
FBE::GeneratorCpp Member List
+
+
+ +

This is the complete list of members for FBE::GeneratorCpp, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
_bufferFBE::Generatorprotected
_cursorFBE::Generatorprotected
_indentFBE::Generatorprotected
_inputFBE::Generatorprotected
_outputFBE::Generatorprotected
_spaceFBE::Generatorprotected
EndLine()FBE::Generatorinlineprotectedstatic
Final() const noexceptFBE::GeneratorCppinline
Final(bool final) noexceptFBE::GeneratorCppinline
Generate(const std::shared_ptr< Package > &package) overrideFBE::GeneratorCppvirtual
Generator(const std::string &input, const std::string &output, int indent, char space)FBE::GeneratorCppinline
Indent(int count)FBE::Generatorinlineprotected
JSON() const noexceptFBE::GeneratorCppinline
JSON(bool json) noexceptFBE::GeneratorCppinline
Logging() const noexceptFBE::GeneratorCppinline
Logging(bool logging) noexceptFBE::GeneratorCppinline
Proto() const noexceptFBE::GeneratorCppinline
Proto(bool proto) noexceptFBE::GeneratorCppinline
Store(const CppCommon::Path &filename)FBE::Generatorprotected
Write(const std::string &str)FBE::Generatorinlineprotected
WriteBegin()FBE::Generatorinlineprotected
WriteEnd()FBE::Generatorinlineprotected
WriteIndent()FBE::Generatorinlineprotected
WriteIndent(const std::string &str)FBE::Generatorinlineprotected
WriteLine()FBE::Generatorinlineprotected
WriteLine(const std::string &str)FBE::Generatorinlineprotected
WriteLineIndent(const std::string &str)FBE::Generatorinlineprotected
+ + +
+ + diff --git a/documents/html/class_f_b_e_1_1_generator_cpp.html b/documents/html/class_f_b_e_1_1_generator_cpp.html new file mode 100644 index 000000000..d03313fda --- /dev/null +++ b/documents/html/class_f_b_e_1_1_generator_cpp.html @@ -0,0 +1,436 @@ + + + + + + + +FastBinaryEncoding: FBE::GeneratorCpp Class Reference + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+ +
FBE::GeneratorCpp Class Reference
+
+
+ +

#include <generator_cpp.h>

+
+Inheritance diagram for FBE::GeneratorCpp:
+
+
+ + +FBE::Generator + +
+ + + + + + + + + + + + + + +

+Public Member Functions

bool Final () const noexcept
GeneratorCpp & Final (bool final) noexcept
bool JSON () const noexcept
GeneratorCpp & JSON (bool json) noexcept
bool Proto () const noexcept
GeneratorCpp & Proto (bool proto) noexcept
bool Logging () const noexcept
GeneratorCpp & Logging (bool logging) noexcept
void Generate (const std::shared_ptr< Package > &package) override
 Generator (const std::string &input, const std::string &output, int indent, char space)
Public Member Functions inherited from FBE::Generator
 Generator (const std::string &input, const std::string &output, int indent, char space)
+ + + + + + + + + + + + + + + + + + + + + +

+Additional Inherited Members

Protected Member Functions inherited from FBE::Generator
void Indent (int count)
void WriteBegin ()
void Write (const std::string &str)
void WriteIndent ()
void WriteIndent (const std::string &str)
void WriteLine ()
void WriteLine (const std::string &str)
void WriteLineIndent (const std::string &str)
void WriteEnd ()
void Store (const CppCommon::Path &filename)
Static Protected Member Functions inherited from FBE::Generator
static std::string EndLine ()
Protected Attributes inherited from FBE::Generator
std::string _buffer
std::string _input
std::string _output
int _cursor {0}
int _indent
char _space
+

Detailed Description

+
+

Definition at line 16 of file generator_cpp.h.

+

Member Function Documentation

+ +

◆ Final() [1/2]

+ +
+
+ + + + + +
+ + + + + + + +
bool FBE::GeneratorCpp::Final () const
+
+inlinenoexcept
+
+ +

Definition at line 22 of file generator_cpp.h.

+ +
+
+ +

◆ Final() [2/2]

+ +
+
+ + + + + +
+ + + + + + + +
GeneratorCpp & FBE::GeneratorCpp::Final (bool final)
+
+inlinenoexcept
+
+ +

Definition at line 23 of file generator_cpp.h.

+ +
+
+ +

◆ Generate()

+ +
+
+ + + + + +
+ + + + + + + +
void FBE::GeneratorCpp::Generate (const std::shared_ptr< Package > & package)
+
+overridevirtual
+
+ +

Implements FBE::Generator.

+ +

Definition at line 13 of file generator_cpp.cpp.

+ +
+
+ +

◆ Generator()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
FBE::Generator::Generator (const std::string & input,
const std::string & output,
int indent,
char space )
+
+inline
+
+ +

Definition at line 19 of file generator.inl.

+ +
+
+ +

◆ JSON() [1/2]

+ +
+
+ + + + + +
+ + + + + + + +
bool FBE::GeneratorCpp::JSON () const
+
+inlinenoexcept
+
+ +

Definition at line 26 of file generator_cpp.h.

+ +
+
+ +

◆ JSON() [2/2]

+ +
+
+ + + + + +
+ + + + + + + +
GeneratorCpp & FBE::GeneratorCpp::JSON (bool json)
+
+inlinenoexcept
+
+ +

Definition at line 27 of file generator_cpp.h.

+ +
+
+ +

◆ Logging() [1/2]

+ +
+
+ + + + + +
+ + + + + + + +
bool FBE::GeneratorCpp::Logging () const
+
+inlinenoexcept
+
+ +

Definition at line 34 of file generator_cpp.h.

+ +
+
+ +

◆ Logging() [2/2]

+ +
+
+ + + + + +
+ + + + + + + +
GeneratorCpp & FBE::GeneratorCpp::Logging (bool logging)
+
+inlinenoexcept
+
+ +

Definition at line 35 of file generator_cpp.h.

+ +
+
+ +

◆ Proto() [1/2]

+ +
+
+ + + + + +
+ + + + + + + +
bool FBE::GeneratorCpp::Proto () const
+
+inlinenoexcept
+
+ +

Definition at line 30 of file generator_cpp.h.

+ +
+
+ +

◆ Proto() [2/2]

+ +
+
+ + + + + +
+ + + + + + + +
GeneratorCpp & FBE::GeneratorCpp::Proto (bool proto)
+
+inlinenoexcept
+
+ +

Definition at line 31 of file generator_cpp.h.

+ +
+
+
The documentation for this class was generated from the following files: +
+ + +
+ + diff --git a/documents/html/class_f_b_e_1_1_generator_cpp.png b/documents/html/class_f_b_e_1_1_generator_cpp.png new file mode 100644 index 0000000000000000000000000000000000000000..cfeca861a3e48000be7db8ab1d1ba143d3546c1c GIT binary patch literal 535 zcmeAS@N?(olHy`uVBq!ia0vp^RX`lT!3-oHZkX5xq@)9ULR|m<{|{uoc=NTi|Il&^ z1I+@7>1SR%c<=xyZhAIs2~du+B*-tA0mugfbEer>7#J8AdAc};R4~4so85Oi3rI$(gh-j5kCpR4t+TCxi9hUWw#6$}W@UENoRf+4#$-WXIp4>>O*qN$0<$ zTvEKX?Y5Z5tmQjAKP|ND%M05#Is5jSvuFN(I~6zSTP6G4U8TK8_BL*|PF>zxq3`+q z&e_uYRg2gyPUOwM_PdiiKQw|r{@s4DN1Yk<@9lV(&-taW*!BtY3%%>9;M839-s?=@Qlo^d!%O3PTNnz>*fO2?Z?&$&sFt2e#>{4^oSHTlJEcG@%>r0L^jlg|9w zF1hZ|+48>&4ynHMDOHcj@RVBJI&DegtZqKV7R_JG6J%0y1U{UM14bc(r>mdKI;Vst E0Iu2l5&!@I literal 0 HcmV?d00001 diff --git a/documents/html/class_f_b_e_1_1_generator_go-members.html b/documents/html/class_f_b_e_1_1_generator_go-members.html new file mode 100644 index 000000000..c18a8a905 --- /dev/null +++ b/documents/html/class_f_b_e_1_1_generator_go-members.html @@ -0,0 +1,117 @@ + + + + + + + +FastBinaryEncoding: Member List + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+
FBE::GeneratorGo Member List
+
+
+ +

This is the complete list of members for FBE::GeneratorGo, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
_bufferFBE::Generatorprotected
_cursorFBE::Generatorprotected
_indentFBE::Generatorprotected
_inputFBE::Generatorprotected
_outputFBE::Generatorprotected
_spaceFBE::Generatorprotected
EndLine()FBE::Generatorinlineprotectedstatic
Final() const noexceptFBE::GeneratorGoinline
Final(bool final) noexceptFBE::GeneratorGoinline
Generate(const std::shared_ptr< Package > &package) overrideFBE::GeneratorGovirtual
Generator(const std::string &input, const std::string &output, int indent, char space)FBE::GeneratorGoinline
Indent(int count)FBE::Generatorinlineprotected
JSON() const noexceptFBE::GeneratorGoinline
JSON(bool json) noexceptFBE::GeneratorGoinline
Proto() const noexceptFBE::GeneratorGoinline
Proto(bool proto) noexceptFBE::GeneratorGoinline
Store(const CppCommon::Path &filename)FBE::Generatorprotected
Write(const std::string &str)FBE::Generatorinlineprotected
WriteBegin()FBE::Generatorinlineprotected
WriteEnd()FBE::Generatorinlineprotected
WriteIndent()FBE::Generatorinlineprotected
WriteIndent(const std::string &str)FBE::Generatorinlineprotected
WriteLine()FBE::Generatorinlineprotected
WriteLine(const std::string &str)FBE::Generatorinlineprotected
WriteLineIndent(const std::string &str)FBE::Generatorinlineprotected
+ + +
+ + diff --git a/documents/html/class_f_b_e_1_1_generator_go.html b/documents/html/class_f_b_e_1_1_generator_go.html new file mode 100644 index 000000000..d78168abe --- /dev/null +++ b/documents/html/class_f_b_e_1_1_generator_go.html @@ -0,0 +1,380 @@ + + + + + + + +FastBinaryEncoding: FBE::GeneratorGo Class Reference + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+ +
FBE::GeneratorGo Class Reference
+
+
+ +

#include <generator_go.h>

+
+Inheritance diagram for FBE::GeneratorGo:
+
+
+ + +FBE::Generator + +
+ + + + + + + + + + + + +

+Public Member Functions

bool Final () const noexcept
GeneratorGo & Final (bool final) noexcept
bool JSON () const noexcept
GeneratorGo & JSON (bool json) noexcept
bool Proto () const noexcept
GeneratorGo & Proto (bool proto) noexcept
void Generate (const std::shared_ptr< Package > &package) override
 Generator (const std::string &input, const std::string &output, int indent, char space)
Public Member Functions inherited from FBE::Generator
 Generator (const std::string &input, const std::string &output, int indent, char space)
+ + + + + + + + + + + + + + + + + + + + + +

+Additional Inherited Members

Protected Member Functions inherited from FBE::Generator
void Indent (int count)
void WriteBegin ()
void Write (const std::string &str)
void WriteIndent ()
void WriteIndent (const std::string &str)
void WriteLine ()
void WriteLine (const std::string &str)
void WriteLineIndent (const std::string &str)
void WriteEnd ()
void Store (const CppCommon::Path &filename)
Static Protected Member Functions inherited from FBE::Generator
static std::string EndLine ()
Protected Attributes inherited from FBE::Generator
std::string _buffer
std::string _input
std::string _output
int _cursor {0}
int _indent
char _space
+

Detailed Description

+
+

Definition at line 16 of file generator_go.h.

+

Member Function Documentation

+ +

◆ Final() [1/2]

+ +
+
+ + + + + +
+ + + + + + + +
bool FBE::GeneratorGo::Final () const
+
+inlinenoexcept
+
+ +

Definition at line 22 of file generator_go.h.

+ +
+
+ +

◆ Final() [2/2]

+ +
+
+ + + + + +
+ + + + + + + +
GeneratorGo & FBE::GeneratorGo::Final (bool final)
+
+inlinenoexcept
+
+ +

Definition at line 23 of file generator_go.h.

+ +
+
+ +

◆ Generate()

+ +
+
+ + + + + +
+ + + + + + + +
void FBE::GeneratorGo::Generate (const std::shared_ptr< Package > & package)
+
+overridevirtual
+
+ +

Implements FBE::Generator.

+ +

Definition at line 13 of file generator_go.cpp.

+ +
+
+ +

◆ Generator()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
FBE::Generator::Generator (const std::string & input,
const std::string & output,
int indent,
char space )
+
+inline
+
+ +

Definition at line 19 of file generator.inl.

+ +
+
+ +

◆ JSON() [1/2]

+ +
+
+ + + + + +
+ + + + + + + +
bool FBE::GeneratorGo::JSON () const
+
+inlinenoexcept
+
+ +

Definition at line 26 of file generator_go.h.

+ +
+
+ +

◆ JSON() [2/2]

+ +
+
+ + + + + +
+ + + + + + + +
GeneratorGo & FBE::GeneratorGo::JSON (bool json)
+
+inlinenoexcept
+
+ +

Definition at line 27 of file generator_go.h.

+ +
+
+ +

◆ Proto() [1/2]

+ +
+
+ + + + + +
+ + + + + + + +
bool FBE::GeneratorGo::Proto () const
+
+inlinenoexcept
+
+ +

Definition at line 30 of file generator_go.h.

+ +
+
+ +

◆ Proto() [2/2]

+ +
+
+ + + + + +
+ + + + + + + +
GeneratorGo & FBE::GeneratorGo::Proto (bool proto)
+
+inlinenoexcept
+
+ +

Definition at line 31 of file generator_go.h.

+ +
+
+
The documentation for this class was generated from the following files: +
+ + +
+ + diff --git a/documents/html/class_f_b_e_1_1_generator_go.png b/documents/html/class_f_b_e_1_1_generator_go.png new file mode 100644 index 0000000000000000000000000000000000000000..7912f2ce1809563f625dcc394ccf13c8e481805b GIT binary patch literal 517 zcmeAS@N?(olHy`uVBq!ia0vp^#Xuau!3-p2m+tZbQqloFA+G=b{|7Q(y!l$%e`vXd zfo6fk^fNCWJa_;UH$5A+1SrQ@666=m0OW&#In(Sb3=E7DJY5_^Dj46+jqN+Ez|+$1 zxT@yAaDH$dug2}%>`g(jsZ3@w^f%tMQ9dSN&OK3O`>B~KnTzWW^7O~cS?`WlKY71o zQ)b$?#|PDJ#vb*ZwEUOM=15EK?;9iAXFh*BZSQ)6%UjsgA2iRnyHX(6wYq-&bBnAg zc9C=KY!lwsYHweA^wsNWA=mXbC%h7Q-BbU~Ry`vJ#*3a3$uFYgfP)TQM z=$*sKU{<8YaN`6}Kp9D3j#i6+8MmWL%IZ0qN=b{oXRciQ>Bh~{#hYAQuFWz#+t_>a zxJ-`V%XN>$1TC-bNEiH}g6y9?$q$0hn5wbb{q?26 zEB3+s;@eSc_T_n&=1yY`wv11FCBonNTcbE|YpU4u9{$GcX94G%?0ceQVzst9e|; + + + + + + +FastBinaryEncoding: Member List + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+
FBE::GeneratorJava Member List
+
+
+ +

This is the complete list of members for FBE::GeneratorJava, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
_bufferFBE::Generatorprotected
_cursorFBE::Generatorprotected
_indentFBE::Generatorprotected
_inputFBE::Generatorprotected
_outputFBE::Generatorprotected
_spaceFBE::Generatorprotected
EndLine()FBE::Generatorinlineprotectedstatic
Final() const noexceptFBE::GeneratorJavainline
Final(bool final) noexceptFBE::GeneratorJavainline
Generate(const std::shared_ptr< Package > &package) overrideFBE::GeneratorJavavirtual
Generator(const std::string &input, const std::string &output, int indent, char space)FBE::GeneratorJavainline
Indent(int count)FBE::Generatorinlineprotected
JSON() const noexceptFBE::GeneratorJavainline
JSON(bool json) noexceptFBE::GeneratorJavainline
Proto() const noexceptFBE::GeneratorJavainline
Proto(bool proto) noexceptFBE::GeneratorJavainline
Store(const CppCommon::Path &filename)FBE::Generatorprotected
Version() const noexceptFBE::GeneratorJavainline
Version(int v) noexceptFBE::GeneratorJavainline
Write(const std::string &str)FBE::Generatorinlineprotected
WriteBegin()FBE::Generatorinlineprotected
WriteEnd()FBE::Generatorinlineprotected
WriteIndent()FBE::Generatorinlineprotected
WriteIndent(const std::string &str)FBE::Generatorinlineprotected
WriteLine()FBE::Generatorinlineprotected
WriteLine(const std::string &str)FBE::Generatorinlineprotected
WriteLineIndent(const std::string &str)FBE::Generatorinlineprotected
+ + +
+ + diff --git a/documents/html/class_f_b_e_1_1_generator_java.html b/documents/html/class_f_b_e_1_1_generator_java.html new file mode 100644 index 000000000..e14531142 --- /dev/null +++ b/documents/html/class_f_b_e_1_1_generator_java.html @@ -0,0 +1,436 @@ + + + + + + + +FastBinaryEncoding: FBE::GeneratorJava Class Reference + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+ +
FBE::GeneratorJava Class Reference
+
+
+ +

#include <generator_java.h>

+
+Inheritance diagram for FBE::GeneratorJava:
+
+
+ + +FBE::Generator + +
+ + + + + + + + + + + + + + +

+Public Member Functions

bool Final () const noexcept
GeneratorJava & Final (bool final) noexcept
bool JSON () const noexcept
GeneratorJava & JSON (bool json) noexcept
bool Proto () const noexcept
GeneratorJava & Proto (bool proto) noexcept
int Version () const noexcept
GeneratorJava & Version (int v) noexcept
void Generate (const std::shared_ptr< Package > &package) override
 Generator (const std::string &input, const std::string &output, int indent, char space)
Public Member Functions inherited from FBE::Generator
 Generator (const std::string &input, const std::string &output, int indent, char space)
+ + + + + + + + + + + + + + + + + + + + + +

+Additional Inherited Members

Protected Member Functions inherited from FBE::Generator
void Indent (int count)
void WriteBegin ()
void Write (const std::string &str)
void WriteIndent ()
void WriteIndent (const std::string &str)
void WriteLine ()
void WriteLine (const std::string &str)
void WriteLineIndent (const std::string &str)
void WriteEnd ()
void Store (const CppCommon::Path &filename)
Static Protected Member Functions inherited from FBE::Generator
static std::string EndLine ()
Protected Attributes inherited from FBE::Generator
std::string _buffer
std::string _input
std::string _output
int _cursor {0}
int _indent
char _space
+

Detailed Description

+
+

Definition at line 16 of file generator_java.h.

+

Member Function Documentation

+ +

◆ Final() [1/2]

+ +
+
+ + + + + +
+ + + + + + + +
bool FBE::GeneratorJava::Final () const
+
+inlinenoexcept
+
+ +

Definition at line 22 of file generator_java.h.

+ +
+
+ +

◆ Final() [2/2]

+ +
+
+ + + + + +
+ + + + + + + +
GeneratorJava & FBE::GeneratorJava::Final (bool final)
+
+inlinenoexcept
+
+ +

Definition at line 23 of file generator_java.h.

+ +
+
+ +

◆ Generate()

+ +
+
+ + + + + +
+ + + + + + + +
void FBE::GeneratorJava::Generate (const std::shared_ptr< Package > & package)
+
+overridevirtual
+
+ +

Implements FBE::Generator.

+ +

Definition at line 13 of file generator_java.cpp.

+ +
+
+ +

◆ Generator()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
FBE::Generator::Generator (const std::string & input,
const std::string & output,
int indent,
char space )
+
+inline
+
+ +

Definition at line 19 of file generator.inl.

+ +
+
+ +

◆ JSON() [1/2]

+ +
+
+ + + + + +
+ + + + + + + +
bool FBE::GeneratorJava::JSON () const
+
+inlinenoexcept
+
+ +

Definition at line 26 of file generator_java.h.

+ +
+
+ +

◆ JSON() [2/2]

+ +
+
+ + + + + +
+ + + + + + + +
GeneratorJava & FBE::GeneratorJava::JSON (bool json)
+
+inlinenoexcept
+
+ +

Definition at line 27 of file generator_java.h.

+ +
+
+ +

◆ Proto() [1/2]

+ +
+
+ + + + + +
+ + + + + + + +
bool FBE::GeneratorJava::Proto () const
+
+inlinenoexcept
+
+ +

Definition at line 30 of file generator_java.h.

+ +
+
+ +

◆ Proto() [2/2]

+ +
+
+ + + + + +
+ + + + + + + +
GeneratorJava & FBE::GeneratorJava::Proto (bool proto)
+
+inlinenoexcept
+
+ +

Definition at line 31 of file generator_java.h.

+ +
+
+ +

◆ Version() [1/2]

+ +
+
+ + + + + +
+ + + + + + + +
int FBE::GeneratorJava::Version () const
+
+inlinenoexcept
+
+ +

Definition at line 34 of file generator_java.h.

+ +
+
+ +

◆ Version() [2/2]

+ +
+
+ + + + + +
+ + + + + + + +
GeneratorJava & FBE::GeneratorJava::Version (int v)
+
+inlinenoexcept
+
+ +

Definition at line 35 of file generator_java.h.

+ +
+
+
The documentation for this class was generated from the following files: +
+ + +
+ + diff --git a/documents/html/class_f_b_e_1_1_generator_java.png b/documents/html/class_f_b_e_1_1_generator_java.png new file mode 100644 index 0000000000000000000000000000000000000000..6dc8f901d152297d591f33792bf157f9c3bb0a67 GIT binary patch literal 530 zcmV+t0`2{YP)vTJr#LVva2S`&=-}Ys|Ns9r%~qrU000SeQchC<|NsC0|NsC0Hv*f~0004< zNklzYsp9{?cyqB0IG48Dt$0|fOl%18p+NhLT5AmyDoKVZ`N=2A zNoD)A)!6nqNj}rlpew#z*E~p?tGh|^R^Q>P)vB|sYOQA5>#cc7(&Gynhq literal 0 HcmV?d00001 diff --git a/documents/html/class_f_b_e_1_1_generator_java_script-members.html b/documents/html/class_f_b_e_1_1_generator_java_script-members.html new file mode 100644 index 000000000..f358bb2c1 --- /dev/null +++ b/documents/html/class_f_b_e_1_1_generator_java_script-members.html @@ -0,0 +1,117 @@ + + + + + + + +FastBinaryEncoding: Member List + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+
FBE::GeneratorJavaScript Member List
+
+
+ +

This is the complete list of members for FBE::GeneratorJavaScript, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
_bufferFBE::Generatorprotected
_cursorFBE::Generatorprotected
_indentFBE::Generatorprotected
_inputFBE::Generatorprotected
_outputFBE::Generatorprotected
_spaceFBE::Generatorprotected
EndLine()FBE::Generatorinlineprotectedstatic
Final() const noexceptFBE::GeneratorJavaScriptinline
Final(bool final) noexceptFBE::GeneratorJavaScriptinline
Generate(const std::shared_ptr< Package > &package) overrideFBE::GeneratorJavaScriptvirtual
Generator(const std::string &input, const std::string &output, int indent, char space)FBE::GeneratorJavaScriptinline
Indent(int count)FBE::Generatorinlineprotected
JSON() const noexceptFBE::GeneratorJavaScriptinline
JSON(bool json) noexceptFBE::GeneratorJavaScriptinline
Proto() const noexceptFBE::GeneratorJavaScriptinline
Proto(bool proto) noexceptFBE::GeneratorJavaScriptinline
Store(const CppCommon::Path &filename)FBE::Generatorprotected
Write(const std::string &str)FBE::Generatorinlineprotected
WriteBegin()FBE::Generatorinlineprotected
WriteEnd()FBE::Generatorinlineprotected
WriteIndent()FBE::Generatorinlineprotected
WriteIndent(const std::string &str)FBE::Generatorinlineprotected
WriteLine()FBE::Generatorinlineprotected
WriteLine(const std::string &str)FBE::Generatorinlineprotected
WriteLineIndent(const std::string &str)FBE::Generatorinlineprotected
+ + +
+ + diff --git a/documents/html/class_f_b_e_1_1_generator_java_script.html b/documents/html/class_f_b_e_1_1_generator_java_script.html new file mode 100644 index 000000000..bce7673b0 --- /dev/null +++ b/documents/html/class_f_b_e_1_1_generator_java_script.html @@ -0,0 +1,380 @@ + + + + + + + +FastBinaryEncoding: FBE::GeneratorJavaScript Class Reference + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+ +
FBE::GeneratorJavaScript Class Reference
+
+
+ +

#include <generator_javascript.h>

+
+Inheritance diagram for FBE::GeneratorJavaScript:
+
+
+ + +FBE::Generator + +
+ + + + + + + + + + + + +

+Public Member Functions

bool Final () const noexcept
GeneratorJavaScript & Final (bool final) noexcept
bool JSON () const noexcept
GeneratorJavaScript & JSON (bool json) noexcept
bool Proto () const noexcept
GeneratorJavaScript & Proto (bool proto) noexcept
void Generate (const std::shared_ptr< Package > &package) override
 Generator (const std::string &input, const std::string &output, int indent, char space)
Public Member Functions inherited from FBE::Generator
 Generator (const std::string &input, const std::string &output, int indent, char space)
+ + + + + + + + + + + + + + + + + + + + + +

+Additional Inherited Members

Protected Member Functions inherited from FBE::Generator
void Indent (int count)
void WriteBegin ()
void Write (const std::string &str)
void WriteIndent ()
void WriteIndent (const std::string &str)
void WriteLine ()
void WriteLine (const std::string &str)
void WriteLineIndent (const std::string &str)
void WriteEnd ()
void Store (const CppCommon::Path &filename)
Static Protected Member Functions inherited from FBE::Generator
static std::string EndLine ()
Protected Attributes inherited from FBE::Generator
std::string _buffer
std::string _input
std::string _output
int _cursor {0}
int _indent
char _space
+

Detailed Description

+
+

Definition at line 16 of file generator_javascript.h.

+

Member Function Documentation

+ +

◆ Final() [1/2]

+ +
+
+ + + + + +
+ + + + + + + +
bool FBE::GeneratorJavaScript::Final () const
+
+inlinenoexcept
+
+ +

Definition at line 22 of file generator_javascript.h.

+ +
+
+ +

◆ Final() [2/2]

+ +
+
+ + + + + +
+ + + + + + + +
GeneratorJavaScript & FBE::GeneratorJavaScript::Final (bool final)
+
+inlinenoexcept
+
+ +

Definition at line 23 of file generator_javascript.h.

+ +
+
+ +

◆ Generate()

+ +
+
+ + + + + +
+ + + + + + + +
void FBE::GeneratorJavaScript::Generate (const std::shared_ptr< Package > & package)
+
+overridevirtual
+
+ +

Implements FBE::Generator.

+ +

Definition at line 13 of file generator_javascript.cpp.

+ +
+
+ +

◆ Generator()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
FBE::Generator::Generator (const std::string & input,
const std::string & output,
int indent,
char space )
+
+inline
+
+ +

Definition at line 19 of file generator.inl.

+ +
+
+ +

◆ JSON() [1/2]

+ +
+
+ + + + + +
+ + + + + + + +
bool FBE::GeneratorJavaScript::JSON () const
+
+inlinenoexcept
+
+ +

Definition at line 26 of file generator_javascript.h.

+ +
+
+ +

◆ JSON() [2/2]

+ +
+
+ + + + + +
+ + + + + + + +
GeneratorJavaScript & FBE::GeneratorJavaScript::JSON (bool json)
+
+inlinenoexcept
+
+ +

Definition at line 27 of file generator_javascript.h.

+ +
+
+ +

◆ Proto() [1/2]

+ +
+
+ + + + + +
+ + + + + + + +
bool FBE::GeneratorJavaScript::Proto () const
+
+inlinenoexcept
+
+ +

Definition at line 30 of file generator_javascript.h.

+ +
+
+ +

◆ Proto() [2/2]

+ +
+
+ + + + + +
+ + + + + + + +
GeneratorJavaScript & FBE::GeneratorJavaScript::Proto (bool proto)
+
+inlinenoexcept
+
+ +

Definition at line 31 of file generator_javascript.h.

+ +
+
+
The documentation for this class was generated from the following files: +
+ + +
+ + diff --git a/documents/html/class_f_b_e_1_1_generator_java_script.png b/documents/html/class_f_b_e_1_1_generator_java_script.png new file mode 100644 index 0000000000000000000000000000000000000000..0f81fb600a59c9fe793816798a8272239e9d81ff GIT binary patch literal 639 zcmeAS@N?(olHy`uVBq!ia0vp^3xGI)gBeJ!Z0=(NQqloFA+G=b{|7Q(y!l$%e`vXd zfo6fk^fNCWJa_;UH$5A+1SrQ@666=m0OW&#In(Sb3=B+Mo-U3d6^w7^K0LQsfv1)K zc#7rs`lIvxTA0qAE&1v8sq7<9barJ!+3)Vu$Z0cMTUDNiGE7?H&gd~ou9joQy!kd# zx9!wVmjBY|NZD)0y5%vO*QJ>D*(&;9l@DY+{Tq8cD>rT5`uLmPldcyrz1yC;Z0@_x z>36Gbuc)t`u5$l{AMdy1(^r#BG!AF2nXaP$<*4#H+Yqx)79TIU*|X>P@3Q?N|L%e3 z(yto-c{i*+*j#Gtr8>)Q#eVy0m&-?0eujMvcb_E3s^D2A(xCD(5acfH2b*+GA7N@( z|B8{pIJ@k?@#LaIHyOkC?c`j}-lNCHFrP_)!G_C$;e!SPkjLBPT$2? zG553Fg2)^D_P>r;d-lxtuiDk0Pan_Tn_6V|c)sy$nfHv}Z_m=+y{dZt2D{9?YPSt! z7-PjISFbo&m$NgfCv91x>D=v4*PKgJKYpjYf5*3gn;yjxPftoFaGER>`(54Oyzbcq zwgZW)t)Fja@Yi~4>NV-g%Dm$Jdkp`D^3J-i7Tv6RF>6njyY$79jhz;8`nj{Um%Myr z6U#Q^>-;6!>lmgiiJm1FFli@Kz$9Q$cz()Y_0e3~`IZ0T_U4b5yXJTSlL~{UtDnm{ Hr-UW|!?_>M literal 0 HcmV?d00001 diff --git a/documents/html/class_f_b_e_1_1_generator_kotlin-members.html b/documents/html/class_f_b_e_1_1_generator_kotlin-members.html new file mode 100644 index 000000000..059800f8c --- /dev/null +++ b/documents/html/class_f_b_e_1_1_generator_kotlin-members.html @@ -0,0 +1,119 @@ + + + + + + + +FastBinaryEncoding: Member List + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+
FBE::GeneratorKotlin Member List
+
+
+ +

This is the complete list of members for FBE::GeneratorKotlin, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
_bufferFBE::Generatorprotected
_cursorFBE::Generatorprotected
_indentFBE::Generatorprotected
_inputFBE::Generatorprotected
_outputFBE::Generatorprotected
_spaceFBE::Generatorprotected
EndLine()FBE::Generatorinlineprotectedstatic
Final() const noexceptFBE::GeneratorKotlininline
Final(bool final) noexceptFBE::GeneratorKotlininline
Generate(const std::shared_ptr< Package > &package) overrideFBE::GeneratorKotlinvirtual
Generator(const std::string &input, const std::string &output, int indent, char space)FBE::GeneratorKotlininline
Indent(int count)FBE::Generatorinlineprotected
JSON() const noexceptFBE::GeneratorKotlininline
JSON(bool json) noexceptFBE::GeneratorKotlininline
Proto() const noexceptFBE::GeneratorKotlininline
Proto(bool proto) noexceptFBE::GeneratorKotlininline
Store(const CppCommon::Path &filename)FBE::Generatorprotected
Version() const noexceptFBE::GeneratorKotlininline
Version(int v) noexceptFBE::GeneratorKotlininline
Write(const std::string &str)FBE::Generatorinlineprotected
WriteBegin()FBE::Generatorinlineprotected
WriteEnd()FBE::Generatorinlineprotected
WriteIndent()FBE::Generatorinlineprotected
WriteIndent(const std::string &str)FBE::Generatorinlineprotected
WriteLine()FBE::Generatorinlineprotected
WriteLine(const std::string &str)FBE::Generatorinlineprotected
WriteLineIndent(const std::string &str)FBE::Generatorinlineprotected
+ + +
+ + diff --git a/documents/html/class_f_b_e_1_1_generator_kotlin.html b/documents/html/class_f_b_e_1_1_generator_kotlin.html new file mode 100644 index 000000000..9d6312515 --- /dev/null +++ b/documents/html/class_f_b_e_1_1_generator_kotlin.html @@ -0,0 +1,436 @@ + + + + + + + +FastBinaryEncoding: FBE::GeneratorKotlin Class Reference + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+ +
FBE::GeneratorKotlin Class Reference
+
+
+ +

#include <generator_kotlin.h>

+
+Inheritance diagram for FBE::GeneratorKotlin:
+
+
+ + +FBE::Generator + +
+ + + + + + + + + + + + + + +

+Public Member Functions

bool Final () const noexcept
GeneratorKotlin & Final (bool final) noexcept
bool JSON () const noexcept
GeneratorKotlin & JSON (bool json) noexcept
bool Proto () const noexcept
GeneratorKotlin & Proto (bool proto) noexcept
int Version () const noexcept
GeneratorKotlin & Version (int v) noexcept
void Generate (const std::shared_ptr< Package > &package) override
 Generator (const std::string &input, const std::string &output, int indent, char space)
Public Member Functions inherited from FBE::Generator
 Generator (const std::string &input, const std::string &output, int indent, char space)
+ + + + + + + + + + + + + + + + + + + + + +

+Additional Inherited Members

Protected Member Functions inherited from FBE::Generator
void Indent (int count)
void WriteBegin ()
void Write (const std::string &str)
void WriteIndent ()
void WriteIndent (const std::string &str)
void WriteLine ()
void WriteLine (const std::string &str)
void WriteLineIndent (const std::string &str)
void WriteEnd ()
void Store (const CppCommon::Path &filename)
Static Protected Member Functions inherited from FBE::Generator
static std::string EndLine ()
Protected Attributes inherited from FBE::Generator
std::string _buffer
std::string _input
std::string _output
int _cursor {0}
int _indent
char _space
+

Detailed Description

+
+

Definition at line 16 of file generator_kotlin.h.

+

Member Function Documentation

+ +

◆ Final() [1/2]

+ +
+
+ + + + + +
+ + + + + + + +
bool FBE::GeneratorKotlin::Final () const
+
+inlinenoexcept
+
+ +

Definition at line 22 of file generator_kotlin.h.

+ +
+
+ +

◆ Final() [2/2]

+ +
+
+ + + + + +
+ + + + + + + +
GeneratorKotlin & FBE::GeneratorKotlin::Final (bool final)
+
+inlinenoexcept
+
+ +

Definition at line 23 of file generator_kotlin.h.

+ +
+
+ +

◆ Generate()

+ +
+
+ + + + + +
+ + + + + + + +
void FBE::GeneratorKotlin::Generate (const std::shared_ptr< Package > & package)
+
+overridevirtual
+
+ +

Implements FBE::Generator.

+ +

Definition at line 13 of file generator_kotlin.cpp.

+ +
+
+ +

◆ Generator()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
FBE::Generator::Generator (const std::string & input,
const std::string & output,
int indent,
char space )
+
+inline
+
+ +

Definition at line 19 of file generator.inl.

+ +
+
+ +

◆ JSON() [1/2]

+ +
+
+ + + + + +
+ + + + + + + +
bool FBE::GeneratorKotlin::JSON () const
+
+inlinenoexcept
+
+ +

Definition at line 26 of file generator_kotlin.h.

+ +
+
+ +

◆ JSON() [2/2]

+ +
+
+ + + + + +
+ + + + + + + +
GeneratorKotlin & FBE::GeneratorKotlin::JSON (bool json)
+
+inlinenoexcept
+
+ +

Definition at line 27 of file generator_kotlin.h.

+ +
+
+ +

◆ Proto() [1/2]

+ +
+
+ + + + + +
+ + + + + + + +
bool FBE::GeneratorKotlin::Proto () const
+
+inlinenoexcept
+
+ +

Definition at line 30 of file generator_kotlin.h.

+ +
+
+ +

◆ Proto() [2/2]

+ +
+
+ + + + + +
+ + + + + + + +
GeneratorKotlin & FBE::GeneratorKotlin::Proto (bool proto)
+
+inlinenoexcept
+
+ +

Definition at line 31 of file generator_kotlin.h.

+ +
+
+ +

◆ Version() [1/2]

+ +
+
+ + + + + +
+ + + + + + + +
int FBE::GeneratorKotlin::Version () const
+
+inlinenoexcept
+
+ +

Definition at line 34 of file generator_kotlin.h.

+ +
+
+ +

◆ Version() [2/2]

+ +
+
+ + + + + +
+ + + + + + + +
GeneratorKotlin & FBE::GeneratorKotlin::Version (int v)
+
+inlinenoexcept
+
+ +

Definition at line 35 of file generator_kotlin.h.

+ +
+
+
The documentation for this class was generated from the following files: +
+ + +
+ + diff --git a/documents/html/class_f_b_e_1_1_generator_kotlin.png b/documents/html/class_f_b_e_1_1_generator_kotlin.png new file mode 100644 index 0000000000000000000000000000000000000000..b20befa34055ccaa6ff2bab28122b347312b9a74 GIT binary patch literal 538 zcmeAS@N?(olHy`uVBq!ia0vp^O+XyL!3-oHX~(_>QqloFA+G=b{|7Q(y!l$%e`vXd zfo6fk^fNCWJa_;UH$5A+1SrQ@666=m0OW&#In(Sb3=E7*JzX3_Dj46+&Fnv-z|r>6 zH1o&*{S~*fo?h5i{ASH$Ug4EZ?EMX&XBM5STo=IBFjI)5v7mjzxA?bH*F9%^;3pSR z(zW0>FKa_qyCj3&(`1fCS0&c&&6pi^{L{)XhJsHzPLkU;cm0=LFw6T|%CRWM1E*7U zf849u*4MMSFFcxY#y3BuB~j4^eS5Yv{bgpE%|Clyzgyyj!uM~)1!Ht&OlDuwatfWZ z=h~)2dpH=UcWw~cl`7I|D-LY-sN>y<7ZTel_1RA#ci77US8O}iWCw&7=itGUaI z^mr$Uls`vq9>_AcX?T#e&~=kYakZe@)vVS^L9^zkV$V6woGDfTxqctN;?gP0PVx6X X&HCxEW}-bX78yKU{an^LB{Ts5WRU7v literal 0 HcmV?d00001 diff --git a/documents/html/class_f_b_e_1_1_generator_python-members.html b/documents/html/class_f_b_e_1_1_generator_python-members.html new file mode 100644 index 000000000..e42f7c2df --- /dev/null +++ b/documents/html/class_f_b_e_1_1_generator_python-members.html @@ -0,0 +1,117 @@ + + + + + + + +FastBinaryEncoding: Member List + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+
FBE::GeneratorPython Member List
+
+
+ +

This is the complete list of members for FBE::GeneratorPython, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
_bufferFBE::Generatorprotected
_cursorFBE::Generatorprotected
_indentFBE::Generatorprotected
_inputFBE::Generatorprotected
_outputFBE::Generatorprotected
_spaceFBE::Generatorprotected
EndLine()FBE::Generatorinlineprotectedstatic
Final() const noexceptFBE::GeneratorPythoninline
Final(bool final) noexceptFBE::GeneratorPythoninline
Generate(const std::shared_ptr< Package > &package) overrideFBE::GeneratorPythonvirtual
Generator(const std::string &input, const std::string &output, int indent, char space)FBE::GeneratorPythoninline
Indent(int count)FBE::Generatorinlineprotected
JSON() const noexceptFBE::GeneratorPythoninline
JSON(bool json) noexceptFBE::GeneratorPythoninline
Proto() const noexceptFBE::GeneratorPythoninline
Proto(bool proto) noexceptFBE::GeneratorPythoninline
Store(const CppCommon::Path &filename)FBE::Generatorprotected
Write(const std::string &str)FBE::Generatorinlineprotected
WriteBegin()FBE::Generatorinlineprotected
WriteEnd()FBE::Generatorinlineprotected
WriteIndent()FBE::Generatorinlineprotected
WriteIndent(const std::string &str)FBE::Generatorinlineprotected
WriteLine()FBE::Generatorinlineprotected
WriteLine(const std::string &str)FBE::Generatorinlineprotected
WriteLineIndent(const std::string &str)FBE::Generatorinlineprotected
+ + +
+ + diff --git a/documents/html/class_f_b_e_1_1_generator_python.html b/documents/html/class_f_b_e_1_1_generator_python.html new file mode 100644 index 000000000..bd26e9384 --- /dev/null +++ b/documents/html/class_f_b_e_1_1_generator_python.html @@ -0,0 +1,380 @@ + + + + + + + +FastBinaryEncoding: FBE::GeneratorPython Class Reference + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+ +
FBE::GeneratorPython Class Reference
+
+
+ +

#include <generator_python.h>

+
+Inheritance diagram for FBE::GeneratorPython:
+
+
+ + +FBE::Generator + +
+ + + + + + + + + + + + +

+Public Member Functions

bool Final () const noexcept
GeneratorPython & Final (bool final) noexcept
bool JSON () const noexcept
GeneratorPython & JSON (bool json) noexcept
bool Proto () const noexcept
GeneratorPython & Proto (bool proto) noexcept
void Generate (const std::shared_ptr< Package > &package) override
 Generator (const std::string &input, const std::string &output, int indent, char space)
Public Member Functions inherited from FBE::Generator
 Generator (const std::string &input, const std::string &output, int indent, char space)
+ + + + + + + + + + + + + + + + + + + + + +

+Additional Inherited Members

Protected Member Functions inherited from FBE::Generator
void Indent (int count)
void WriteBegin ()
void Write (const std::string &str)
void WriteIndent ()
void WriteIndent (const std::string &str)
void WriteLine ()
void WriteLine (const std::string &str)
void WriteLineIndent (const std::string &str)
void WriteEnd ()
void Store (const CppCommon::Path &filename)
Static Protected Member Functions inherited from FBE::Generator
static std::string EndLine ()
Protected Attributes inherited from FBE::Generator
std::string _buffer
std::string _input
std::string _output
int _cursor {0}
int _indent
char _space
+

Detailed Description

+
+

Definition at line 16 of file generator_python.h.

+

Member Function Documentation

+ +

◆ Final() [1/2]

+ +
+
+ + + + + +
+ + + + + + + +
bool FBE::GeneratorPython::Final () const
+
+inlinenoexcept
+
+ +

Definition at line 22 of file generator_python.h.

+ +
+
+ +

◆ Final() [2/2]

+ +
+
+ + + + + +
+ + + + + + + +
GeneratorPython & FBE::GeneratorPython::Final (bool final)
+
+inlinenoexcept
+
+ +

Definition at line 23 of file generator_python.h.

+ +
+
+ +

◆ Generate()

+ +
+
+ + + + + +
+ + + + + + + +
void FBE::GeneratorPython::Generate (const std::shared_ptr< Package > & package)
+
+overridevirtual
+
+ +

Implements FBE::Generator.

+ +

Definition at line 13 of file generator_python.cpp.

+ +
+
+ +

◆ Generator()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
FBE::Generator::Generator (const std::string & input,
const std::string & output,
int indent,
char space )
+
+inline
+
+ +

Definition at line 19 of file generator.inl.

+ +
+
+ +

◆ JSON() [1/2]

+ +
+
+ + + + + +
+ + + + + + + +
bool FBE::GeneratorPython::JSON () const
+
+inlinenoexcept
+
+ +

Definition at line 26 of file generator_python.h.

+ +
+
+ +

◆ JSON() [2/2]

+ +
+
+ + + + + +
+ + + + + + + +
GeneratorPython & FBE::GeneratorPython::JSON (bool json)
+
+inlinenoexcept
+
+ +

Definition at line 27 of file generator_python.h.

+ +
+
+ +

◆ Proto() [1/2]

+ +
+
+ + + + + +
+ + + + + + + +
bool FBE::GeneratorPython::Proto () const
+
+inlinenoexcept
+
+ +

Definition at line 30 of file generator_python.h.

+ +
+
+ +

◆ Proto() [2/2]

+ +
+
+ + + + + +
+ + + + + + + +
GeneratorPython & FBE::GeneratorPython::Proto (bool proto)
+
+inlinenoexcept
+
+ +

Definition at line 31 of file generator_python.h.

+ +
+
+
The documentation for this class was generated from the following files: +
+ + +
+ + diff --git a/documents/html/class_f_b_e_1_1_generator_python.png b/documents/html/class_f_b_e_1_1_generator_python.png new file mode 100644 index 0000000000000000000000000000000000000000..22b1c34e9be11c520fefddb6d99352abb1c07ff1 GIT binary patch literal 593 zcmeAS@N?(olHy`uVBq!ia0vp^T|gYb!3-on{*jdjQqloFA+G=b{|7Q(y!l$%e`vXd zfo6fk^fNCWJa_;UH$5A+1SrQ@666=m0OW&#In(Sb3=E8SJY5_^Dj46+y_k1cfyY%} zeC4PA^&clqVA$vAyM3AHEStAeZZOtJ&3P+o`P_#6go-8eLZ?YyD<&-Yeq)Y&#gB5CLa37@@MkzQ^ArYEn@xc`RjKVT*?ib2lH;=roUyc z7wKNtwOter^mM4^>Fr;)I`Hm3S-b7@+-cV=Z)saqF~?sJwXHOt`}p?h*qaZxvtQY@ zt8RH%Mt)A{N8h5=UH0nrIg6KHD%;_idO>jUBJ#tn9J!`*d-F5rCw(905w)gh+ z##;p$8voXqUb=5tQS7s5E&Y(r|7U=XT`^;(X7S1;Q!a`8VUYb?IGdGeNhdJ!89ZJ6 KT-G@yGywqoRS^~d literal 0 HcmV?d00001 diff --git a/documents/html/class_f_b_e_1_1_generator_ruby-members.html b/documents/html/class_f_b_e_1_1_generator_ruby-members.html new file mode 100644 index 000000000..bcf706a19 --- /dev/null +++ b/documents/html/class_f_b_e_1_1_generator_ruby-members.html @@ -0,0 +1,117 @@ + + + + + + + +FastBinaryEncoding: Member List + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+
FBE::GeneratorRuby Member List
+
+
+ +

This is the complete list of members for FBE::GeneratorRuby, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
_bufferFBE::Generatorprotected
_cursorFBE::Generatorprotected
_indentFBE::Generatorprotected
_inputFBE::Generatorprotected
_outputFBE::Generatorprotected
_spaceFBE::Generatorprotected
EndLine()FBE::Generatorinlineprotectedstatic
Final() const noexceptFBE::GeneratorRubyinline
Final(bool final) noexceptFBE::GeneratorRubyinline
Generate(const std::shared_ptr< Package > &package) overrideFBE::GeneratorRubyvirtual
Generator(const std::string &input, const std::string &output, int indent, char space)FBE::GeneratorRubyinline
Indent(int count)FBE::Generatorinlineprotected
JSON() const noexceptFBE::GeneratorRubyinline
JSON(bool json) noexceptFBE::GeneratorRubyinline
Proto() const noexceptFBE::GeneratorRubyinline
Proto(bool proto) noexceptFBE::GeneratorRubyinline
Store(const CppCommon::Path &filename)FBE::Generatorprotected
Write(const std::string &str)FBE::Generatorinlineprotected
WriteBegin()FBE::Generatorinlineprotected
WriteEnd()FBE::Generatorinlineprotected
WriteIndent()FBE::Generatorinlineprotected
WriteIndent(const std::string &str)FBE::Generatorinlineprotected
WriteLine()FBE::Generatorinlineprotected
WriteLine(const std::string &str)FBE::Generatorinlineprotected
WriteLineIndent(const std::string &str)FBE::Generatorinlineprotected
+ + +
+ + diff --git a/documents/html/class_f_b_e_1_1_generator_ruby.html b/documents/html/class_f_b_e_1_1_generator_ruby.html new file mode 100644 index 000000000..f3e7883c4 --- /dev/null +++ b/documents/html/class_f_b_e_1_1_generator_ruby.html @@ -0,0 +1,380 @@ + + + + + + + +FastBinaryEncoding: FBE::GeneratorRuby Class Reference + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+ +
FBE::GeneratorRuby Class Reference
+
+
+ +

#include <generator_ruby.h>

+
+Inheritance diagram for FBE::GeneratorRuby:
+
+
+ + +FBE::Generator + +
+ + + + + + + + + + + + +

+Public Member Functions

bool Final () const noexcept
GeneratorRuby & Final (bool final) noexcept
bool JSON () const noexcept
GeneratorRuby & JSON (bool json) noexcept
bool Proto () const noexcept
GeneratorRuby & Proto (bool proto) noexcept
void Generate (const std::shared_ptr< Package > &package) override
 Generator (const std::string &input, const std::string &output, int indent, char space)
Public Member Functions inherited from FBE::Generator
 Generator (const std::string &input, const std::string &output, int indent, char space)
+ + + + + + + + + + + + + + + + + + + + + +

+Additional Inherited Members

Protected Member Functions inherited from FBE::Generator
void Indent (int count)
void WriteBegin ()
void Write (const std::string &str)
void WriteIndent ()
void WriteIndent (const std::string &str)
void WriteLine ()
void WriteLine (const std::string &str)
void WriteLineIndent (const std::string &str)
void WriteEnd ()
void Store (const CppCommon::Path &filename)
Static Protected Member Functions inherited from FBE::Generator
static std::string EndLine ()
Protected Attributes inherited from FBE::Generator
std::string _buffer
std::string _input
std::string _output
int _cursor {0}
int _indent
char _space
+

Detailed Description

+
+

Definition at line 16 of file generator_ruby.h.

+

Member Function Documentation

+ +

◆ Final() [1/2]

+ +
+
+ + + + + +
+ + + + + + + +
bool FBE::GeneratorRuby::Final () const
+
+inlinenoexcept
+
+ +

Definition at line 22 of file generator_ruby.h.

+ +
+
+ +

◆ Final() [2/2]

+ +
+
+ + + + + +
+ + + + + + + +
GeneratorRuby & FBE::GeneratorRuby::Final (bool final)
+
+inlinenoexcept
+
+ +

Definition at line 23 of file generator_ruby.h.

+ +
+
+ +

◆ Generate()

+ +
+
+ + + + + +
+ + + + + + + +
void FBE::GeneratorRuby::Generate (const std::shared_ptr< Package > & package)
+
+overridevirtual
+
+ +

Implements FBE::Generator.

+ +

Definition at line 13 of file generator_ruby.cpp.

+ +
+
+ +

◆ Generator()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
FBE::Generator::Generator (const std::string & input,
const std::string & output,
int indent,
char space )
+
+inline
+
+ +

Definition at line 19 of file generator.inl.

+ +
+
+ +

◆ JSON() [1/2]

+ +
+
+ + + + + +
+ + + + + + + +
bool FBE::GeneratorRuby::JSON () const
+
+inlinenoexcept
+
+ +

Definition at line 26 of file generator_ruby.h.

+ +
+
+ +

◆ JSON() [2/2]

+ +
+
+ + + + + +
+ + + + + + + +
GeneratorRuby & FBE::GeneratorRuby::JSON (bool json)
+
+inlinenoexcept
+
+ +

Definition at line 27 of file generator_ruby.h.

+ +
+
+ +

◆ Proto() [1/2]

+ +
+
+ + + + + +
+ + + + + + + +
bool FBE::GeneratorRuby::Proto () const
+
+inlinenoexcept
+
+ +

Definition at line 30 of file generator_ruby.h.

+ +
+
+ +

◆ Proto() [2/2]

+ +
+
+ + + + + +
+ + + + + + + +
GeneratorRuby & FBE::GeneratorRuby::Proto (bool proto)
+
+inlinenoexcept
+
+ +

Definition at line 31 of file generator_ruby.h.

+ +
+
+
The documentation for this class was generated from the following files: +
+ + +
+ + diff --git a/documents/html/class_f_b_e_1_1_generator_ruby.png b/documents/html/class_f_b_e_1_1_generator_ruby.png new file mode 100644 index 0000000000000000000000000000000000000000..7893ced5e3dc009ade18766a4996fe8e68d1a9dc GIT binary patch literal 534 zcmeAS@N?(olHy`uVBq!ia0vp^4L}^g!3-py-Rr#uq@)9ULR|m<{|{uoc=NTi|Il&^ z1I+@7>1SR%c<=xyZhAIs2~du+B*-tA0mugfbEer>7#J8Adb&7@^;J}~#4 z`dr40-Hi+Z{@lz5mc}s&te*(z}R@3^WSQ%EgGuXVbF8pR&%UitniL^9pgJZa@ zLDcN)%M4fYZL#8Vu#cbOP_;$gWwl5Cyn0%MTD)78&qol`;+ E03#0M<^TWy literal 0 HcmV?d00001 diff --git a/documents/html/class_f_b_e_1_1_generator_swift-members.html b/documents/html/class_f_b_e_1_1_generator_swift-members.html new file mode 100644 index 000000000..920de1a2f --- /dev/null +++ b/documents/html/class_f_b_e_1_1_generator_swift-members.html @@ -0,0 +1,117 @@ + + + + + + + +FastBinaryEncoding: Member List + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+
FBE::GeneratorSwift Member List
+
+
+ +

This is the complete list of members for FBE::GeneratorSwift, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
_bufferFBE::Generatorprotected
_cursorFBE::Generatorprotected
_indentFBE::Generatorprotected
_inputFBE::Generatorprotected
_outputFBE::Generatorprotected
_spaceFBE::Generatorprotected
EndLine()FBE::Generatorinlineprotectedstatic
Final() const noexceptFBE::GeneratorSwiftinline
Final(bool final) noexceptFBE::GeneratorSwiftinline
Generate(const std::shared_ptr< Package > &package) overrideFBE::GeneratorSwiftvirtual
Generator(const std::string &input, const std::string &output, int indent, char space)FBE::GeneratorSwiftinline
Indent(int count)FBE::Generatorinlineprotected
JSON() const noexceptFBE::GeneratorSwiftinline
JSON(bool json) noexceptFBE::GeneratorSwiftinline
Proto() const noexceptFBE::GeneratorSwiftinline
Proto(bool proto) noexceptFBE::GeneratorSwiftinline
Store(const CppCommon::Path &filename)FBE::Generatorprotected
Write(const std::string &str)FBE::Generatorinlineprotected
WriteBegin()FBE::Generatorinlineprotected
WriteEnd()FBE::Generatorinlineprotected
WriteIndent()FBE::Generatorinlineprotected
WriteIndent(const std::string &str)FBE::Generatorinlineprotected
WriteLine()FBE::Generatorinlineprotected
WriteLine(const std::string &str)FBE::Generatorinlineprotected
WriteLineIndent(const std::string &str)FBE::Generatorinlineprotected
+ + +
+ + diff --git a/documents/html/class_f_b_e_1_1_generator_swift.html b/documents/html/class_f_b_e_1_1_generator_swift.html new file mode 100644 index 000000000..dba3810e5 --- /dev/null +++ b/documents/html/class_f_b_e_1_1_generator_swift.html @@ -0,0 +1,380 @@ + + + + + + + +FastBinaryEncoding: FBE::GeneratorSwift Class Reference + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+ +
FBE::GeneratorSwift Class Reference
+
+
+ +

#include <generator_swift.h>

+
+Inheritance diagram for FBE::GeneratorSwift:
+
+
+ + +FBE::Generator + +
+ + + + + + + + + + + + +

+Public Member Functions

bool Final () const noexcept
GeneratorSwift & Final (bool final) noexcept
bool JSON () const noexcept
GeneratorSwift & JSON (bool json) noexcept
bool Proto () const noexcept
GeneratorSwift & Proto (bool proto) noexcept
void Generate (const std::shared_ptr< Package > &package) override
 Generator (const std::string &input, const std::string &output, int indent, char space)
Public Member Functions inherited from FBE::Generator
 Generator (const std::string &input, const std::string &output, int indent, char space)
+ + + + + + + + + + + + + + + + + + + + + +

+Additional Inherited Members

Protected Member Functions inherited from FBE::Generator
void Indent (int count)
void WriteBegin ()
void Write (const std::string &str)
void WriteIndent ()
void WriteIndent (const std::string &str)
void WriteLine ()
void WriteLine (const std::string &str)
void WriteLineIndent (const std::string &str)
void WriteEnd ()
void Store (const CppCommon::Path &filename)
Static Protected Member Functions inherited from FBE::Generator
static std::string EndLine ()
Protected Attributes inherited from FBE::Generator
std::string _buffer
std::string _input
std::string _output
int _cursor {0}
int _indent
char _space
+

Detailed Description

+
+

Definition at line 18 of file generator_swift.h.

+

Member Function Documentation

+ +

◆ Final() [1/2]

+ +
+
+ + + + + +
+ + + + + + + +
bool FBE::GeneratorSwift::Final () const
+
+inlinenoexcept
+
+ +

Definition at line 24 of file generator_swift.h.

+ +
+
+ +

◆ Final() [2/2]

+ +
+
+ + + + + +
+ + + + + + + +
GeneratorSwift & FBE::GeneratorSwift::Final (bool final)
+
+inlinenoexcept
+
+ +

Definition at line 25 of file generator_swift.h.

+ +
+
+ +

◆ Generate()

+ +
+
+ + + + + +
+ + + + + + + +
void FBE::GeneratorSwift::Generate (const std::shared_ptr< Package > & package)
+
+overridevirtual
+
+ +

Implements FBE::Generator.

+ +

Definition at line 16 of file generator_swift.cpp.

+ +
+
+ +

◆ Generator()

+ +
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
FBE::Generator::Generator (const std::string & input,
const std::string & output,
int indent,
char space )
+
+inline
+
+ +

Definition at line 19 of file generator.inl.

+ +
+
+ +

◆ JSON() [1/2]

+ +
+
+ + + + + +
+ + + + + + + +
bool FBE::GeneratorSwift::JSON () const
+
+inlinenoexcept
+
+ +

Definition at line 28 of file generator_swift.h.

+ +
+
+ +

◆ JSON() [2/2]

+ +
+
+ + + + + +
+ + + + + + + +
GeneratorSwift & FBE::GeneratorSwift::JSON (bool json)
+
+inlinenoexcept
+
+ +

Definition at line 29 of file generator_swift.h.

+ +
+
+ +

◆ Proto() [1/2]

+ +
+
+ + + + + +
+ + + + + + + +
bool FBE::GeneratorSwift::Proto () const
+
+inlinenoexcept
+
+ +

Definition at line 32 of file generator_swift.h.

+ +
+
+ +

◆ Proto() [2/2]

+ +
+
+ + + + + +
+ + + + + + + +
GeneratorSwift & FBE::GeneratorSwift::Proto (bool proto)
+
+inlinenoexcept
+
+ +

Definition at line 33 of file generator_swift.h.

+ +
+
+
The documentation for this class was generated from the following files: +
+ + +
+ + diff --git a/documents/html/class_f_b_e_1_1_generator_swift.png b/documents/html/class_f_b_e_1_1_generator_swift.png new file mode 100644 index 0000000000000000000000000000000000000000..ad371c379efcf25eccd0db238ee9789d1c6ded18 GIT binary patch literal 554 zcmV+_0@eMAP)vTJr#LVva2S`&=-}Ys|Ns9r%~qrU000SeQchC<|NsC0|NsC0Hv*f~0005C zNkl#pM<41|Y4s^-O#42C zy~As|bZXr3S(5a6())SzR1a~WL#;MT(p=XMe>k%rLhD60=ZEpW2figAd;60P&!B&V zpL*Xa*@Er>Fe=1=Nu*g_#52-AWpIP+bxtIi@(z& z`N8-vcmBcyK$I390D`pe01%{w2Y?_gJOBh~;Q=5>3l9K6T6h4ss+3ZS6OtrFY2hU) zNWTSNj95n#_k}K!q;t)S=I6@ZZP~!v$G0*hnX9EG>8aj$Zm-}+_z~5!+1{W>TUh7g zt7OgY^|}3SJCc|9GVS=f&kixWj`@^rWg7hX+uNQWdS5dZ;y{O5Ey5M{2>-_64`=p6 zXuaqrJ1I&@^K}{TdoY>lh#%WkCtSjxbodPP7(Xp}jGubnD%t&NoNxT#RygOI-~EiA soG(fLUkfiuL0Wi83Q{~irIf<-2hMe8p+ablmjD0&07*qoM6N<$f^`24kpKVy literal 0 HcmV?d00001 diff --git a/documents/html/classes.html b/documents/html/classes.html new file mode 100644 index 000000000..fceac5038 --- /dev/null +++ b/documents/html/classes.html @@ -0,0 +1,112 @@ + + + + + + + +FastBinaryEncoding: Class Index + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + +
+
+ +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
Class Index
+
+ + + +
+ + diff --git a/documents/html/clipboard.js b/documents/html/clipboard.js new file mode 100644 index 000000000..9da9f3ca4 --- /dev/null +++ b/documents/html/clipboard.js @@ -0,0 +1,61 @@ +/** + +The code below is based on the Doxygen Awesome project, see +https://github.com/jothepro/doxygen-awesome-css + +MIT License + +Copyright (c) 2021 - 2022 jothepro + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +*/ + +let clipboard_title = "Copy to clipboard" +let clipboard_icon = `` +let clipboard_successIcon = `` +let clipboard_successDuration = 1000 + +$(function() { + if(navigator.clipboard) { + const fragments = document.getElementsByClassName("fragment") + for(const fragment of fragments) { + const clipboard_div = document.createElement("div") + clipboard_div.classList.add("clipboard") + clipboard_div.innerHTML = clipboard_icon + clipboard_div.title = clipboard_title + $(clipboard_div).click(function() { + const content = this.parentNode.cloneNode(true) + // filter out line number and folded fragments from file listings + content.querySelectorAll(".lineno, .ttc, .foldclosed").forEach((node) => { node.remove() }) + let text = content.textContent + // remove trailing newlines and trailing spaces from empty lines + text = text.replace(/^\s*\n/gm,'\n').replace(/\n*$/,'') + navigator.clipboard.writeText(text); + this.classList.add("success") + this.innerHTML = clipboard_successIcon + window.setTimeout(() => { // switch back to normal icon after timeout + this.classList.remove("success") + this.innerHTML = clipboard_icon + }, clipboard_successDuration); + }) + fragment.insertBefore(clipboard_div, fragment.firstChild) + } + } +}) diff --git a/documents/html/cookie.js b/documents/html/cookie.js new file mode 100644 index 000000000..53ad21d98 --- /dev/null +++ b/documents/html/cookie.js @@ -0,0 +1,58 @@ +/*! + Cookie helper functions + Copyright (c) 2023 Dimitri van Heesch + Released under MIT license. +*/ +let Cookie = { + cookie_namespace: 'doxygen_', + + readSetting(cookie,defVal) { + if (window.chrome) { + const val = localStorage.getItem(this.cookie_namespace+cookie) || + sessionStorage.getItem(this.cookie_namespace+cookie); + if (val) return val; + } else { + let myCookie = this.cookie_namespace+cookie+"="; + if (document.cookie) { + const index = document.cookie.indexOf(myCookie); + if (index != -1) { + const valStart = index + myCookie.length; + let valEnd = document.cookie.indexOf(";", valStart); + if (valEnd == -1) { + valEnd = document.cookie.length; + } + return document.cookie.substring(valStart, valEnd); + } + } + } + return defVal; + }, + + writeSetting(cookie,val,days=10*365) { // default days='forever', 0=session cookie, -1=delete + if (window.chrome) { + if (days==0) { + sessionStorage.setItem(this.cookie_namespace+cookie,val); + } else { + localStorage.setItem(this.cookie_namespace+cookie,val); + } + } else { + let date = new Date(); + date.setTime(date.getTime()+(days*24*60*60*1000)); + const expiration = days!=0 ? "expires="+date.toGMTString()+";" : ""; + document.cookie = this.cookie_namespace + cookie + "=" + + val + "; SameSite=Lax;" + expiration + "path=/"; + } + }, + + eraseSetting(cookie) { + if (window.chrome) { + if (localStorage.getItem(this.cookie_namespace+cookie)) { + localStorage.removeItem(this.cookie_namespace+cookie); + } else if (sessionStorage.getItem(this.cookie_namespace+cookie)) { + sessionStorage.removeItem(this.cookie_namespace+cookie); + } + } else { + this.writeSetting(cookie,'',-1); + } + }, +} diff --git a/documents/html/dir_b2f33c71d4aa5e7af42a1ca61ff5af1b.html b/documents/html/dir_b2f33c71d4aa5e7af42a1ca61ff5af1b.html new file mode 100644 index 000000000..ac600b7bf --- /dev/null +++ b/documents/html/dir_b2f33c71d4aa5e7af42a1ca61ff5af1b.html @@ -0,0 +1,116 @@ + + + + + + + +FastBinaryEncoding: source Directory Reference + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+
source Directory Reference
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +

+Files

 
fbe.cpp
 Fast binary encoding implementation.
 
fbe.l
 
generator.cpp
 Fast binary encoding generator implementation.
 
generator_cpp.cpp
 Fast binary encoding C++ generator implementation.
 
generator_csharp.cpp
 Fast binary encoding C# generator implementation.
 
generator_go.cpp
 Fast binary encoding Go generator implementation.
 
generator_java.cpp
 Fast binary encoding Java generator implementation.
 
generator_javascript.cpp
 Fast binary encoding JavaScript generator implementation.
 
generator_kotlin.cpp
 Fast binary encoding Kotlin generator implementation.
 
generator_python.cpp
 Fast binary encoding Python generator implementation.
 
generator_ruby.cpp
 Fast binary encoding Ruby generator implementation.
 
generator_swift.cpp
 Fast binary encoding Swift generator implementation.
+
+ + +
+ + diff --git a/documents/html/dir_d44c64559bbebec7f509842c48db8b23.html b/documents/html/dir_d44c64559bbebec7f509842c48db8b23.html new file mode 100644 index 000000000..e7032a33c --- /dev/null +++ b/documents/html/dir_d44c64559bbebec7f509842c48db8b23.html @@ -0,0 +1,119 @@ + + + + + + + +FastBinaryEncoding: include Directory Reference + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+
include Directory Reference
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Files

 
fbe.h
 Fast binary encoding definitions.
 
generator.h
 Fast binary encoding generator definition.
 
generator.inl
 Fast binary encoding generator inline implementation.
 
generator_cpp.h
 Fast binary encoding C++ generator definition.
 
generator_csharp.h
 Fast binary encoding C# generator definition.
 
generator_go.h
 Fast binary encoding Go generator definition.
 
generator_java.h
 Fast binary encoding Java generator definition.
 
generator_javascript.h
 Fast binary encoding JavaScript generator definition.
 
generator_kotlin.h
 Fast binary encoding Kotlin generator definition.
 
generator_python.h
 Fast binary encoding Python generator definition.
 
generator_ruby.h
 Fast binary encoding Ruby generator definition.
 
generator_swift.h
 Fast binary encoding Kotlin generator definition.
 
version.h
 Version definition.
+
+ + +
+ + diff --git a/documents/html/doxygen.css b/documents/html/doxygen.css new file mode 100644 index 000000000..788923ab6 --- /dev/null +++ b/documents/html/doxygen.css @@ -0,0 +1,2540 @@ +/* The standard CSS for doxygen 1.16.1*/ + +html { +/* page base colors */ +--page-background-color: white; +--page-foreground-color: black; +--page-link-color: #3D578C; +--page-visited-link-color: #3D578C; +--page-external-link-color: #334975; + +/* index */ +--index-odd-item-bg-color: #F8F9FC; +--index-even-item-bg-color: white; +--index-header-color: black; +--index-separator-color: #A0A0A0; + +/* header */ +--header-background-color: #F9FAFC; +--header-separator-color: #C4CFE5; +--group-header-separator-color: #D9E0EE; +--group-header-color: #354C7B; + +--footer-foreground-color: #2A3D61; +--footer-logo-width: 75px; +--citation-label-color: #334975; +--glow-color: cyan; + +--title-background-color: white; +--title-separator-color: #C4CFE5; + +--blockquote-background-color: #F7F8FB; +--blockquote-border-color: #9CAFD4; + +--scrollbar-thumb-color: #C4CFE5; +--scrollbar-background-color: #F9FAFC; + +--icon-background-color: #728DC1; +--icon-foreground-color: white; +--icon-folder-open-fill-color: #C4CFE5; +--icon-folder-fill-color: #D8DFEE; +--icon-folder-border-color: #4665A2; +--icon-doc-fill-color: #D8DFEE; +--icon-doc-border-color: #4665A2; + +/* brief member declaration list */ +--memdecl-background-color: #F9FAFC; +--memdecl-foreground-color: #555; +--memdecl-template-color: #4665A2; +--memdecl-border-color: #D5DDEC; + +/* detailed member list */ +--memdef-border-color: #A8B8D9; +--memdef-title-background-color: #E2E8F2; +--memdef-proto-background-color: #EEF1F7; +--memdef-proto-text-color: #253555; +--memdef-param-name-color: #602020; +--memdef-template-color: #4665A2; + +/* tables */ +--table-cell-border-color: #2D4068; +--table-header-background-color: #374F7F; +--table-header-foreground-color: #FFFFFF; + +/* labels */ +--label-background-color: #728DC1; +--label-left-top-border-color: #5373B4; +--label-right-bottom-border-color: #C4CFE5; +--label-foreground-color: white; + +/** navigation bar/tree/menu */ +--nav-background-color: #F9FAFC; +--nav-foreground-color: #364D7C; +--nav-border-color: #C4CFE5; +--nav-breadcrumb-separator-color: #C4CFE5; +--nav-breadcrumb-active-bg: #EEF1F7; +--nav-breadcrumb-color: #354C7B; +--nav-splitbar-bg-color: #DCE2EF; +--nav-splitbar-handle-color: #9CAFD4; +--nav-font-size-level1: 13px; +--nav-font-size-level2: 10px; +--nav-font-size-level3: 9px; +--nav-text-normal-color: #283A5D; +--nav-menu-button-color: #364D7C; +--nav-menu-background-color: white; +--nav-menu-foreground-color: #555555; +--nav-menu-active-bg: #DCE2EF; +--nav-menu-active-color: #9CAFD4; +--nav-arrow-color: #B6C4DF; +--nav-arrow-selected-color: #90A5CE; + +/* sync icon */ +--sync-icon-border-color: #C4CFE5; +--sync-icon-background-color: #F9FAFC; +--sync-icon-selected-background-color: #EEF1F7; +--sync-icon-color: #C4CFE5; +--sync-icon-selected-color: #6884BD; + +/* table of contents */ +--toc-background-color: #F4F6FA; +--toc-border-color: #D8DFEE; +--toc-header-color: #4665A2; +--toc-down-arrow-image: url("data:image/svg+xml;utf8,&%238595;"); + +/** search field */ +--search-background-color: white; +--search-foreground-color: #909090; +--search-active-color: black; +--search-filter-background-color: rgba(255,255,255,.7); +--search-filter-backdrop-filter: blur(4px); +--search-filter-foreground-color: black; +--search-filter-border-color: rgba(150,150,150,.4); +--search-filter-highlight-text-color: white; +--search-filter-highlight-bg-color: #3D578C; +--search-results-foreground-color: #425E97; +--search-results-background-color: rgba(255,255,255,.8); +--search-results-backdrop-filter: blur(4px); +--search-results-border-color: rgba(150,150,150,.4); +--search-box-border-color: #B6C4DF; +--search-close-icon-bg-color: #A0A0A0; +--search-close-icon-fg-color: white; + +/** code fragments */ +--code-keyword-color: #008000; +--code-type-keyword-color: #604020; +--code-flow-keyword-color: #E08000; +--code-comment-color: #800000; +--code-preprocessor-color: #806020; +--code-string-literal-color: #002080; +--code-char-literal-color: #008080; +--code-xml-cdata-color: black; +--code-vhdl-digit-color: #FF00FF; +--code-vhdl-char-color: #000000; +--code-vhdl-keyword-color: #700070; +--code-vhdl-logic-color: #FF0000; +--fragment-foreground-color: black; +--fragment-background-color: #FBFCFD; +--fragment-border-color: #C4CFE5; +--fragment-lineno-border-color: #00FF00; +--fragment-lineno-background-color: #E8E8E8; +--fragment-lineno-foreground-color: black; +--fragment-lineno-link-fg-color: #4665A2; +--fragment-lineno-link-bg-color: #D8D8D8; +--fragment-lineno-link-hover-fg-color: #4665A2; +--fragment-lineno-link-hover-bg-color: #C8C8C8; +--fragment-copy-ok-color: #2EC82E; +--fragment-highlight-filter: -3; +--tooltip-foreground-color: black; +--tooltip-background-color: rgba(255,255,255,0.8); +--tooltip-arrow-background-color: white; +--tooltip-border-color: rgba(150,150,150,0.7); +--tooltip-backdrop-filter: blur(3px); +--tooltip-doc-color: grey; +--tooltip-declaration-color: #006318; +--tooltip-link-color: #4665A2; +--tooltip-shadow: 0 4px 8px 0 rgba(0,0,0,.25); +--fold-line-color: #808080; + +/** font-family */ +--font-family-normal: system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans,sans-serif,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol"; +--font-family-monospace: 'JetBrains Mono',Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace,fixed; +--font-family-nav: 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; +--font-family-title: system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans,sans-serif,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol"; +--font-family-toc: Verdana,'DejaVu Sans',Geneva,sans-serif; +--font-family-search: Arial,Verdana,sans-serif; +--font-family-icon: Arial,Helvetica; +--font-family-tooltip: Roboto,sans-serif; + +/** special sections */ +--warning-color-bg: #f8d1cc; +--warning-color-hl: #b61825; +--warning-color-text: #75070f; +--note-color-bg: #faf3d8; +--note-color-hl: #f3a600; +--note-color-text: #5f4204; +--todo-color-bg: #e4f3ff; +--todo-color-hl: #1879C4; +--todo-color-text: #274a5c; +--test-color-bg: #e8e8ff; +--test-color-hl: #3939C4; +--test-color-text: #1a1a5c; +--deprecated-color-bg: #ecf0f3; +--deprecated-color-hl: #5b6269; +--deprecated-color-text: #43454a; +--bug-color-bg: #e4dafd; +--bug-color-hl: #5b2bdd; +--bug-color-text: #2a0d72; +--invariant-color-bg: #d8f1e3; +--invariant-color-hl: #44b86f; +--invariant-color-text: #265532; +--satisfies-color-hl: #b61825; +--satisfies-color-bg: #f8d1cc; +--verifies-color-hl: #b61825; +--verifies-color-bg: #f8d1cc; + +} + +@media (prefers-color-scheme: dark) { + html:not(.dark-mode) { + color-scheme: dark; + +/* page base colors */ +--page-background-color: black; +--page-foreground-color: #C9D1D9; +--page-link-color: #90A5CE; +--page-visited-link-color: #90A5CE; +--page-external-link-color: #A3B4D7; + +/* index */ +--index-odd-item-bg-color: #0B101A; +--index-even-item-bg-color: black; +--index-header-color: #C4CFE5; +--index-separator-color: #334975; + +/* header */ +--header-background-color: #070B11; +--header-separator-color: #141C2E; +--group-header-separator-color: #1D2A43; +--group-header-color: #90A5CE; + +--footer-foreground-color: #5B7AB7; +--footer-logo-width: 60px; +--citation-label-color: #90A5CE; +--glow-color: cyan; + +--title-background-color: #090D16; +--title-separator-color: #212F4B; + +--blockquote-background-color: #101826; +--blockquote-border-color: #283A5D; + +--scrollbar-thumb-color: #2C3F65; +--scrollbar-background-color: #070B11; + +--icon-background-color: #334975; +--icon-foreground-color: #C4CFE5; +--icon-folder-open-fill-color: #4665A2; +--icon-folder-fill-color: #5373B4; +--icon-folder-border-color: #C4CFE5; +--icon-doc-fill-color: #6884BD; +--icon-doc-border-color: #C4CFE5; + +/* brief member declaration list */ +--memdecl-background-color: #0B101A; +--memdecl-foreground-color: #BBB; +--memdecl-template-color: #7C95C6; +--memdecl-border-color: #233250; + +/* detailed member list */ +--memdef-border-color: #233250; +--memdef-title-background-color: #1B2840; +--memdef-proto-background-color: #19243A; +--memdef-proto-text-color: #9DB0D4; +--memdef-param-name-color: #D28757; +--memdef-template-color: #7C95C6; + +/* tables */ +--table-cell-border-color: #283A5D; +--table-header-background-color: #283A5D; +--table-header-foreground-color: #C4CFE5; + +/* labels */ +--label-background-color: #354C7B; +--label-left-top-border-color: #4665A2; +--label-right-bottom-border-color: #283A5D; +--label-foreground-color: #CCCCCC; + +/** navigation bar/tree/menu */ +--nav-background-color: #101826; +--nav-foreground-color: #364D7C; +--nav-border-color: #212F4B; +--nav-breadcrumb-separator-color: #212F4B; +--nav-breadcrumb-active-bg: #1D2A43; +--nav-breadcrumb-color: #90A5CE; +--nav-splitbar-bg-color: #283A5D; +--nav-splitbar-handle-color: #4665A2; +--nav-font-size-level1: 13px; +--nav-font-size-level2: 10px; +--nav-font-size-level3: 9px; +--nav-text-normal-color: #B6C4DF; +--nav-menu-button-color: #B6C4DF; +--nav-menu-background-color: #05070C; +--nav-menu-foreground-color: #BBBBBB; +--nav-menu-active-bg: #1D2A43; +--nav-menu-active-color: #C9D3E7; +--nav-arrow-color: #4665A2; +--nav-arrow-selected-color: #6884BD; + +/* sync icon */ +--sync-icon-border-color: #212F4B; +--sync-icon-background-color: #101826; +--sync-icon-selected-background-color: #1D2A43; +--sync-icon-color: #4665A2; +--sync-icon-selected-color: #5373B4; + +/* table of contents */ +--toc-background-color: #151E30; +--toc-border-color: #202E4A; +--toc-header-color: #A3B4D7; +--toc-down-arrow-image: url("data:image/svg+xml;utf8,&%238595;"); + +/** search field */ +--search-background-color: black; +--search-foreground-color: #C5C5C5; +--search-active-color: #F5F5F5; +--search-filter-background-color: #101826; +--search-filter-foreground-color: #90A5CE; +--search-filter-backdrop-filter: none; +--search-filter-border-color: #7C95C6; +--search-filter-highlight-text-color: #BCC9E2; +--search-filter-highlight-bg-color: #283A5D; +--search-results-background-color: black; +--search-results-foreground-color: #90A5CE; +--search-results-backdrop-filter: none; +--search-results-border-color: #334975; +--search-box-border-color: #334975; +--search-close-icon-bg-color: #909090; +--search-close-icon-fg-color: black; + +/** code fragments */ +--code-keyword-color: #CC99CD; +--code-type-keyword-color: #AB99CD; +--code-flow-keyword-color: #E08000; +--code-comment-color: #717790; +--code-preprocessor-color: #65CABE; +--code-string-literal-color: #7EC699; +--code-char-literal-color: #00E0F0; +--code-xml-cdata-color: #C9D1D9; +--code-vhdl-digit-color: #FF00FF; +--code-vhdl-char-color: #C0C0C0; +--code-vhdl-keyword-color: #CF53C9; +--code-vhdl-logic-color: #FF0000; +--fragment-foreground-color: #C9D1D9; +--fragment-background-color: #090D16; +--fragment-border-color: #30363D; +--fragment-lineno-border-color: #30363D; +--fragment-lineno-background-color: black; +--fragment-lineno-foreground-color: #6E7681; +--fragment-lineno-link-fg-color: #6E7681; +--fragment-lineno-link-bg-color: #303030; +--fragment-lineno-link-hover-fg-color: #8E96A1; +--fragment-lineno-link-hover-bg-color: #505050; +--fragment-copy-ok-color: #0EA80E; +--fragment-highlight-filter: 5; +--tooltip-foreground-color: #C9D1D9; +--tooltip-background-color: #202020; +--tooltip-arrow-background-color: #202020; +--tooltip-backdrop-filter: none; +--tooltip-border-color: #C9D1D9; +--tooltip-doc-color: #D9E1E9; +--tooltip-declaration-color: #20C348; +--tooltip-link-color: #79C0FF; +--tooltip-shadow: none; +--fold-line-color: #808080; + +/** font-family */ +--font-family-normal: system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans,sans-serif,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol"; +--font-family-monospace: 'JetBrains Mono',Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace,fixed; +--font-family-nav: 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; +--font-family-title: system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans,sans-serif,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol"; +--font-family-toc: Verdana,'DejaVu Sans',Geneva,sans-serif; +--font-family-search: Arial,Verdana,sans-serif; +--font-family-icon: Arial,Helvetica; +--font-family-tooltip: Roboto,sans-serif; + +/** special sections */ +--warning-color-bg: #2e1917; +--warning-color-hl: #ad2617; +--warning-color-text: #f5b1aa; +--note-color-bg: #3b2e04; +--note-color-hl: #f1b602; +--note-color-text: #ceb670; +--todo-color-bg: #163750; +--todo-color-hl: #1982D2; +--todo-color-text: #dcf0fa; +--test-color-bg: #121258; +--test-color-hl: #4242cf; +--test-color-text: #c0c0da; +--deprecated-color-bg: #2e323b; +--deprecated-color-hl: #738396; +--deprecated-color-text: #abb0bd; +--bug-color-bg: #2a2536; +--bug-color-hl: #7661b3; +--bug-color-text: #ae9ed6; +--invariant-color-bg: #303a35; +--invariant-color-hl: #76ce96; +--invariant-color-text: #cceed5; +--satisfies-color-hl: #ad2617; +--satisfies-color-bg: #2e1917; +--verifies-color-hl: #ad2617; +--verifies-color-bg: #2e1917; + +}} +body { + background-color: var(--page-background-color); + color: var(--page-foreground-color); +} + +body, table, div, p, dl { + font-weight: 400; + font-size: 14px; + font-family: var(--font-family-normal); + line-height: 22px; +} + +body.resizing { + user-select: none; + -webkit-user-select: none; +} + +#doc-content { + scrollbar-width: thin; +} + +/* @group Heading Levels */ + +.title { + font-family: var(--font-family-normal); + line-height: 28px; + font-size: 160%; + font-weight: 400; + margin: 10px 2px; +} + +h1.groupheader { + font-size: 150%; +} + +h2.groupheader { + box-shadow: 12px 0 var(--page-background-color), + -12px 0 var(--page-background-color), + 12px 1px var(--group-header-separator-color), + -12px 1px var(--group-header-separator-color); + color: var(--group-header-color); + font-size: 150%; + font-weight: normal; + margin-top: 1.75em; + padding-top: 8px; + padding-bottom: 4px; + width: 100%; +} + +td h2.groupheader { + box-shadow: 13px 0 var(--page-background-color), + -13px 0 var(--page-background-color), + 13px 1px var(--group-header-separator-color), + -13px 1px var(--group-header-separator-color); +} + +h3.groupheader { + font-size: 100%; +} + +h1, h2, h3, h4, h5, h6 { + -webkit-transition: text-shadow 0.5s linear; + -moz-transition: text-shadow 0.5s linear; + -ms-transition: text-shadow 0.5s linear; + -o-transition: text-shadow 0.5s linear; + transition: text-shadow 0.5s linear; + margin-right: 15px; +} + +h1.glow, h2.glow, h3.glow, h4.glow, h5.glow, h6.glow { + text-shadow: 0 0 15px var(--glow-color); +} + +dt { + font-weight: bold; +} + +p.startli, p.startdd { + margin-top: 2px; + margin-bottom: 0px; +} + +th p.starttd, th p.intertd, th p.endtd { + font-size: 100%; + font-weight: 700; +} + +p.starttd { + margin-top: 0px; +} + +p.endli { + margin-bottom: 0px; +} + +p.enddd { + margin-bottom: 4px; +} + +p.endtd { + margin-bottom: 2px; +} + +p.interli { +} + +p.interdd { +} + +p.intertd { +} + +/* @end */ + +caption { + font-weight: bold; +} + +span.legend { + font-size: 70%; + text-align: center; +} + +h3.version { + font-size: 90%; + text-align: center; +} + +div.navtab { + margin-right: 6px; + padding-right: 6px; + text-align: right; + line-height: 110%; + background-color: var(--nav-background-color); +} + +div.navtab table { + border-spacing: 0; +} + +td.navtab { + padding-right: 6px; + padding-left: 6px; +} + +td.navtabHL { + padding-right: 6px; + padding-left: 6px; + border-radius: 0 6px 6px 0; + background-color: var(--nav-menu-active-bg); +} + +div.qindex{ + text-align: center; + width: 100%; + line-height: 140%; + font-size: 130%; + color: var(--index-separator-color); +} + +#main-menu a:focus { + outline: auto; + z-index: 10; + position: relative; +} + +dt.alphachar{ + font-size: 180%; + font-weight: bold; +} + +.alphachar a{ + color: var(--index-header-color); +} + +.alphachar a:hover, .alphachar a:visited{ + text-decoration: none; +} + +.classindex dl { + padding: 25px; + column-count:1 +} + +.classindex dd { + display:inline-block; + margin-left: 50px; + width: 90%; + line-height: 1.15em; +} + +.classindex dl.even { + background-color: var(--index-even-item-bg-color); +} + +.classindex dl.odd { + background-color: var(--index-odd-item-bg-color); +} + +@media(min-width: 1120px) { + .classindex dl { + column-count:2 + } +} + +@media(min-width: 1320px) { + .classindex dl { + column-count:3 + } +} + + +/* @group Link Styling */ + +a { + color: var(--page-link-color); + font-weight: normal; + text-decoration: none; +} + +.contents a:visited { + color: var(--page-visited-link-color); +} + +span.label a:hover { + text-decoration: none; + background: linear-gradient(to bottom, transparent 0,transparent calc(100% - 1px), currentColor 100%); +} + +a.el { + font-weight: bold; +} + +a.elRef { +} + +a.el, a.el:visited, a.code, a.code:visited, a.line, a.line:visited { + color: var(--page-link-color); +} + +a.codeRef, a.codeRef:visited, a.lineRef, a.lineRef:visited { + color: var(--page-external-link-color); +} + +a.code.hl_class { /* style for links to class names in code snippets */ } +a.code.hl_struct { /* style for links to struct names in code snippets */ } +a.code.hl_union { /* style for links to union names in code snippets */ } +a.code.hl_interface { /* style for links to interface names in code snippets */ } +a.code.hl_protocol { /* style for links to protocol names in code snippets */ } +a.code.hl_category { /* style for links to category names in code snippets */ } +a.code.hl_exception { /* style for links to exception names in code snippets */ } +a.code.hl_service { /* style for links to service names in code snippets */ } +a.code.hl_singleton { /* style for links to singleton names in code snippets */ } +a.code.hl_concept { /* style for links to concept names in code snippets */ } +a.code.hl_namespace { /* style for links to namespace names in code snippets */ } +a.code.hl_package { /* style for links to package names in code snippets */ } +a.code.hl_define { /* style for links to macro names in code snippets */ } +a.code.hl_function { /* style for links to function names in code snippets */ } +a.code.hl_variable { /* style for links to variable names in code snippets */ } +a.code.hl_typedef { /* style for links to typedef names in code snippets */ } +a.code.hl_enumvalue { /* style for links to enum value names in code snippets */ } +a.code.hl_enumeration { /* style for links to enumeration names in code snippets */ } +a.code.hl_signal { /* style for links to Qt signal names in code snippets */ } +a.code.hl_slot { /* style for links to Qt slot names in code snippets */ } +a.code.hl_friend { /* style for links to friend names in code snippets */ } +a.code.hl_dcop { /* style for links to KDE3 DCOP names in code snippets */ } +a.code.hl_property { /* style for links to property names in code snippets */ } +a.code.hl_event { /* style for links to event names in code snippets */ } +a.code.hl_sequence { /* style for links to sequence names in code snippets */ } +a.code.hl_dictionary { /* style for links to dictionary names in code snippets */ } + +div.embeddoc { + font-family: var(--font-family-monospace); + padding-left: 10px; +} + +/* @end */ + +dl.el { + margin-left: -1cm; +} + +ul.check { + list-style: none; + padding-left: 40px; + margin: 0; +} + +ul.check li { + position: relative; +} + +li.unchecked::before, li.checked::before { + position: absolute; + left: -18px; + top: 0; +} + +li.unchecked::before { + content: "☐"; +} + +li.checked::before { + content: "☑"; +} + +ul.check li > p { + display: inline; +} + +ul.check li > p:not(:first-child) { + display: block; +} + +ol { + text-indent: 0px; +} + +ul { + text-indent: 0px; + overflow: visible; +} + +ul.multicol { + -moz-column-gap: 1em; + -webkit-column-gap: 1em; + column-gap: 1em; + -moz-column-count: 3; + -webkit-column-count: 3; + column-count: 3; + list-style-type: none; +} + +#side-nav ul { + overflow: visible; /* reset ul rule for scroll bar in GENERATE_TREEVIEW window */ +} + +#main-nav ul { + overflow: visible; /* reset ul rule for the navigation bar drop down lists */ +} + +.fragment { + text-align: left; + direction: ltr; + overflow-x: auto; + overflow-y: hidden; + position: relative; + min-height: 12px; + margin: 10px 0px; + padding: 10px 10px; + border: 1px solid var(--fragment-border-color); + border-radius: 4px; + background-color: var(--fragment-background-color); + color: var(--fragment-foreground-color); +} + +pre.fragment { + word-wrap: break-word; + font-size: 10pt; + line-height: 125%; + font-family: var(--font-family-monospace); +} + +span.tt { + white-space: pre; + font-family: var(--font-family-monospace); + background-color: var(--fragment-background-color); +} + +.clipboard { + width: 24px; + height: 24px; + right: 5px; + top: 5px; + opacity: 0; + position: absolute; + display: inline; + overflow: hidden; + justify-content: center; + align-items: center; + cursor: pointer; +} + +.clipboard.success { + border: 1px solid var(--fragment-foreground-color); + border-radius: 4px; +} + +.fragment:hover .clipboard, .clipboard.success { + opacity: .4; +} + +.clipboard:hover, .clipboard.success { + opacity: 1 !important; +} + +.clipboard:active:not([class~=success]) svg { + transform: scale(.91); +} + +.clipboard.success svg { + fill: var(--fragment-copy-ok-color); +} + +.clipboard.success { + border-color: var(--fragment-copy-ok-color); +} + +div.line { + font-family: var(--font-family-monospace); + font-size: 13px; + min-height: 13px; + line-height: 1.2; + text-wrap: wrap; + word-break: break-all; + white-space: -moz-pre-wrap; /* Moz */ + white-space: -pre-wrap; /* Opera 4-6 */ + white-space: -o-pre-wrap; /* Opera 7 */ + white-space: pre-wrap; /* CSS3 */ + word-wrap: break-word; /* IE 5.5+ */ + text-indent: -62px; + padding-left: 62px; + padding-bottom: 0px; + margin: 0px; + -webkit-transition-property: background-color, box-shadow; + -webkit-transition-duration: 0.5s; + -moz-transition-property: background-color, box-shadow; + -moz-transition-duration: 0.5s; + -ms-transition-property: background-color, box-shadow; + -ms-transition-duration: 0.5s; + -o-transition-property: background-color, box-shadow; + -o-transition-duration: 0.5s; + transition-property: background-color, box-shadow; + transition-duration: 0.5s; +} + +div.line:after { + content:"\000A"; + white-space: pre; +} + +div.line.glow { + background-color: var(--glow-color); + box-shadow: 0 0 10px var(--glow-color); +} + +span.fold { + display: inline-block; + width: 12px; + height: 12px; + margin-left: 4px; + margin-right: 1px; +} + +span.foldnone { + display: inline-block; + position: relative; + cursor: pointer; + user-select: none; +} + +span.fold.plus, span.fold.minus { + width: 10px; + height: 10px; + background-color: var(--fragment-background-color); + position: relative; + border: 1px solid var(--fold-line-color); + margin-right: 1px; +} + +span.fold.plus::before, span.fold.minus::before { + content: ''; + position: absolute; + background-color: var(--fold-line-color); +} + +span.fold.plus::before { + width: 2px; + height: 6px; + top: 2px; + left: 4px; +} + +span.fold.plus::after { + content: ''; + position: absolute; + width: 6px; + height: 2px; + top: 4px; + left: 2px; + background-color: var(--fold-line-color); +} + +span.fold.minus::before { + width: 6px; + height: 2px; + top: 4px; + left: 2px; +} + +span.lineno { + padding-right: 4px; + margin-right: 9px; + text-align: right; + border-right: 2px solid var(--fragment-lineno-border-color); + color: var(--fragment-lineno-foreground-color); + background-color: var(--fragment-lineno-background-color); + white-space: pre; +} +span.lineno a, span.lineno a:visited { + color: var(--fragment-lineno-link-fg-color); + background-color: var(--fragment-lineno-link-bg-color); +} + +span.lineno a:hover { + color: var(--fragment-lineno-link-hover-fg-color); + background-color: var(--fragment-lineno-link-hover-bg-color); +} + +.lineno { + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +div.classindex ul { + list-style: none; + padding-left: 0; +} + +div.classindex span.ai { + display: inline-block; +} + +div.groupHeader { + box-shadow: 13px 0 var(--page-background-color), + -13px 0 var(--page-background-color), + 13px 1px var(--group-header-separator-color), + -13px 1px var(--group-header-separator-color); + color: var(--group-header-color); + font-size: 110%; + font-weight: 500; + margin-left: 0px; + margin-top: 0em; + margin-bottom: 6px; + padding-top: 8px; + padding-bottom: 4px; +} + +div.groupText { + margin-left: 16px; + font-style: italic; +} + +body { + color: var(--page-foreground-color); + margin: 0; +} + +div.contents { + margin-top: 10px; + margin-left: 12px; + margin-right: 12px; +} + +p.formulaDsp { + text-align: center; +} + +img.dark-mode-visible { + display: none; +} +img.light-mode-visible { + display: none; +} + +img.formulaInl, img.inline { + vertical-align: middle; +} + +div.center { + text-align: center; + margin-top: 0px; + margin-bottom: 0px; + padding: 0px; +} + +div.center img { + border: 0px; +} + +address.footer { + text-align: right; + padding-right: 12px; +} + +img.footer { + border: 0px; + vertical-align: middle; + width: var(--footer-logo-width); +} + +.compoundTemplParams { + color: var(--memdecl-template-color); + font-size: 80%; + line-height: 120%; +} + +/* @group Code Colorization */ + +span.keyword { + color: var(--code-keyword-color); +} + +span.keywordtype { + color: var(--code-type-keyword-color); +} + +span.keywordflow { + color: var(--code-flow-keyword-color); +} + +span.comment { + color: var(--code-comment-color); +} + +span.preprocessor { + color: var(--code-preprocessor-color); +} + +span.stringliteral { + color: var(--code-string-literal-color); +} + +span.charliteral { + color: var(--code-char-literal-color); +} + +span.xmlcdata { + color: var(--code-xml-cdata-color); +} + +span.vhdldigit { + color: var(--code-vhdl-digit-color); +} + +span.vhdlchar { + color: var(--code-vhdl-char-color); +} + +span.vhdlkeyword { + color: var(--code-vhdl-keyword-color); +} + +span.vhdllogic { + color: var(--code-vhdl-logic-color); +} + +blockquote { + background-color: var(--blockquote-background-color); + border-left: 2px solid var(--blockquote-border-color); + margin: 0 24px 0 4px; + padding: 0 12px 0 16px; +} + +/* @end */ + +td.tiny { + font-size: 75%; +} + +.dirtab { + padding: 4px; + border-collapse: collapse; + border: 1px solid var(--table-cell-border-color); +} + +th.dirtab { + background-color: var(--table-header-background-color); + color: var(--table-header-foreground-color); + font-weight: bold; +} + +hr { + border: none; + margin-top: 16px; + margin-bottom: 16px; + height: 1px; + box-shadow: 13px 0 var(--page-background-color), + -13px 0 var(--page-background-color), + 13px 1px var(--group-header-separator-color), + -13px 1px var(--group-header-separator-color); +} + +hr.footer { + height: 1px; +} + +/* @group Member Descriptions */ + +table.memberdecls { + border-spacing: 0px; + padding: 0px; +} + +.memberdecls td, .fieldtable tr { + transition-property: background-color, box-shadow; + transition-duration: 0.5s; +} + +.memberdecls td.glow, .fieldtable tr.glow { + background-color: var(--glow-color); + box-shadow: 0 0 15px var(--glow-color); +} + +.memberdecls tr[class^='memitem'] { + font-family: var(--font-family-monospace); +} + +.mdescLeft, .mdescRight, +.memItemLeft, .memItemRight { + padding-top: 2px; + padding-bottom: 2px; +} + +.memTemplParams { + padding-left: 10px; + padding-top: 5px; +} + +.memItemLeft, .memItemRight, .memTemplParams { + background-color: var(--memdecl-background-color); +} + +.mdescLeft, .mdescRight { + padding: 0px 8px 4px 8px; + color: var(--memdecl-foreground-color); +} + +tr[class^='memdesc'] { + box-shadow: inset 0px 1px 3px 0px rgba(0,0,0,.075); +} + +.mdescLeft { + border-left: 1px solid var(--memdecl-border-color); + border-bottom: 1px solid var(--memdecl-border-color); +} + +.mdescRight { + border-right: 1px solid var(--memdecl-border-color); + border-bottom: 1px solid var(--memdecl-border-color); +} + +.memTemplParams { + color: var(--memdecl-template-color); + white-space: nowrap; + font-size: 80%; + border-left: 1px solid var(--memdecl-border-color); + border-right: 1px solid var(--memdecl-border-color); +} + +td.ititle { + border: 1px solid var(--memdecl-border-color); + border-top-left-radius: 4px; + border-top-right-radius: 4px; + padding-left: 10px; +} + +tr:not(:first-child) > td.ititle { + border-top: 0; + border-radius: 0; +} + +.memItemLeft { + white-space: nowrap; + border-left: 1px solid var(--memdecl-border-color); + border-bottom: 1px solid var(--memdecl-border-color); + padding-left: 10px; + transition: none; + vertical-align: top; + text-align: right; +} + +.memItemRight { + width: 100%; + border-right: 1px solid var(--memdecl-border-color); + border-bottom: 1px solid var(--memdecl-border-color); + padding-right: 10px; + transition: none; + vertical-align: bottom; +} + +tr.heading + tr[class^='memitem'] td.memItemLeft, +tr.groupHeader + tr[class^='memitem'] td.memItemLeft, +tr.inherit_header + tr[class^='memitem'] td.memItemLeft { + border-top: 1px solid var(--memdecl-border-color); + border-top-left-radius: 4px; +} + +tr.heading + tr[class^='memitem'] td.memItemRight, +tr.groupHeader + tr[class^='memitem'] td.memItemRight, +tr.inherit_header + tr[class^='memitem'] td.memItemRight { + border-top: 1px solid var(--memdecl-border-color); + border-top-right-radius: 4px; +} + +tr.heading + tr[class^='memitem'] td.memTemplParams, +tr.heading + tr td.ititle, +tr.groupHeader + tr[class^='memitem'] td.memTemplParams, +tr.groupHeader + tr td.ititle, +tr.inherit_header + tr[class^='memitem'] td.memTemplParams { + border-top: 1px solid var(--memdecl-border-color); + border-top-left-radius: 4px; + border-top-right-radius: 4px; +} + +table.memberdecls tr:last-child td.memItemLeft, +table.memberdecls tr:last-child td.mdescLeft, +table.memberdecls tr[class^='memitem']:has(+ tr.groupHeader) td.memItemLeft, +table.memberdecls tr[class^='memitem']:has(+ tr.inherit_header) td.memItemLeft, +table.memberdecls tr[class^='memdesc']:has(+ tr.groupHeader) td.mdescLeft, +table.memberdecls tr[class^='memdesc']:has(+ tr.inherit_header) td.mdescLeft { + border-bottom-left-radius: 4px; +} + +table.memberdecls tr:last-child td.memItemRight, +table.memberdecls tr:last-child td.mdescRight, +table.memberdecls tr[class^='memitem']:has(+ tr.groupHeader) td.memItemRight, +table.memberdecls tr[class^='memitem']:has(+ tr.inherit_header) td.memItemRight, +table.memberdecls tr[class^='memdesc']:has(+ tr.groupHeader) td.mdescRight, +table.memberdecls tr[class^='memdesc']:has(+ tr.inherit_header) td.mdescRight { + border-bottom-right-radius: 4px; +} + +tr.template .memItemLeft, tr.template .memItemRight { + border-top: none; + padding-top: 0; +} + + +/* @end */ + +/* @group Member Details */ + +/* Styles for detailed member documentation */ + +.memtitle { + padding: 8px; + border-top: 1px solid var(--memdef-border-color); + border-left: 1px solid var(--memdef-border-color); + border-right: 1px solid var(--memdef-border-color); + border-top-right-radius: 4px; + border-top-left-radius: 4px; + margin-bottom: -1px; + background-color: var(--memdef-proto-background-color); + line-height: 1.25; + font-family: var(--font-family-monospace); + font-weight: 500; + font-size: 16px; + float:left; + box-shadow: 0 10px 0 -1px var(--memdef-proto-background-color), + 0 2px 8px 0 rgba(0,0,0,.075); + position: relative; +} + +.memtitle:after { + content: ''; + display: block; + background: var(--memdef-proto-background-color); + height: 10px; + bottom: -10px; + left: 0px; + right: -14px; + position: absolute; + border-top-right-radius: 6px; +} + +.permalink +{ + font-family: var(--font-family-monospace); + font-weight: 500; + line-height: 1.25; + font-size: 16px; + display: inline-block; + vertical-align: middle; +} + +.memtemplate { + font-size: 80%; + color: var(--memdef-template-color); + font-family: var(--font-family-monospace); + font-weight: normal; + margin-left: 9px; +} + +.mempage { + width: 100%; +} + +.memitem { + padding: 0; + margin-bottom: 10px; + margin-right: 5px; + display: table !important; + width: 100%; + box-shadow: 0 2px 8px 0 rgba(0,0,0,.075); + border-radius: 4px; +} + +.memitem.glow { + box-shadow: 0 0 15px var(--glow-color); +} + +.memname { + font-family: var(--font-family-monospace); + font-size: 13px; + font-weight: 400; + margin-left: 6px; +} + +.memname td { + vertical-align: bottom; +} + +.memproto, dl.reflist dt { + border-top: 1px solid var(--memdef-border-color); + border-left: 1px solid var(--memdef-border-color); + border-right: 1px solid var(--memdef-border-color); + padding: 6px 0px 6px 0px; + color: var(--memdef-proto-text-color); + font-weight: bold; + background-color: var(--memdef-proto-background-color); + border-top-right-radius: 4px; + border-bottom: 1px solid var(--memdef-border-color); +} + +.overload { + font-family: var(--font-family-monospace); + font-size: 65%; +} + +.memdoc, dl.reflist dd { + border-bottom: 1px solid var(--memdef-border-color); + border-left: 1px solid var(--memdef-border-color); + border-right: 1px solid var(--memdef-border-color); + padding: 6px 10px 2px 10px; + border-top-width: 0; + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; +} + +dl.reflist dt { + padding: 5px; +} + +dl.reflist dd { + margin: 0px 0px 10px 0px; + padding: 5px; +} + +.paramkey { + text-align: right; +} + +.paramtype { + white-space: nowrap; + padding: 0px; + padding-bottom: 1px; +} + +.paramname { + white-space: nowrap; + padding: 0px; + padding-bottom: 1px; + margin-left: 2px; +} + +.paramname em { + color: var(--memdef-param-name-color); + font-style: normal; + margin-right: 1px; +} + +.paramname .paramdefval { + font-family: var(--font-family-monospace); +} + +.params, .retval, .exception, .tparams { + margin-left: 0px; + padding-left: 0px; +} + +.params .paramname, .retval .paramname, .tparams .paramname, .exception .paramname { + font-weight: bold; + vertical-align: top; +} + +.params .paramtype, .tparams .paramtype { + font-style: italic; + vertical-align: top; +} + +.params .paramdir, .tparams .paramdir { + font-family: var(--font-family-monospace); + vertical-align: top; +} + +table.mlabels { + border-spacing: 0px; +} + +td.mlabels-left { + width: 100%; + padding: 0px; +} + +td.mlabels-right { + vertical-align: bottom; + padding: 0px; + white-space: nowrap; +} + +span.mlabels { + margin-left: 8px; +} + +span.mlabel { + background-color: var(--label-background-color); + border-top:1px solid var(--label-left-top-border-color); + border-left:1px solid var(--label-left-top-border-color); + border-right:1px solid var(--label-right-bottom-border-color); + border-bottom:1px solid var(--label-right-bottom-border-color); + text-shadow: none; + color: var(--label-foreground-color); + margin-right: 4px; + padding: 2px 3px; + border-radius: 3px; + font-size: 7pt; + white-space: nowrap; + vertical-align: middle; +} + + + +/* @end */ + +/* these are for tree view inside a (index) page */ + +div.directory { + margin: 10px 0px; + width: 100%; +} + +.directory table { + border-collapse:collapse; +} + +.directory td { + margin: 0px; + padding: 0px; + vertical-align: top; +} + +.directory td.entry { + white-space: nowrap; + padding-right: 6px; + padding-top: 3px; +} + +.directory td.entry a { + outline:none; +} + +.directory td.entry a img { + border: none; +} + +.directory td.desc { + width: 100%; + padding-left: 6px; + padding-right: 6px; + padding-top: 3px; + border-left: 1px solid rgba(0,0,0,0.05); +} + +.directory tr.odd { + padding-left: 6px; + background-color: var(--index-odd-item-bg-color); +} + +.directory tr.even { + padding-left: 6px; + background-color: var(--index-even-item-bg-color); +} + +.directory img { + vertical-align: -30%; +} + +.directory .levels { + white-space: nowrap; + width: 100%; + text-align: right; + font-size: 9pt; +} + +.directory .levels span { + cursor: pointer; + padding-left: 2px; + padding-right: 2px; + color: var(--page-link-color); +} + +.arrow { + color: var(--nav-background-color); + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + cursor: pointer; + font-size: 80%; + display: inline-block; + width: 16px; + height: 14px; + transition: opacity 0.3s ease; +} + +span.arrowhead { + position: relative; + padding: 0; + margin: 0 0 0 2px; + display: inline-block; + width: 5px; + height: 5px; + border-right: 2px solid var(--nav-arrow-color); + border-bottom: 2px solid var(--nav-arrow-color); + transform: rotate(-45deg); + transition: transform 0.3s ease; +} + +span.arrowhead.opened { + transform: rotate(45deg); +} + +.selected span.arrowhead { + border-right: 2px solid var(--nav-arrow-selected-color); + border-bottom: 2px solid var(--nav-arrow-selected-color); +} + +.icon { + font-family: var(--font-family-icon); + line-height: normal; + font-weight: bold; + font-size: 12px; + height: 14px; + width: 16px; + display: inline-block; + background-color: var(--icon-background-color); + color: var(--icon-foreground-color); + text-align: center; + border-radius: 4px; + margin-left: 2px; + margin-right: 2px; +} + +.icona { + width: 24px; + height: 22px; + display: inline-block; +} + +.iconfolder { + width: 24px; + height: 18px; + margin-top: 6px; + vertical-align:top; + display: inline-block; + position: relative; +} + +.icondoc { + width: 24px; + height: 18px; + margin-top: 3px; + vertical-align:top; + display: inline-block; + position: relative; +} + +.folder-icon { + width: 16px; + height: 11px; + background-color: var(--icon-folder-fill-color); + border: 1px solid var(--icon-folder-border-color); + border-radius: 0 2px 2px 2px; + position: relative; + box-sizing: content-box; +} + +.folder-icon::after { + content: ''; + position: absolute; + top: 2px; + left: -1px; + width: 16px; + height: 7px; + background-color: var(--icon-folder-open-fill-color); + border: 1px solid var(--icon-folder-border-color); + border-radius: 7px 7px 2px 2px; + transform-origin: top left; + opacity: 0; + transition: all 0.3s linear; +} + +.folder-icon::before { + content: ''; + position: absolute; + top: -3px; + left: -1px; + width: 6px; + height: 2px; + background-color: var(--icon-folder-fill-color); + border-top: 1px solid var(--icon-folder-border-color); + border-left: 1px solid var(--icon-folder-border-color); + border-right: 1px solid var(--icon-folder-border-color); + border-radius: 2px 2px 0 0; +} + +.folder-icon.open::after { + top: 3px; + opacity: 1; +} + +.doc-icon { + left: 6px; + width: 12px; + height: 16px; + background-color: var(--icon-doc-border-color); + clip-path: polygon(0 0, 66% 0, 100% 25%, 100% 100%, 0 100%); + position: relative; + display: inline-block; +} +.doc-icon::before { + content: ""; + left: 1px; + top: 1px; + width: 10px; + height: 14px; + background-color: var(--icon-doc-fill-color); + clip-path: polygon(0 0, 66% 0, 100% 25%, 100% 100%, 0 100%); + position: absolute; + box-sizing: border-box; +} +.doc-icon::after { + content: ""; + left: 7px; + top: 0px; + width: 3px; + height: 3px; + background-color: transparent; + position: absolute; + border: 1px solid var(--icon-doc-border-color); +} + + + + +/* @end */ + +div.dynheader { + margin-top: 8px; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +span.dynarrow { + position: relative; + display: inline-block; + width: 12px; + bottom: 1px; +} + +address { + font-style: normal; + color: var(--footer-foreground-color); +} + +table.doxtable caption { + caption-side: top; +} + +table.doxtable { + border-collapse:collapse; + margin-top: 4px; + margin-bottom: 4px; +} + +table.doxtable td, table.doxtable th { + border: 1px solid var(--table-cell-border-color); + padding: 3px 7px 2px; +} + +table.doxtable th { + background-color: var(--table-header-background-color); + color: var(--table-header-foreground-color); + font-size: 110%; + padding-bottom: 4px; + padding-top: 5px; +} + +table.fieldtable { + margin-bottom: 10px; + border: 1px solid var(--memdef-border-color); + border-spacing: 0px; + border-radius: 4px; + box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15); +} + +.fieldtable td, .fieldtable th { + padding: 3px 7px 2px; +} + +.fieldtable td.fieldtype, .fieldtable td.fieldname, .fieldtable td.fieldinit { + white-space: nowrap; + border-right: 1px solid var(--memdef-border-color); + border-bottom: 1px solid var(--memdef-border-color); + vertical-align: top; +} + +.fieldtable td.fieldname { + padding-top: 3px; +} + +.fieldtable td.fieldinit { + padding-top: 3px; + text-align: right; +} + +.fieldtable td.fielddoc { + border-bottom: 1px solid var(--memdef-border-color); +} + +.fieldtable td.fielddoc p:first-child { + margin-top: 0px; +} + +.fieldtable td.fielddoc p:last-child { + margin-bottom: 2px; +} + +.fieldtable tr:last-child td { + border-bottom: none; +} + +.fieldtable th { + background-color: var(--memdef-title-background-color); + font-size: 90%; + color: var(--memdef-proto-text-color); + padding-bottom: 4px; + padding-top: 5px; + text-align:left; + font-weight: 400; + border-top-left-radius: 4px; + border-top-right-radius: 4px; + border-bottom: 1px solid var(--memdef-border-color); +} + +/* style requirements page */ + +div.req_title { + text-decoration-line: underline; + text-decoration-style: solid; + text-decoration-color: var(--table-cell-border-color); + text-decoration-thickness: 1px; + font-weight: bold; +} + +table.reqlist tr > td:first-child { + text-align: right; + font-weight: bold; +} + +div.missing_satisfies { + border-left: 8px solid var(--satisfies-color-hl); + border-radius: 4px; + background: var(--satisfies-color-bg); + padding: 10px; + margin: 10px 0px; + overflow: hidden; + margin-left: 0; +} + +div.missing_verifies { + border-left: 8px solid var(--verifies-color-hl); + border-radius: 4px; + background: var(--verifies-color-bg); + padding: 10px; + margin: 10px 0px; + overflow: hidden; + margin-left: 0; +} + +/* ----------- navigation breadcrumb styling ----------- */ + +#nav-path ul { + height: 30px; + line-height: 30px; + color: var(--nav-text-normal-color); + overflow: hidden; + margin: 0px; + padding-left: 4px; + background-image: none; + background: var(--page-background-color); + border-bottom: 1px solid var(--nav-breadcrumb-separator-color); + font-size: var(--nav-font-size-level1); + font-family: var(--font-family-nav); + position: relative; + z-index: 100; +} + +#main-nav { + border-bottom: 1px solid var(--nav-border-color); +} + +.navpath li { + list-style-type:none; + float:left; + color: var(--nav-foreground-color); +} + +.navpath li.footer { + list-style-type:none; + float:right; + padding-left:10px; + padding-right:15px; + background-image:none; + background-repeat:no-repeat; + background-position:right; + font-size: 8pt; + color: var(--footer-foreground-color); +} + +#nav-path li.navelem { + background-image: none; + display: flex; + align-items: center; + padding-left: 15px; +} + +.navpath li.navelem a { + text-shadow: none; + display: inline-block; + color: var(--nav-breadcrumb-color); + position: relative; + top: 0px; + height: 30px; + margin-right: -20px; +} + +#nav-path li.navelem:after { + content: ''; + display: inline-block; + position: relative; + top: 0; + right: -15px; + width: 30px; + height: 30px; + transform: scaleX(0.5) scale(0.707) rotate(45deg); + z-index: 10; + background: var(--page-background-color); + box-shadow: 2px -2px 0 2px var(--nav-breadcrumb-separator-color); + border-radius: 0 5px 0 50px; +} + +#nav-path li.navelem:first-child { + margin-left: -6px; +} + +#nav-path li.navelem:hover, +#nav-path li.navelem:hover:after { + background-color: var(--nav-breadcrumb-active-bg); +} + +/* ---------------------- */ + +div.summary +{ + float: right; + font-size: 8pt; + padding-right: 5px; + width: 50%; + text-align: right; +} + +div.summary a +{ + white-space: nowrap; +} + +table.classindex +{ + margin: 10px; + white-space: nowrap; + margin-left: 3%; + margin-right: 3%; + width: 94%; + border: 0; + border-spacing: 0; + padding: 0; +} + +div.ingroups +{ + font-size: 8pt; + width: 50%; + text-align: left; +} + +div.ingroups a +{ + white-space: nowrap; +} + +div.header +{ + margin: 0px; + background-color: var(--header-background-color); + border-bottom: 1px solid var(--header-separator-color); +} + +div.headertitle +{ + padding: 5px 5px 5px 10px; +} + +dl { + padding: 0 0 0 0; +} + +dl.bug dt a, dl.deprecated dt a, dl.todo dt a, dl.test a { + font-weight: bold !important; +} + +dl.warning, dl.attention, dl.important, dl.note, dl.deprecated, dl.bug, +dl.invariant, dl.pre, dl.post, dl.todo, dl.test, dl.remark { + padding: 10px; + margin: 10px 0px; + overflow: hidden; + margin-left: 0; + border-radius: 4px; +} + +dl.section dd { + margin-bottom: 2px; +} + +dl.warning, dl.attention, dl.important { + background: var(--warning-color-bg); + border-left: 8px solid var(--warning-color-hl); + color: var(--warning-color-text); +} + +dl.warning dt, dl.attention dt, dl.important dt { + color: var(--warning-color-hl); +} + +dl.warning .tt, dl.attention .tt, dl.important .tt { + background-color: hsl(from var(--warning-color-bg) h s calc(l + var(--fragment-highlight-filter))); +} + +dl.note, dl.remark { + background: var(--note-color-bg); + border-left: 8px solid var(--note-color-hl); + color: var(--note-color-text); +} + +dl.note dt, dl.remark dt { + color: var(--note-color-hl); +} + +dl.note .tt, dl.remark .tt { + background-color: hsl(from var(--note-color-bg) h s calc(l + var(--fragment-highlight-filter))); +} + +dl.todo { + background: var(--todo-color-bg); + border-left: 8px solid var(--todo-color-hl); + color: var(--todo-color-text); +} + +dl.todo dt { + color: var(--todo-color-hl); +} + +dl.todo .tt { + background-color: hsl(from var(--todo-color-bg) h s calc(l + var(--fragment-highlight-filter))); +} + +dl.test { + background: var(--test-color-bg); + border-left: 8px solid var(--test-color-hl); + color: var(--test-color-text); +} + +dl.test dt { + color: var(--test-color-hl); +} + +dl.test .tt { + background-color: hsl(from var(--test-color-bg) h s calc(l + var(--fragment-highlight-filter))); +} + +dl.bug dt a { + color: var(--bug-color-hl) !important; +} + +dl.bug { + background: var(--bug-color-bg); + border-left: 8px solid var(--bug-color-hl); + color: var(--bug-color-text); +} + +dl.bug dt a { + color: var(--bug-color-hl) !important; +} + +dl.bug .tt { + background-color: hsl(from var(--bug-color-bg) h s calc(l + var(--fragment-highlight-filter))); +} + +dl.deprecated { + background: var(--deprecated-color-bg); + border-left: 8px solid var(--deprecated-color-hl); + color: var(--deprecated-color-text); +} + +dl.deprecated dt a { + color: var(--deprecated-color-hl) !important; +} + +dl.deprecated .tt { + background-color: hsl(from var(--deprecated-color-bg) h s calc(l + var(--fragment-highlight-filter))); +} + + +dl.invariant, dl.pre, dl.post { + background: var(--invariant-color-bg); + border-left: 8px solid var(--invariant-color-hl); + color: var(--invariant-color-text); +} + +dl.invariant dt, dl.pre dt, dl.post dt { + color: var(--invariant-color-hl); +} + +dl.invariant .tt, dl.pre .tt, dl.post .tt { + background-color: hsl(from var(--invariant-color-bg) h s calc(l + var(--fragment-highlight-filter))); +} + +dl.note dd, dl.warning dd, dl.pre dd, dl.post dd, +dl.remark dd, dl.attention dd, dl.important dd, dl.invariant dd, +dl.bug dd, dl.deprecated dd, dl.todo dd, dl.test dd { + margin-inline-start: 0px; +} + + +#projectrow +{ + height: 56px; +} + +#projectlogo +{ + text-align: center; + vertical-align: bottom; + border-collapse: separate; +} + +#projectlogo img +{ + border: 0px none; +} + +#projectalign +{ + vertical-align: middle; + padding-left: 0.5em; +} + +#projectname +{ + font-size: 200%; + font-family: var(--font-family-title); + margin: 0; + padding: 0; +} + +#side-nav #projectname +{ + font-size: 130%; +} + +#projectbrief +{ + font-size: 90%; + font-family: var(--font-family-title); + margin: 0px; + padding: 0px; +} + +#projectnumber +{ + font-size: 50%; + font-family: var(--font-family-title); + margin: 0px; + padding: 0px; +} + +#titlearea +{ + padding: 0 0 0 5px; + margin: 0px; + border-bottom: 1px solid var(--title-separator-color); + background-color: var(--title-background-color); +} + +.image +{ + text-align: center; +} + +.dotgraph +{ + text-align: center; +} + +.mscgraph +{ + text-align: center; +} + +.plantumlgraph +{ + text-align: center; +} + +.diagraph +{ + text-align: center; +} + +.caption +{ + font-weight: bold; +} + +dl.citelist { + margin-bottom:50px; +} + +dl.citelist dt { + color:var(--citation-label-color); + float:left; + font-weight:bold; + margin-right:10px; + padding:5px; + text-align:right; + width:52px; +} + +dl.citelist dd { + margin:2px 0 2px 72px; + padding:5px 0; +} + +div.toc { + padding: 14px 25px; + background-color: var(--toc-background-color); + border: 1px solid var(--toc-border-color); + border-radius: 7px 7px 7px 7px; + float: right; + height: auto; + margin: 0 8px 10px 10px; + width: 200px; +} + +div.toc li { + background: var(--toc-down-arrow-image) no-repeat scroll 0 5px transparent; + font: 10px/1.2 var(--font-family-toc); + margin-top: 5px; + padding-left: 10px; + padding-top: 2px; +} + +div.toc h3 { + font: bold 12px/1.2 var(--font-family-toc); + color: var(--toc-header-color); + border-bottom: 0 none; + margin: 0; +} + +div.toc ul { + list-style: none outside none; + border: medium none; + padding: 0px; +} + +div.toc li[class^='level'] { + margin-left: 15px; +} + +div.toc li.level1 { + margin-left: 0px; +} + +div.toc li.empty { + background-image: none; + margin-top: 0px; +} + +span.emoji { + /* font family used at the site: https://unicode.org/emoji/charts/full-emoji-list.html + * font-family: "Noto Color Emoji", "Apple Color Emoji", "Segoe UI Emoji", Times, Symbola, Aegyptus, Code2000, Code2001, Code2002, Musica, serif, LastResort; + */ +} + +span.obfuscator { + display: none; +} + +.inherit_header { + font-weight: 400; + cursor: pointer; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.inherit_header td { + padding: 6px 0 2px 0; +} + +.inherit { + display: none; +} + +tr.heading h2 { + margin-top: 12px; + margin-bottom: 12px; +} + +/* tooltip related style info */ + +.ttc { + position: absolute; + display: none; +} + +#powerTip { + cursor: default; + color: var(--tooltip-foreground-color); + background-color: var(--tooltip-background-color); + backdrop-filter: var(--tooltip-backdrop-filter); + -webkit-backdrop-filter: var(--tooltip-backdrop-filter); + border: 1px solid var(--tooltip-border-color); + border-radius: 4px; + box-shadow: var(--tooltip-shadow); + display: none; + font-size: smaller; + max-width: 80%; + padding: 1ex 1em 1em; + position: absolute; + z-index: 2147483647; +} + +#powerTip div.ttdoc { + color: var(--tooltip-doc-color); + font-style: italic; +} + +#powerTip div.ttname a { + font-weight: bold; +} + +#powerTip a { + color: var(--tooltip-link-color); +} + +#powerTip div.ttname { + font-weight: bold; +} + +#powerTip div.ttdeci { + color: var(--tooltip-declaration-color); +} + +#powerTip div { + margin: 0px; + padding: 0px; + font-size: 12px; + font-family: var(--font-family-tooltip); + line-height: 16px; +} + +#powerTip:before, #powerTip:after { + content: ""; + position: absolute; + margin: 0px; +} + +#powerTip.n:after, #powerTip.n:before, +#powerTip.s:after, #powerTip.s:before, +#powerTip.w:after, #powerTip.w:before, +#powerTip.e:after, #powerTip.e:before, +#powerTip.ne:after, #powerTip.ne:before, +#powerTip.se:after, #powerTip.se:before, +#powerTip.nw:after, #powerTip.nw:before, +#powerTip.sw:after, #powerTip.sw:before { + border: solid transparent; + content: " "; + height: 0; + width: 0; + position: absolute; +} + +#powerTip.n:after, #powerTip.s:after, +#powerTip.w:after, #powerTip.e:after, +#powerTip.nw:after, #powerTip.ne:after, +#powerTip.sw:after, #powerTip.se:after { + border-color: rgba(255, 255, 255, 0); +} + +#powerTip.n:before, #powerTip.s:before, +#powerTip.w:before, #powerTip.e:before, +#powerTip.nw:before, #powerTip.ne:before, +#powerTip.sw:before, #powerTip.se:before { + border-color: rgba(128, 128, 128, 0); +} + +#powerTip.n:after, #powerTip.n:before, +#powerTip.ne:after, #powerTip.ne:before, +#powerTip.nw:after, #powerTip.nw:before { + top: 100%; +} + +#powerTip.n:after, #powerTip.ne:after, #powerTip.nw:after { + border-top-color: var(--tooltip-arrow-background-color); + border-width: 10px; + margin: 0px -10px; +} +#powerTip.n:before, #powerTip.ne:before, #powerTip.nw:before { + border-top-color: var(--tooltip-border-color); + border-width: 11px; + margin: 0px -11px; +} +#powerTip.n:after, #powerTip.n:before { + left: 50%; +} + +#powerTip.nw:after, #powerTip.nw:before { + right: 14px; +} + +#powerTip.ne:after, #powerTip.ne:before { + left: 14px; +} + +#powerTip.s:after, #powerTip.s:before, +#powerTip.se:after, #powerTip.se:before, +#powerTip.sw:after, #powerTip.sw:before { + bottom: 100%; +} + +#powerTip.s:after, #powerTip.se:after, #powerTip.sw:after { + border-bottom-color: var(--tooltip-arrow-background-color); + border-width: 10px; + margin: 0px -10px; +} + +#powerTip.s:before, #powerTip.se:before, #powerTip.sw:before { + border-bottom-color: var(--tooltip-border-color); + border-width: 11px; + margin: 0px -11px; +} + +#powerTip.s:after, #powerTip.s:before { + left: 50%; +} + +#powerTip.sw:after, #powerTip.sw:before { + right: 14px; +} + +#powerTip.se:after, #powerTip.se:before { + left: 14px; +} + +#powerTip.e:after, #powerTip.e:before { + left: 100%; +} +#powerTip.e:after { + border-left-color: var(--tooltip-border-color); + border-width: 10px; + top: 50%; + margin-top: -10px; +} +#powerTip.e:before { + border-left-color: var(--tooltip-border-color); + border-width: 11px; + top: 50%; + margin-top: -11px; +} + +#powerTip.w:after, #powerTip.w:before { + right: 100%; +} +#powerTip.w:after { + border-right-color: var(--tooltip-border-color); + border-width: 10px; + top: 50%; + margin-top: -10px; +} +#powerTip.w:before { + border-right-color: var(--tooltip-border-color); + border-width: 11px; + top: 50%; + margin-top: -11px; +} + +@media print +{ + #top { display: none; } + #side-nav { display: none; } + #nav-path { display: none; } + body { overflow:visible; } + h1, h2, h3, h4, h5, h6 { page-break-after: avoid; } + .summary { display: none; } + .memitem { page-break-inside: avoid; } + #doc-content + { + margin-left:0 !important; + height:auto !important; + width:auto !important; + overflow:inherit; + display:inline; + } +} + +/* @group Markdown */ + +table.markdownTable { + border-collapse:collapse; + margin-top: 4px; + margin-bottom: 4px; +} + +table.markdownTable td, table.markdownTable th { + border: 1px solid var(--table-cell-border-color); + padding: 3px 7px 2px; +} + +table.markdownTable tr { +} + +th.markdownTableHeadLeft, th.markdownTableHeadRight, th.markdownTableHeadCenter, th.markdownTableHeadNone { + background-color: var(--table-header-background-color); + color: var(--table-header-foreground-color); + font-size: 110%; + padding-bottom: 4px; + padding-top: 5px; +} + +th.markdownTableHeadLeft, td.markdownTableBodyLeft { + text-align: left +} + +th.markdownTableHeadRight, td.markdownTableBodyRight { + text-align: right +} + +th.markdownTableHeadCenter, td.markdownTableBodyCenter { + text-align: center +} + +tt, code, kbd +{ + display: inline-block; +} +tt, code, kbd +{ + vertical-align: top; +} +/* @end */ + +u { + text-decoration: underline; +} + +details>summary { + list-style-type: none; +} + +details > summary::-webkit-details-marker { + display: none; +} + +details>summary::before { + content: "\25ba"; + padding-right:4px; + font-size: 80%; +} + +details[open]>summary::before { + content: "\25bc"; + padding-right:4px; + font-size: 80%; +} + +:root { + scrollbar-width: thin; + scrollbar-color: var(--scrollbar-thumb-color) var(--scrollbar-background-color); +} + +::-webkit-scrollbar { + background-color: var(--scrollbar-background-color); + height: 12px; + width: 12px; +} +::-webkit-scrollbar-thumb { + border-radius: 6px; + box-shadow: inset 0 0 12px 12px var(--scrollbar-thumb-color); + border: solid 2px transparent; +} +::-webkit-scrollbar-corner { + background-color: var(--scrollbar-background-color); +} + diff --git a/documents/html/doxygen.svg b/documents/html/doxygen.svg new file mode 100644 index 000000000..79a763540 --- /dev/null +++ b/documents/html/doxygen.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/documents/html/doxygen_crawl.html b/documents/html/doxygen_crawl.html new file mode 100644 index 000000000..084bc3a1a --- /dev/null +++ b/documents/html/doxygen_crawl.html @@ -0,0 +1,341 @@ + + + +Validator / crawler helper + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/documents/html/dynsections.js b/documents/html/dynsections.js new file mode 100644 index 000000000..d89724e8d --- /dev/null +++ b/documents/html/dynsections.js @@ -0,0 +1,198 @@ +/* + @licstart The following is the entire license notice for the JavaScript code in this file. + + The MIT License (MIT) + + Copyright (C) 1997-2020 by Dimitri van Heesch + + Permission is hereby granted, free of charge, to any person obtaining a copy of this software + and associated documentation files (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, publish, distribute, + sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or + substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING + BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + @licend The above is the entire license notice for the JavaScript code in this file + */ + +function toggleVisibility(linkObj) { + return dynsection.toggleVisibility(linkObj); +} + +let dynsection = { + // helper function + updateStripes : function() { + $('table.directory tr'). + removeClass('even').filter(':visible:even').addClass('even'); + $('table.directory tr'). + removeClass('odd').filter(':visible:odd').addClass('odd'); + }, + + toggleVisibility : function(linkObj) { + const base = $(linkObj).attr('id'); + const summary = $('#'+base+'-summary'); + const content = $('#'+base+'-content'); + const trigger = $('#'+base+'-trigger'); + const src=$(trigger).attr('src'); + if (content.is(':visible')===true) { + content.slideUp('fast'); + summary.show(); + $(linkObj).find('.arrowhead').addClass('closed').removeClass('opened'); + } else { + content.slideDown('fast'); + summary.hide(); + $(linkObj).find('.arrowhead').removeClass('closed').addClass('opened'); + } + return false; + }, + + toggleLevel : function(level) { + $('table.directory tr').each(function() { + const l = this.id.split('_').length-1; + const i = $('#img'+this.id.substring(3)); + const a = $('#arr'+this.id.substring(3)); + if (l'); + // add vertical lines to other rows + $('span[class=lineno]').not(':eq(0)').append(''); + // add toggle controls to lines with fold divs + $('div[class=foldopen]').each(function() { + // extract specific id to use + const id = $(this).attr('id').replace('foldopen',''); + // extract start and end foldable fragment attributes + const start = $(this).attr('data-start'); + const end = $(this).attr('data-end'); + // replace normal fold span with controls for the first line of a foldable fragment + $(this).find('span[class=fold]:first').replaceWith(''); + // append div for folded (closed) representation + $(this).after(''); + // extract the first line from the "open" section to represent closed content + const line = $(this).children().first().clone(); + // remove any glow that might still be active on the original line + $(line).removeClass('glow'); + if (start) { + // if line already ends with a start marker (e.g. trailing {), remove it + $(line).html($(line).html().replace(new RegExp('\\s*'+start+'\\s*$','g'),'')); + } + // replace minus with plus symbol + $(line).find('span[class=fold]').addClass('plus').removeClass('minus'); + // append ellipsis + $(line).append(' '+start+'…'+end); + // insert constructed line into closed div + $('#foldclosed'+id).html(line); + }); + }, +}; +/* @license-end */ +$(function() { + $('.code,.codeRef').each(function() { + $(this).data('powertip',$('#a'+$(this).attr('href').replace(/.*\//,'').replace(/[^a-z_A-Z0-9]/g,'_')).html()); + $.fn.powerTip.smartPlacementLists.s = [ 's', 'n', 'ne', 'se' ]; + $(this).powerTip({ placement: 's', smartPlacement: true, mouseOnToPopup: true }); + }); +}); diff --git a/documents/html/fbe_8cpp.html b/documents/html/fbe_8cpp.html new file mode 100644 index 000000000..76e059354 --- /dev/null +++ b/documents/html/fbe_8cpp.html @@ -0,0 +1,109 @@ + + + + + + + +FastBinaryEncoding: source/fbe.cpp File Reference + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+ +
fbe.cpp File Reference
+
+
+ +

Fast binary encoding implementation. +More...

+
#include "fbe.h"
+
+

Go to the source code of this file.

+ + + +

+Namespaces

namespace  FBE
+

Detailed Description

+

Fast binary encoding implementation.

+
Author
Ivan Shynkarenka
+
Date
11.04.2018
+ + +

Definition in file fbe.cpp.

+
+ + +
+ + diff --git a/documents/html/fbe_8cpp_source.html b/documents/html/fbe_8cpp_source.html new file mode 100644 index 000000000..48743e5a9 --- /dev/null +++ b/documents/html/fbe_8cpp_source.html @@ -0,0 +1,416 @@ + + + + + + + +FastBinaryEncoding: source/fbe.cpp Source File + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+
fbe.cpp
+
+
+Go to the documentation of this file.
1
+
8
+
9#include "fbe.h"
+
10
+
11namespace FBE {
+
12
+
+ +
14{
+
15 deprecated |= attributes->deprecated;
+
16 hidden |= attributes->hidden;
+
17}
+
+
18
+
+ +
20{
+
21 if (v == nullptr)
+
22 yyerror("Enum is null!");
+
23 if (v->name->empty())
+
24 yyerror("Enum name is invalid!");
+
25
+
26 // Check for duplicates
+
27 auto it = std::find_if(values.begin(), values.end(), [v](auto item)->bool { return *item->name.get() == *v->name.get(); });
+
28 if (it != values.end())
+
29 yyerror("Duplicate enum name " + *v->name.get());
+
30
+
31 values.push_back(std::shared_ptr<EnumValue>(v));
+
32}
+
+
33
+
+ +
35{
+
36 if (v == nullptr)
+
37 yyerror("Flags is null!");
+
38 if (v->name->empty())
+
39 yyerror("Flags name is invalid!");
+
40 if (!v->value || (!v->value->constant && !v->value->reference))
+
41 yyerror("Flags value is invalid!");
+
42
+
43 // Check for duplicates
+
44 auto it = std::find_if(values.begin(), values.end(), [v](auto item)->bool { return *item->name.get() == *v->name.get(); });
+
45 if (it != values.end())
+
46 yyerror("Duplicate flags name " + *v->name.get());
+
47
+
48 values.push_back(std::shared_ptr<FlagsValue>(v));
+
49}
+
+
50
+
+ +
52{
+
53 if (size <= 0)
+
54 yyerror("Array size should be greater than zero!");
+
55
+
56 N = size;
+
57}
+
+
58
+
+ +
60{
+
61 if (f == nullptr)
+
62 yyerror("Struct field is null!");
+
63 if (f->name->empty())
+
64 yyerror("Struct field name is invalid!");
+
65 if (f->type->empty())
+
66 yyerror("Struct field type is invalid!");
+
67
+
68 // Check for duplicates
+
69 auto it = std::find_if(fields.begin(), fields.end(), [f](auto item)->bool { return *item->name.get() == *f->name.get(); });
+
70 if (it != fields.end())
+
71 yyerror("Duplicate struct field name " + *f->name.get());
+
72
+
73 fields.push_back(std::shared_ptr<StructField>(f));
+
74}
+
+
75
+
+
76void StructRejects::AddReject(std::string* r, bool g)
+
77{
+
78 if (r == nullptr)
+
79 yyerror("Reject is null!");
+
80 if (r->empty())
+
81 yyerror("Reject is invalid!");
+
82
+
83 // Check for duplicates
+
84 auto it = std::find_if(rejects.begin(), rejects.end(), [r](auto item)->bool { return *item.reject.get() == *r; });
+
85 if (it != rejects.end())
+
86 yyerror("Duplicate reject " + *r);
+
87
+
88 rejects.push_back({ std::shared_ptr<std::string>(r), g });
+
89}
+
+
90
+
91int StructType::stype = 0;
+
92
+
+
93StructType::StructType(int t, bool f) : type(t), fixed(f)
+
94{
+
95 if (type < 0)
+
96 yyerror("Struct type should not be negative!");
+
97
+
98 if (!fixed)
+
99 {
+
100 if (type == 0)
+
101 type = ++stype;
+
102 else
+
103 stype = type;
+
104 }
+
105}
+
+
106
+
+ +
108{
+
109 if (st == nullptr)
+
110 yyerror("Statement is null!");
+
111
+
112 if (st->e)
+
113 AddEnum(st->e);
+
114 if (st->f)
+
115 AddFlags(st->f);
+
116 if (st->s)
+
117 AddStruct(st->s);
+
118
+
119 delete st;
+
120}
+
+
121
+
+
122void Statements::AddEnum(std::shared_ptr<EnumType>& e)
+
123{
+
124 if (e == nullptr)
+
125 yyerror("Enum is null!");
+
126 if (e->name->empty())
+
127 yyerror("Enum name is invalid!");
+
128 if (!e->body)
+
129 yyerror("Enum is empty - " + *e->name.get());
+
130
+
131 // Check for duplicates
+
132 auto it = std::find_if(enums.begin(), enums.end(), [&e](auto item)->bool { return *item->name.get() == *e->name.get(); });
+
133 if (it != enums.end())
+
134 yyerror("Duplicate enum name " + *e->name.get());
+
135
+
136 enums.push_back(e);
+
137}
+
+
138
+
+
139void Statements::AddFlags(std::shared_ptr<FlagsType>& f)
+
140{
+
141 if (f == nullptr)
+
142 yyerror("Flags is null!");
+
143 if (f->name->empty())
+
144 yyerror("Flags name is invalid!");
+
145 if (!f->body)
+
146 yyerror("Flags is empty - " + *f->name.get());
+
147
+
148 // Check for duplicates
+
149 auto it = std::find_if(flags.begin(), flags.end(), [&f](auto item)->bool { return *item->name.get() == *f->name.get(); });
+
150 if (it != flags.end())
+
151 yyerror("Duplicate flags name " + *f->name.get());
+
152
+
153 flags.push_back(f);
+
154}
+
+
155
+
+
156void Statements::AddStruct(std::shared_ptr<StructType>& s)
+
157{
+
158 if (s == nullptr)
+
159 yyerror("Struct is null!");
+
160 if (s->name->empty())
+
161 yyerror("Struct name is invalid!");
+
162 if (!s->body)
+
163 yyerror("Struct is empty - " + *s->name.get());
+
164
+
165 // Check for duplicates
+
166 auto it = std::find_if(structs.begin(), structs.end(), [&s](auto item)->bool { return *item->name.get() == *s->name.get(); });
+
167 if (it != structs.end())
+
168 yyerror("Duplicate struct name " + *s->name.get());
+
169 it = std::find_if(structs.begin(), structs.end(), [&s](auto item)->bool { return (item->type == s->type) && item->fixed && s->fixed; });
+
170 if (it != structs.end())
+
171 yyerror("Duplicate struct type " + std::to_string(s->type));
+
172
+
173 structs.push_back(s);
+
174}
+
+
175
+
+
176void Import::AddImport(std::string* i)
+
177{
+
178 if (i == nullptr)
+
179 yyerror("Import is null!");
+
180 if (i->empty())
+
181 yyerror("Import package is invalid!");
+
182
+
183 // Check for duplicates
+
184 auto it = std::find_if(imports.begin(), imports.end(), [i](auto item)->bool { return *item.get() == *i; });
+
185 if (it != imports.end())
+
186 yyerror("Duplicate import package " + *i);
+
187
+
188 imports.push_back(std::shared_ptr<std::string>(i));
+
189}
+
+
190
+
+
191Version::Version(const std::string& v)
+
192{
+
193 auto pos = v.find('.');
+
194 if (pos == v.npos)
+
195 minor = std::atoi(v.c_str());
+
196 else
+
197 {
+
198 major = std::atoi(v.substr(0, pos).c_str());
+
199 minor = std::atoi(v.substr(pos + 1).c_str());
+
200 }
+
201}
+
+
202
+
203std::shared_ptr<Package> Package::root = std::make_shared<Package>(0);
+
204
+
+ +
206{
+
207 if (offset < 0)
+
208 yyerror("Package offset should not be negative!");
+
209}
+
+
210
+
+ +
212{
+
213 if (body)
+
214 {
+
215 for (const auto& child_s : body->structs)
+
216 {
+
217 // Add offset to all structs in the package
+
218 if (!child_s->fixed)
+
219 child_s->type += offset;
+
220
+
221 // Find structs with id & key flags
+
222 if (child_s->body)
+
223 {
+
224 std::vector<std::shared_ptr<StructField>> fields;
+
225 for (const auto& field : child_s->body->fields)
+
226 {
+
227 if (field->id)
+
228 {
+
229 if (child_s->id)
+
230 yyerror("Struct " + *child_s->name.get() + " must have only one [id] field!");
+
231 child_s->id = true;
+
232 field->keys = true;
+
233 }
+
234 if (field->keys)
+
235 child_s->keys = true;
+
236 if (field->reseter)
+
237 field->optional = true;
+
238 fields.push_back(field);
+
239 if (field->reseter)
+
240 {
+
241 auto reseter = std::make_shared<StructField>();
+
242 reseter->name = std::make_shared<std::string>(*field->name + "Reset");
+
243 reseter->type = std::make_shared<std::string>("bool");
+
244 fields.push_back(reseter);
+
245 }
+
246 }
+
247 child_s->body->fields = fields;
+
248 }
+
249 }
+
250 }
+
251}
+
+
252
+
253} // namespace FBE
+
Fast binary encoding definitions.
+
int yyerror(const char *msg)
Definition fbe.l:163
+
Definition fbe.h:33
+ +
bool hidden
Definition fbe.h:38
+
void Merge(Attributes *attributes)
Definition fbe.cpp:13
+
bool deprecated
Definition fbe.h:37
+
void AddValue(EnumValue *v)
Definition fbe.cpp:19
+
std::vector< std::shared_ptr< EnumValue > > values
Definition fbe.h:58
+ +
std::shared_ptr< std::string > name
Definition fbe.h:52
+
void AddValue(FlagsValue *v)
Definition fbe.cpp:34
+
std::vector< std::shared_ptr< FlagsValue > > values
Definition fbe.h:86
+ +
std::shared_ptr< std::string > name
Definition fbe.h:80
+
std::shared_ptr< FlagsConst > value
Definition fbe.h:81
+
void AddImport(std::string *i)
Definition fbe.cpp:176
+
std::vector< std::shared_ptr< std::string > > imports
Definition fbe.h:192
+
int offset
Definition fbe.h:208
+
std::shared_ptr< Statements > body
Definition fbe.h:213
+
static std::shared_ptr< Package > root
Definition fbe.h:215
+
void initialize()
Definition fbe.cpp:211
+
Package(int o)
Definition fbe.cpp:205
+ +
std::shared_ptr< FlagsType > f
Definition fbe.h:173
+
std::shared_ptr< EnumType > e
Definition fbe.h:172
+
std::shared_ptr< StructType > s
Definition fbe.h:174
+
void AddFlags(std::shared_ptr< FlagsType > &f)
Definition fbe.cpp:139
+
std::vector< std::shared_ptr< FlagsType > > flags
Definition fbe.h:180
+
std::vector< std::shared_ptr< StructType > > structs
Definition fbe.h:181
+
void AddEnum(std::shared_ptr< EnumType > &e)
Definition fbe.cpp:122
+
std::vector< std::shared_ptr< EnumType > > enums
Definition fbe.h:179
+
void AddStruct(std::shared_ptr< StructType > &s)
Definition fbe.cpp:156
+
void AddStatement(Statement *st)
Definition fbe.cpp:107
+
void AddField(StructField *field)
Definition fbe.cpp:59
+
std::vector< std::shared_ptr< StructField > > fields
Definition fbe.h:123
+ +
void SetArraySize(int size)
Definition fbe.cpp:51
+ +
std::shared_ptr< std::string > name
Definition fbe.h:102
+
std::shared_ptr< std::string > type
Definition fbe.h:104
+
void AddReject(std::string *r, bool g)
Definition fbe.cpp:76
+
std::vector< StructReject > rejects
Definition fbe.h:145
+
static int stype
Definition fbe.h:165
+
bool fixed
Definition fbe.h:153
+
StructType(int t, bool f)
Definition fbe.cpp:93
+ +
int minor
Definition fbe.h:200
+
int major
Definition fbe.h:199
+
Version()=default
+
+ + +
+ + diff --git a/documents/html/fbe_8h.html b/documents/html/fbe_8h.html new file mode 100644 index 000000000..7ca154f6a --- /dev/null +++ b/documents/html/fbe_8h.html @@ -0,0 +1,193 @@ + + + + + + + +FastBinaryEncoding: include/fbe.h File Reference + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+ +
fbe.h File Reference
+
+
+ +

Fast binary encoding definitions. +More...

+
#include "version.h"
+#include "filesystem/directory.h"
+#include "filesystem/file.h"
+#include "string/string_utils.h"
+#include "system/environment.h"
+#include "system/stream.h"
+#include "threads/file_lock.h"
+#include "threads/thread.h"
+#include <algorithm>
+#include <cstdint>
+#include <memory>
+#include <regex>
+#include <set>
+#include <string>
+#include <vector>
+
+

Go to the source code of this file.

+ + + + + + + + + + + + + + + + + + + + + + + +

+Classes

struct  FBE::Attributes
struct  FBE::EnumConst
struct  FBE::EnumValue
struct  FBE::EnumBody
struct  FBE::EnumType
struct  FBE::FlagsConst
struct  FBE::FlagsValue
struct  FBE::FlagsBody
struct  FBE::FlagsType
struct  FBE::StructField
struct  FBE::StructBody
struct  FBE::StructRequest
struct  FBE::StructResponse
struct  FBE::StructReject
struct  FBE::StructRejects
struct  FBE::StructType
struct  FBE::Statement
struct  FBE::Statements
struct  FBE::Import
struct  FBE::Version
struct  FBE::Package
+ + +

+Namespaces

namespace  FBE
+ + + +

+Functions

int yyerror (const char *msg)
int yyerror (const std::string &msg)
+

Detailed Description

+

Fast binary encoding definitions.

+
Author
Ivan Shynkarenka
+
Date
11.04.2018
+ + +

Definition in file fbe.h.

+

Function Documentation

+ +

◆ yyerror() [1/2]

+ +
+
+ + + + + + + +
int yyerror (const char * msg)
+
+ +

Definition at line 163 of file fbe.l.

+ +
+
+ +

◆ yyerror() [2/2]

+ +
+
+ + + + + + + +
int yyerror (const std::string & msg)
+
+ +

Definition at line 174 of file fbe.l.

+ +
+
+
+ + +
+ + diff --git a/documents/html/fbe_8h_source.html b/documents/html/fbe_8h_source.html new file mode 100644 index 000000000..b232b55bc --- /dev/null +++ b/documents/html/fbe_8h_source.html @@ -0,0 +1,456 @@ + + + + + + + +FastBinaryEncoding: include/fbe.h Source File + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+
fbe.h
+
+
+Go to the documentation of this file.
1
+
8
+
9#ifndef FBE_H
+
10#define FBE_H
+
11
+
12#include "version.h"
+
13
+
14#include "filesystem/directory.h"
+
15#include "filesystem/file.h"
+
16#include "string/string_utils.h"
+
17#include "system/environment.h"
+
18#include "system/stream.h"
+
19#include "threads/file_lock.h"
+
20#include "threads/thread.h"
+
21
+
22#include <algorithm>
+
23#include <cstdint>
+
24#include <memory>
+
25#include <regex>
+
26#include <set>
+
27#include <string>
+
28#include <vector>
+
29
+
30int yyerror(const char* msg);
+
31int yyerror(const std::string& msg);
+
32
+
+
33namespace FBE {
+
34
+
+ +
36{
+
37 bool deprecated{false};
+
38 bool hidden{false};
+
39
+
40 void Merge(Attributes* attributes);
+
41};
+
+
42
+
+ +
44{
+
45 std::shared_ptr<std::string> constant;
+
46 std::shared_ptr<std::string> reference;
+
47};
+
+
48
+
+ +
50{
+
51 std::shared_ptr<Attributes> attributes;
+
52 std::shared_ptr<std::string> name;
+
53 std::shared_ptr<EnumConst> value;
+
54};
+
+
55
+
+ +
57{
+
58 std::vector<std::shared_ptr<EnumValue>> values;
+
59
+
60 void AddValue(EnumValue* v);
+
61};
+
+
62
+
+ +
64{
+
65 std::shared_ptr<Attributes> attributes;
+
66 std::shared_ptr<std::string> name;
+
67 std::shared_ptr<std::string> base;
+
68 std::shared_ptr<EnumBody> body;
+
69};
+
+
70
+
+ +
72{
+
73 std::shared_ptr<std::string> constant;
+
74 std::shared_ptr<std::string> reference;
+
75};
+
+
76
+
+ +
78{
+
79 std::shared_ptr<Attributes> attributes;
+
80 std::shared_ptr<std::string> name;
+
81 std::shared_ptr<FlagsConst> value;
+
82};
+
+
83
+
+ +
85{
+
86 std::vector<std::shared_ptr<FlagsValue>> values;
+
87
+
88 void AddValue(FlagsValue* v);
+
89};
+
+
90
+
+ +
92{
+
93 std::shared_ptr<Attributes> attributes;
+
94 std::shared_ptr<std::string> name;
+
95 std::shared_ptr<std::string> base;
+
96 std::shared_ptr<FlagsBody> body;
+
97};
+
+
98
+
+ +
100{
+
101 std::shared_ptr<Attributes> attributes;
+
102 std::shared_ptr<std::string> name;
+
103 std::shared_ptr<std::string> key;
+
104 std::shared_ptr<std::string> type;
+
105 std::shared_ptr<std::string> value;
+
106 bool id{false};
+
107 bool keys{false};
+
108 bool optional{false};
+
109 bool reseter{false};
+
110 bool array{false};
+
111 bool vector{false};
+
112 bool list{false};
+
113 bool set{false};
+
114 bool map{false};
+
115 bool hash{false};
+
116 int N{0};
+
117
+
118 void SetArraySize(int size);
+
119};
+
+
120
+
+ +
122{
+
123 std::vector<std::shared_ptr<StructField>> fields;
+
124
+
125 void AddField(StructField* field);
+
126};
+
+
127
+
+ +
129{
+
130};
+
+
131
+
+ +
133{
+
134 std::shared_ptr<std::string> response;
+
135};
+
+
136
+
+ +
138{
+
139 std::shared_ptr<std::string> reject;
+
140 bool global;
+
141};
+
+
142
+
+ +
144{
+
145 std::vector<StructReject> rejects;
+
146
+
147 void AddReject(std::string* r, bool g);
+
148};
+
+
149
+
+ +
151{
+
152 int type;
+
153 bool fixed;
+
154 bool id{false};
+
155 bool keys{false};
+
156 bool message{false};
+
157 std::shared_ptr<Attributes> attributes;
+
158 std::shared_ptr<std::string> name;
+
159 std::shared_ptr<std::string> base;
+
160 std::shared_ptr<StructRequest> request;
+
161 std::shared_ptr<StructResponse> response;
+
162 std::shared_ptr<StructRejects> rejects;
+
163 std::shared_ptr<StructBody> body;
+
164
+
165 static int stype;
+
166
+
167 StructType(int t, bool f);
+
168};
+
+
169
+
+ +
171{
+
172 std::shared_ptr<EnumType> e;
+
173 std::shared_ptr<FlagsType> f;
+
174 std::shared_ptr<StructType> s;
+
175};
+
+
176
+
+ +
178{
+
179 std::vector<std::shared_ptr<EnumType>> enums;
+
180 std::vector<std::shared_ptr<FlagsType>> flags;
+
181 std::vector<std::shared_ptr<StructType>> structs;
+
182
+
183 void AddStatement(Statement* st);
+
184
+
185 void AddEnum(std::shared_ptr<EnumType>& e);
+
186 void AddFlags(std::shared_ptr<FlagsType>& f);
+
187 void AddStruct(std::shared_ptr<StructType>& s);
+
188};
+
+
189
+
+
190struct Import
+
191{
+
192 std::vector<std::shared_ptr<std::string>> imports;
+
193
+
194 void AddImport(std::string* i);
+
195};
+
+
196
+
+ +
198{
+
199 int major{0};
+
200 int minor{0};
+
201
+
202 Version() = default;
+
203 Version(const std::string& v);
+
204};
+
+
205
+
+ +
207{
+ +
209 std::shared_ptr<std::string> domain;
+
210 std::shared_ptr<std::string> name;
+
211 std::shared_ptr<Import> import;
+
212 std::shared_ptr<Version> version;
+
213 std::shared_ptr<Statements> body;
+
214
+
215 static std::shared_ptr<Package> root;
+
216
+
217 Package(int o);
+
218
+
219 void initialize();
+
220};
+
+
221
+
222} // namespace FBE
+
+
223
+
224#endif // FBE_H
+
int yyerror(const char *msg)
Definition fbe.l:163
+
Definition fbe.h:33
+ +
bool hidden
Definition fbe.h:38
+
void Merge(Attributes *attributes)
Definition fbe.cpp:13
+
bool deprecated
Definition fbe.h:37
+ +
void AddValue(EnumValue *v)
Definition fbe.cpp:19
+
std::vector< std::shared_ptr< EnumValue > > values
Definition fbe.h:58
+ +
std::shared_ptr< std::string > constant
Definition fbe.h:45
+
std::shared_ptr< std::string > reference
Definition fbe.h:46
+ +
std::shared_ptr< std::string > name
Definition fbe.h:66
+
std::shared_ptr< Attributes > attributes
Definition fbe.h:65
+
std::shared_ptr< std::string > base
Definition fbe.h:67
+
std::shared_ptr< EnumBody > body
Definition fbe.h:68
+ +
std::shared_ptr< EnumConst > value
Definition fbe.h:53
+
std::shared_ptr< std::string > name
Definition fbe.h:52
+
std::shared_ptr< Attributes > attributes
Definition fbe.h:51
+ +
void AddValue(FlagsValue *v)
Definition fbe.cpp:34
+
std::vector< std::shared_ptr< FlagsValue > > values
Definition fbe.h:86
+ +
std::shared_ptr< std::string > reference
Definition fbe.h:74
+
std::shared_ptr< std::string > constant
Definition fbe.h:73
+ +
std::shared_ptr< FlagsBody > body
Definition fbe.h:96
+
std::shared_ptr< std::string > name
Definition fbe.h:94
+
std::shared_ptr< std::string > base
Definition fbe.h:95
+
std::shared_ptr< Attributes > attributes
Definition fbe.h:93
+ +
std::shared_ptr< Attributes > attributes
Definition fbe.h:79
+
std::shared_ptr< std::string > name
Definition fbe.h:80
+
std::shared_ptr< FlagsConst > value
Definition fbe.h:81
+ +
void AddImport(std::string *i)
Definition fbe.cpp:176
+
std::vector< std::shared_ptr< std::string > > imports
Definition fbe.h:192
+
int offset
Definition fbe.h:208
+
std::shared_ptr< Version > version
Definition fbe.h:212
+
std::shared_ptr< std::string > domain
Definition fbe.h:209
+
std::shared_ptr< Statements > body
Definition fbe.h:213
+
static std::shared_ptr< Package > root
Definition fbe.h:215
+
void initialize()
Definition fbe.cpp:211
+
Package(int o)
Definition fbe.cpp:205
+
std::shared_ptr< std::string > name
Definition fbe.h:210
+ +
std::shared_ptr< FlagsType > f
Definition fbe.h:173
+
std::shared_ptr< EnumType > e
Definition fbe.h:172
+
std::shared_ptr< StructType > s
Definition fbe.h:174
+ +
void AddFlags(std::shared_ptr< FlagsType > &f)
Definition fbe.cpp:139
+
std::vector< std::shared_ptr< FlagsType > > flags
Definition fbe.h:180
+
std::vector< std::shared_ptr< StructType > > structs
Definition fbe.h:181
+
void AddEnum(std::shared_ptr< EnumType > &e)
Definition fbe.cpp:122
+
std::vector< std::shared_ptr< EnumType > > enums
Definition fbe.h:179
+
void AddStruct(std::shared_ptr< StructType > &s)
Definition fbe.cpp:156
+
void AddStatement(Statement *st)
Definition fbe.cpp:107
+ +
void AddField(StructField *field)
Definition fbe.cpp:59
+
std::vector< std::shared_ptr< StructField > > fields
Definition fbe.h:123
+ + +
bool reseter
Definition fbe.h:109
+
std::shared_ptr< std::string > key
Definition fbe.h:103
+ +
void SetArraySize(int size)
Definition fbe.cpp:51
+ +
bool vector
Definition fbe.h:111
+ + +
bool optional
Definition fbe.h:108
+
std::shared_ptr< std::string > name
Definition fbe.h:102
+ +
std::shared_ptr< std::string > type
Definition fbe.h:104
+
std::shared_ptr< Attributes > attributes
Definition fbe.h:101
+
std::shared_ptr< std::string > value
Definition fbe.h:105
+ + + +
std::shared_ptr< std::string > reject
Definition fbe.h:139
+ +
void AddReject(std::string *r, bool g)
Definition fbe.cpp:76
+
std::vector< StructReject > rejects
Definition fbe.h:145
+ + +
std::shared_ptr< std::string > response
Definition fbe.h:134
+
static int stype
Definition fbe.h:165
+
std::shared_ptr< StructResponse > response
Definition fbe.h:161
+
std::shared_ptr< Attributes > attributes
Definition fbe.h:157
+
std::shared_ptr< StructBody > body
Definition fbe.h:163
+
std::shared_ptr< std::string > base
Definition fbe.h:159
+
std::shared_ptr< StructRequest > request
Definition fbe.h:160
+
bool fixed
Definition fbe.h:153
+
StructType(int t, bool f)
Definition fbe.cpp:93
+
std::shared_ptr< std::string > name
Definition fbe.h:158
+
std::shared_ptr< StructRejects > rejects
Definition fbe.h:162
+
bool message
Definition fbe.h:156
+ +
bool keys
Definition fbe.h:155
+
int minor
Definition fbe.h:200
+
int major
Definition fbe.h:199
+
Version()=default
+
Version definition.
+
+ + +
+ + diff --git a/documents/html/fbe_8l.html b/documents/html/fbe_8l.html new file mode 100644 index 000000000..6bac9b014 --- /dev/null +++ b/documents/html/fbe_8l.html @@ -0,0 +1,356 @@ + + + + + + + +FastBinaryEncoding: source/fbe.l File Reference + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+ +
fbe.l File Reference
+
+
+
#include "fbe.h"
+#include "fbe-parser.hpp"
+#include "generator_cpp.h"
+#include "generator_csharp.h"
+#include "generator_go.h"
+#include "generator_java.h"
+#include "generator_javascript.h"
+#include "generator_kotlin.h"
+#include "generator_python.h"
+#include "generator_ruby.h"
+#include "generator_swift.h"
+#include <OptionParser.h>
+
+

Go to the source code of this file.

+ + + + + + + + + + + +

+Functions

void yycount ()
int yychar (char c)
int yytoken (int t)
int yystring (int s)
int yyerror (const char *msg)
int yyerror (const std::string &msg)
int yylex (void)
int yyparse ()
int main (int argc, char **argv)
+ + + + +

+Variables

int yycolumn = 0
std::string yyfile
std::string yyline
+

Function Documentation

+ +

◆ main()

+ +
+
+ + + + + + + + + + + +
int main (int argc,
char ** argv )
+
+ +

Definition at line 181 of file fbe.l.

+ +
+
+ +

◆ yychar()

+ +
+
+ + + + + + + +
int yychar (char c)
+
+ +

Definition at line 146 of file fbe.l.

+ +
+
+ +

◆ yycount()

+ +
+
+ + + + + + + +
void yycount ()
+
+ +

Definition at line 129 of file fbe.l.

+ +
+
+ +

◆ yyerror() [1/2]

+ +
+
+ + + + + + + +
int yyerror (const char * msg)
+
+ +

Definition at line 163 of file fbe.l.

+ +
+
+ +

◆ yyerror() [2/2]

+ +
+
+ + + + + + + +
int yyerror (const std::string & msg)
+
+ +

Definition at line 174 of file fbe.l.

+ +
+
+ +

◆ yylex()

+ +
+
+ + + + + + + +
int yylex (void )
+
+ +

Definition at line 36 of file fbe.l.

+ +
+
+ +

◆ yyparse()

+ +
+
+ + + + + +
+ + + + + + + +
int yyparse ()
+
+extern
+
+ +
+
+ +

◆ yystring()

+ +
+
+ + + + + + + +
int yystring (int s)
+
+ +

Definition at line 157 of file fbe.l.

+ +
+
+ +

◆ yytoken()

+ +
+
+ + + + + + + +
int yytoken (int t)
+
+ +

Definition at line 151 of file fbe.l.

+ +
+
+

Variable Documentation

+ +

◆ yycolumn

+ +
+
+ + + + +
int yycolumn = 0
+
+ +

Definition at line 125 of file fbe.l.

+ +
+
+ +

◆ yyfile

+ +
+
+ + + + +
std::string yyfile
+
+ +

Definition at line 126 of file fbe.l.

+ +
+
+ +

◆ yyline

+ +
+
+ + + + +
std::string yyline
+
+ +

Definition at line 127 of file fbe.l.

+ +
+
+
+ + +
+ + diff --git a/documents/html/fbe_8l_source.html b/documents/html/fbe_8l_source.html new file mode 100644 index 000000000..b065fa345 --- /dev/null +++ b/documents/html/fbe_8l_source.html @@ -0,0 +1,493 @@ + + + + + + + +FastBinaryEncoding: source/fbe.l Source File + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+
fbe.l
+
+
+Go to the documentation of this file.
-1D [0-9]
+
0L [a-zA-Z_]
+
1H [a-fA-F0-9]
+
2E [Ee][+-]?{D}+
+
3
+
4%{
+
5
+
6#include "fbe.h"
+
7#include "fbe-parser.hpp"
+
8#include "generator_cpp.h"
+
9#include "generator_csharp.h"
+
10#include "generator_go.h"
+
11#include "generator_java.h"
+ +
13#include "generator_kotlin.h"
+
14#include "generator_python.h"
+
15#include "generator_ruby.h"
+
16#include "generator_swift.h"
+
17
+
18#include <OptionParser.h>
+
19
+
20void yycount();
+
21int yychar(char c);
+
22int yytoken(int t);
+
23int yystring(int s);
+
24int yyerror(const char* msg);
+
25int yyerror(const std::string& msg);
+
26
+
Fast binary encoding definitions.
+
void yycount()
Definition fbe.l:129
+
int yytoken(int t)
Definition fbe.l:151
+
int yyerror(const char *msg)
Definition fbe.l:163
+
int yychar(char c)
Definition fbe.l:146
+
int yystring(int s)
Definition fbe.l:157
+
Fast binary encoding C++ generator definition.
+
Fast binary encoding C# generator definition.
+
Fast binary encoding Go generator definition.
+
Fast binary encoding Java generator definition.
+
Fast binary encoding JavaScript generator definition.
+
Fast binary encoding Kotlin generator definition.
+
Fast binary encoding Python generator definition.
+
Fast binary encoding Ruby generator definition.
+
Fast binary encoding Kotlin generator definition.
+
27%}
+
28
+
29%option noinput
+
30%option nounput
+
31%option noyywrap
+
32%option yylineno
+
33
+
34%%
+
35
+
36"//"[^\n]* { /* Single line comment */ }
+
37"/*"[^*]*|[*]*"*/" { /* Multilines comment */ }
+
38
+
39"domain" { yycount(); return yytoken(PDOMAIN); }
+
40"package" { yycount(); return yytoken(PACKAGE); }
+
41"offset" { yycount(); return yytoken(OFFSET); }
+
42"import" { yycount(); return yytoken(IMPORT); }
+
43"version" { yycount(); return yytoken(VERSION); }
+
44"enum" { yycount(); return yytoken(ENUM); }
+
45"flags" { yycount(); return yytoken(FLAGS); }
+
46"struct" { yycount(); return yytoken(STRUCT); }
+
47"message" { yycount(); return yytoken(MESSAGE); }
+
48"base" { yycount(); return yytoken(BASE); }
+
49"[id]" { yycount(); return yytoken(ID); }
+
50"[key]" { yycount(); return yytoken(KEY); }
+
51"[hidden]" { yycount(); return yytoken(HIDDEN); }
+
52"[deprecated]" { yycount(); return yytoken(DEPRECATED); }
+
53"request" { yycount(); return yytoken(REQ); }
+
54"response" { yycount(); return yytoken(RES); }
+
55"reject" { yycount(); return yytoken(REJ); }
+
56
+
57"bool" { yycount(); return yystring(BOOL); }
+
58"byte" { yycount(); return yystring(BYTE); }
+
59"bytes" { yycount(); return yystring(BYTES); }
+
60"char" { yycount(); return yystring(CHAR); }
+
61"wchar" { yycount(); return yystring(WCHAR); }
+
62"int8" { yycount(); return yystring(INT8); }
+
63"uint8" { yycount(); return yystring(UINT8); }
+
64"int16" { yycount(); return yystring(INT16); }
+
65"uint16" { yycount(); return yystring(UINT16); }
+
66"int32" { yycount(); return yystring(INT32); }
+
67"uint32" { yycount(); return yystring(UINT32); }
+
68"int64" { yycount(); return yystring(INT64); }
+
69"uint64" { yycount(); return yystring(UINT64); }
+
70"float" { yycount(); return yystring(FLOAT); }
+
71"double" { yycount(); return yystring(DOUBLE); }
+
72"decimal" { yycount(); return yystring(DECIMAL); }
+
73"string" { yycount(); return yystring(STRING); }
+
74"timestamp" { yycount(); return yystring(TIMESTAMP); }
+
75"uuid" { yycount(); return yystring(UUID); }
+
76
+
77"true" { yycount(); return yystring(CONST_TRUE); }
+
78"false" { yycount(); return yystring(CONST_FALSE); }
+
79"null" { yycount(); return yystring(CONST_NULL); }
+
80"epoch" { yycount(); return yystring(CONST_EPOCH); }
+
81"utc" { yycount(); return yystring(CONST_UTC); }
+
82"uuid0" { yycount(); return yystring(CONST_UUID0); }
+
83"uuid1" { yycount(); return yystring(CONST_UUID1); }
+
84"uuid4" { yycount(); return yystring(CONST_UUID4); }
+
85
+
86'(\\.|[^\\'])+' { yycount(); return yystring(CONST_CHAR); }
+
87[-]?0[xX]{H}+ { yycount(); return yystring(CONST_INT); }
+
88[-]?0{D}+ { yycount(); return yystring(CONST_INT); }
+
89[-]?{D}+ { yycount(); return yystring(CONST_INT); }
+
90[-]?{D}+{E} { yycount(); return yystring(CONST_FLOAT); }
+
91[-]?{D}*"."{D}+({E})? { yycount(); return yystring(CONST_FLOAT); }
+
92[-]?{D}+"."{D}*({E})? { yycount(); return yystring(CONST_FLOAT); }
+
93\"(\\.|[^\\"\n])*\" { yycount(); return yystring(CONST_STRING); }
+
94
+
95{L}({L}|{D})* { yycount(); return yystring(IDENTIFIER); }
+
96
+
97"," { yycount(); return yychar(','); }
+
98"." { yycount(); return yychar('.'); }
+
99":" { yycount(); return yychar(':'); }
+
100";" { yycount(); return yychar(';'); }
+
101"+" { yycount(); return yychar('+'); }
+
102"*" { yycount(); return yychar('*'); }
+
103"=" { yycount(); return yychar('='); }
+
104"|" { yycount(); return yychar('|'); }
+
105"!" { yycount(); return yychar('!'); }
+
106"?" { yycount(); return yychar('?'); }
+
107"~" { yycount(); return yychar('~'); }
+
108"(" { yycount(); return yychar('('); }
+
109")" { yycount(); return yychar(')'); }
+
110"[" { yycount(); return yychar('['); }
+
111"]" { yycount(); return yychar(']'); }
+
112"<" { yycount(); return yychar('<'); }
+
113">" { yycount(); return yychar('>'); }
+
114"{" { yycount(); return yychar('{'); }
+
115"}" { yycount(); return yychar('}'); }
+
116
+
117[ \t\n\r\b\v\f] { yycount(); }
+
118
+
119. { yycount(); yyerror("Unknown token!"); }
+
int yyerror(const char *msg)
Definition fbe.l:163
+
120
+
121%%
+
122
+
123int yycolumn = 0;
+
124std::string yyfile;
+
125std::string yyline;
+ + +
128{
+
+
129 for (int i = 0; yytext[i] != '\0'; ++i)
+
130 {
+
131 yyline += yytext[i];
+
132 if (yytext[i] == '\n')
+
133 {
+
134 yycolumn = 0;
+
135 yyline.clear();
+
136 }
+
137 else if (yytext[i] == '\t')
+
138 yycolumn += 8 - (yycolumn % 8);
+
139 else
+
140 ++yycolumn;
+
141 }
+
142}
+
143
+
144int yychar(char c)
+
+
145{
+
+
146 return c;
+
147}
+
148
+
149int yytoken(int t)
+
+
150{
+
+
151 yylval.token = t;
+
152 return t;
+
153}
+
154
+
155int yystring(int s)
+
+
156{
+
+
157 yylval.string = new std::string(yytext, yyleng);
+
158 return s;
+
159}
+
160
+
161int yyerror(const char* msg)
+
+
162{
+
+
163 if (yyfile.empty())
+
164 yyfile = "<stdin>";
+
165 fprintf(stderr, "\n%s:%d: error: %s\n", yyfile.c_str(), yylineno, msg);
+
166 fprintf(stderr, "%s\n", yyline.c_str());
+
167 fprintf(stderr, "%*s--- %s\n", yycolumn, "^", msg);
+
168 yyterminate();
+
169 return -1;
+
170}
+
171
+
172int yyerror(const std::string& msg)
+
+
173{
+
+
174 return yyerror(msg.c_str());
+
175}
+
176
+
177extern int yyparse();
+
+
178
+
179int main(int argc, char** argv)
+
180{
+
+
181 auto parser = optparse::OptionParser().version(FBE::version);
+
182
+
183 parser.add_option("-i", "--input").dest("input").help("Input path");
+
184 parser.add_option("-o", "--output").dest("output").help("Output path");
+
185 parser.add_option("-q", "--quiet").dest("quiet").action("store_true").help("Launch in quiet mode. No progress will be shown!");
+
186 parser.add_option("-n", "--indent").dest("indent").action("store").type("int").set_default(0).help("Format indent. Default: %default");
+
187 parser.add_option("-t", "--tabs").dest("tabs").action("store_true").set_default(0).help("Format with tabs. Default: off");
+
188 parser.add_option("--cpp").dest("cpp").action("store_true").set_default(0).help("Generate C++ code");
+
189 parser.add_option("--cpp-logging").dest("cpp-logging").action("store_true").set_default(0).help("Generate C++ logging code");
+
190 parser.add_option("--csharp").dest("csharp").action("store_true").set_default(0).help("Generate C# code");
+
191 parser.add_option("--go").dest("go").action("store_true").set_default(0).help("Generate Go code");
+
192 parser.add_option("--java7").dest("java7").action("store_true").set_default(0).help("Generate Java code (old Java 7 for Android)");
+
193 parser.add_option("--java").dest("java").action("store_true").set_default(0).help("Generate Java code");
+
194 parser.add_option("--javascript").dest("javascript").action("store_true").set_default(0).help("Generate JavaScript code");
+
195 parser.add_option("--kotlin7").dest("kotlin7").action("store_true").set_default(0).help("Generate Kotlin code (old Java 7 for Android)");
+
196 parser.add_option("--kotlin").dest("kotlin").action("store_true").set_default(0).help("Generate Kotlin code");
+
197 parser.add_option("--python").dest("python").action("store_true").set_default(0).help("Generate Python code");
+
198 parser.add_option("--ruby").dest("ruby").action("store_true").set_default(0).help("Generate Ruby code");
+
199 parser.add_option("--swift").dest("swift").action("store_true").set_default(0).help("Generate Swift code");
+
200 parser.add_option("--final").dest("final").action("store_true").set_default(0).help("Generate Final serialization code");
+
201 parser.add_option("--json").dest("json").action("store_true").set_default(0).help("Generate JSON serialization code");
+
202 parser.add_option("--proto").dest("proto").action("store_true").set_default(0).help("Generate Sender/Receiver protocol code");
+
203
+
204 optparse::Values options = parser.parse_args(argc, argv);
+
205
+
206 // Print help
+
207 if (options.get("help"))
+
208 {
+
209 parser.print_help();
+
210 return 0;
+
211 }
+
212
+
213 // Client parameters
+
214 std::string directory;
+
215 std::string input(options.get("input"));
+
216 std::string output(options.get("output"));
+
217 int indent = options.get("indent");
+
218 bool tabs = options.get("tabs");
+
219 bool quiet = options.get("quiet");
+
220 bool cpp = options.get("cpp");
+
221 bool cpp_logging = options.get("cpp-logging");
+
222 bool csharp = options.get("csharp");
+
223 bool go = options.get("go");
+
224 bool java = options.get("java");
+
225 bool java7 = options.get("java7");
+
226 bool javascript = options.get("javascript");
+
227 bool kotlin = options.get("kotlin");
+
228 bool kotlin7 = options.get("kotlin7");
+
229 bool python = options.get("python");
+
230 bool ruby = options.get("ruby");
+
231 bool swift = options.get("swift");
+
232 bool final = options.get("final");
+
233 bool json = options.get("json");
+
234 bool proto = options.get("proto");
+
235 char space = tabs ? '\t' : ' ';
+
236
+
237 // Check for the input path
+
238 if (input.empty())
+
239 {
+
240 std::cerr << "Input path is not provided!" << std::endl;
+
241 parser.print_help();
+
242 return -1;
+
243 }
+
244
+
245 // Check for the output path
+
246 if (output.empty())
+
247 {
+
248 std::cerr << "Output path is not provided!" << std::endl;
+
249 parser.print_help();
+
250 return -1;
+
251 }
+
252
+
253 // Open the input file
+
254 if (!quiet) std::cout << "Open input file - " + input + "...";
+
255
+
256 CppCommon::File file(input);
+
257
+
258 // Check if the input file exist
+
259 if (!file.IsFileExists())
+
260 yyerror("Input file not exist - " + input);
+
261
+
262 // Decompose the parent directory
+
263 directory = file.parent().string();
+
264
+
265 // Open the input file
+
266 FILE* in = fopen(input.c_str(), "r");
+
267
+
268 // Setup the lexical parser input
+
269 yyfile = input;
+
270 yyset_in(in);
+
271
+
272 if (!quiet) std::cout << "Done!" << std::endl;
+
273
+
274 // Parse the input
+
275 if (!quiet) std::cout << "Parsing input...";
+
276 yyparse();
+
277 if (!quiet) std::cout << "Done!" << std::endl;
+
278
+
279 // Close the input file
+
280 if (!input.empty())
+
281 {
+
282 if (!quiet) std::cout << "Close input file...";
+
283 fclose(yyget_in());
+
284 if (!quiet) std::cout << "Done!" << std::endl;
+
285 }
+
286
+
287 // Generate the output
+
288 if (cpp)
+
289 {
+
290 if (!quiet) std::cout << "Generating C++ code...";
+
291 FBE::GeneratorCpp(input, output, (indent ? indent : 4), space).Final(final).JSON(json).Proto(proto).Logging(cpp_logging).Generate(FBE::Package::root);
+
292 if (!quiet) std::cout << "Done!" << std::endl;
+
293 }
+
294 if (csharp)
+
295 {
+
296 if (!quiet) std::cout << "Generating C# code...";
+
297 FBE::GeneratorCSharp(input, output, (indent ? indent : 4), space).Final(final).JSON(json).Proto(proto).Generate(FBE::Package::root);
+
298 if (!quiet) std::cout << "Done!" << std::endl;
+
299 }
+
300 if (go)
+
301 {
+
302 if (!quiet) std::cout << "Generating Go code...";
+
303 FBE::GeneratorGo(input, output, (indent ? indent : 4), space).Final(final).JSON(json).Proto(proto).Generate(FBE::Package::root);
+
304 if (!quiet) std::cout << "Done!" << std::endl;
+
305 }
+
306 if (java || java7)
+
307 {
+
308 if (!quiet) std::cout << "Generating Java code...";
+
309 FBE::GeneratorJava(input, output, (indent ? indent : 4), space).Final(final).JSON(json).Proto(proto).Version(java7 ? 7 : 8).Generate(FBE::Package::root);
+
310 if (!quiet) std::cout << "Done!" << std::endl;
+
311 }
+
312 if (javascript)
+
313 {
+
314 if (!quiet) std::cout << "Generating JavaScript code...";
+
315 FBE::GeneratorJavaScript(input, output, (indent ? indent : 2), space).Final(final).JSON(json).Proto(proto).Generate(FBE::Package::root);
+
316 if (!quiet) std::cout << "Done!" << std::endl;
+
317 }
+
318 if (kotlin || kotlin7)
+
319 {
+
320 if (!quiet) std::cout << "Generating Kotlin code...";
+
321 FBE::GeneratorKotlin(input, output, (indent ? indent : 4), space).Final(final).JSON(json).Proto(proto).Version(kotlin7 ? 7 : 8).Generate(FBE::Package::root);
+
322 if (!quiet) std::cout << "Done!" << std::endl;
+
323 }
+
324 if (python)
+
325 {
+
326 if (!quiet) std::cout << "Generating Python code...";
+
327 FBE::GeneratorPython(input, output, (indent ? indent : 4), space).Final(final).JSON(json).Proto(proto).Generate(FBE::Package::root);
+
328 if (!quiet) std::cout << "Done!" << std::endl;
+
329 }
+
330 if (ruby)
+
331 {
+
332 if (!quiet) std::cout << "Generating Ruby code...";
+
333 FBE::GeneratorRuby(input, output, (indent ? indent : 2), space).Final(final).JSON(json).Proto(proto).Generate(FBE::Package::root);
+
334 if (!quiet) std::cout << "Done!" << std::endl;
+
335 }
+
336 if (swift)
+
337 {
+
338 if (!quiet) std::cout << "Generating Swift code...";
+
339 FBE::GeneratorSwift(input, output, (indent ? indent : 4), space).Final(final).JSON(json).Proto(proto).Generate(FBE::Package::root);
+
340 if (!quiet) std::cout << "Done!" << std::endl;
+
341 }
+
342
+
343 // Destroy the lexical parser
+
344 yylex_destroy();
+
345
+
346 return 0;
+
347}
+
+ +
bool Final() const noexcept
+ +
bool Final() const noexcept
+ +
bool Final() const noexcept
+ +
bool Final() const noexcept
+ +
bool Final() const noexcept
+ +
bool Final() const noexcept
+ +
bool Final() const noexcept
+ +
bool Final() const noexcept
+ +
bool Final() const noexcept
+
int main(int argc, char **argv)
Definition fbe.l:181
+
std::string yyfile
Definition fbe.l:126
+
std::string yyline
Definition fbe.l:127
+
int yyparse()
+
int yycolumn
Definition fbe.l:125
+
const char version[]
Definition version.h:15
+
static std::shared_ptr< Package > root
Definition fbe.h:215
+
+ + +
+ + diff --git a/documents/html/files.html b/documents/html/files.html new file mode 100644 index 000000000..5830e1a62 --- /dev/null +++ b/documents/html/files.html @@ -0,0 +1,116 @@ + + + + + + + +FastBinaryEncoding: File List + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + +
+
+ +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
File List
+
+
+
Here is a list of all files with brief descriptions:
+
[detail level 12]
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
 
include
 
fbe.h
Fast binary encoding definitions
 
generator.h
Fast binary encoding generator definition
 
generator.inl
Fast binary encoding generator inline implementation
 
generator_cpp.h
Fast binary encoding C++ generator definition
 
generator_csharp.h
Fast binary encoding C# generator definition
 
generator_go.h
Fast binary encoding Go generator definition
 
generator_java.h
Fast binary encoding Java generator definition
 
generator_javascript.h
Fast binary encoding JavaScript generator definition
 
generator_kotlin.h
Fast binary encoding Kotlin generator definition
 
generator_python.h
Fast binary encoding Python generator definition
 
generator_ruby.h
Fast binary encoding Ruby generator definition
 
generator_swift.h
Fast binary encoding Kotlin generator definition
 
version.h
Version definition
 
source
 
fbe.cpp
Fast binary encoding implementation
 
fbe.l
 
generator.cpp
Fast binary encoding generator implementation
 
generator_cpp.cpp
Fast binary encoding C++ generator implementation
 
generator_csharp.cpp
Fast binary encoding C# generator implementation
 
generator_go.cpp
Fast binary encoding Go generator implementation
 
generator_java.cpp
Fast binary encoding Java generator implementation
 
generator_javascript.cpp
Fast binary encoding JavaScript generator implementation
 
generator_kotlin.cpp
Fast binary encoding Kotlin generator implementation
 
generator_python.cpp
Fast binary encoding Python generator implementation
 
generator_ruby.cpp
Fast binary encoding Ruby generator implementation
 
generator_swift.cpp
Fast binary encoding Swift generator implementation
+
+
+ + +
+ + diff --git a/documents/html/functions.html b/documents/html/functions.html new file mode 100644 index 000000000..99e747551 --- /dev/null +++ b/documents/html/functions.html @@ -0,0 +1,251 @@ + + + + + + + +FastBinaryEncoding: Class Members + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + +
+
+ +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
Here is a list of all class members with links to the classes they belong to:
+ +

- _ -

+ + +

- a -

+ + +

- b -

+ + +

- c -

+ + +

- d -

+ + +

- e -

+ + +

- f -

+ + +

- g -

+ + +

- h -

+ + +

- i -

+ + +

- j -

+ + +

- k -

+ + +

- l -

+ + +

- m -

+ + +

- n -

+ + +

- o -

+ + +

- p -

+ + +

- r -

+ + +

- s -

+ + +

- t -

+ + +

- v -

+ + +

- w -

+
+ + +
+ + diff --git a/documents/html/functions_func.html b/documents/html/functions_func.html new file mode 100644 index 000000000..93f9b2e8f --- /dev/null +++ b/documents/html/functions_func.html @@ -0,0 +1,159 @@ + + + + + + + +FastBinaryEncoding: Class Members - Functions + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + +
+
+ +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
Here is a list of all functions with links to the classes they belong to:
+ +

- a -

+ + +

- e -

+ + +

- f -

+ + +

- g -

+ + +

- i -

+ + +

- j -

+ + +

- l -

+ + +

- m -

+ + +

- p -

+ + +

- s -

+ + +

- v -

+ + +

- w -

+
+ + +
+ + diff --git a/documents/html/functions_vars.html b/documents/html/functions_vars.html new file mode 100644 index 000000000..d9caf2fac --- /dev/null +++ b/documents/html/functions_vars.html @@ -0,0 +1,210 @@ + + + + + + + +FastBinaryEncoding: Class Members - Variables + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + +
+
+ +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
Here is a list of all variables with links to the classes they belong to:
+ +

- _ -

+ + +

- a -

+ + +

- b -

+ + +

- c -

+ + +

- d -

+ + +

- e -

+ + +

- f -

+ + +

- g -

+ + +

- h -

+ + +

- i -

+ + +

- k -

+ + +

- l -

+ + +

- m -

+ + +

- n -

+ + +

- o -

+ + +

- r -

+ + +

- s -

+ + +

- t -

+ + +

- v -

+
+ + +
+ + diff --git a/documents/html/generator_8cpp.html b/documents/html/generator_8cpp.html new file mode 100644 index 000000000..40e23e957 --- /dev/null +++ b/documents/html/generator_8cpp.html @@ -0,0 +1,109 @@ + + + + + + + +FastBinaryEncoding: source/generator.cpp File Reference + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+ +
generator.cpp File Reference
+
+
+ +

Fast binary encoding generator implementation. +More...

+
#include "generator.h"
+
+

Go to the source code of this file.

+ + + +

+Namespaces

namespace  FBE
+

Detailed Description

+

Fast binary encoding generator implementation.

+
Author
Ivan Shynkarenka
+
Date
20.04.2018
+ + +

Definition in file generator.cpp.

+
+ + +
+ + diff --git a/documents/html/generator_8cpp_source.html b/documents/html/generator_8cpp_source.html new file mode 100644 index 000000000..73dd993c3 --- /dev/null +++ b/documents/html/generator_8cpp_source.html @@ -0,0 +1,160 @@ + + + + + + + +FastBinaryEncoding: source/generator.cpp Source File + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+
generator.cpp
+
+
+Go to the documentation of this file.
1
+
8
+
9#include "generator.h"
+
10
+
11#if defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
+
12#include <windows.h>
+
13#endif
+
14
+
15namespace FBE {
+
16
+
+
17void Generator::Store(const CppCommon::Path& filename)
+
18{
+
19 std::string previous;
+
20
+
21 // Try to read the previous file content
+
22 if (filename.IsExists())
+
23 {
+
24 CppCommon::File file = filename;
+
25 file.Open(true, false);
+
26 previous = file.ReadAllText();
+
27 file.Close();
+
28 }
+
29
+
30 // Compare the buffer with previous content in order to store only new content
+
31 if (_buffer == previous)
+
32 return;
+
33
+
34 // Store the buffer into unique file
+
35 CppCommon::Path unique = filename.parent() / CppCommon::Path::unique();
+
36 CppCommon::File::WriteAllText(unique, _buffer);
+
37
+
38#if defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
+
39 // Sometimes it happens that Visual Studio opens generated files on a fly to analyze.
+
40 // It opens them with mapping into its process with CreateFileMapping/MapViewOfFile.
+
41 // As the result files cannot be replaced or removed. Therefore we need to have some
+
42 // retry attempts with small delay to give a change for the file to be created.
+
43 // https://stackoverflow.com/questions/41844842/when-error-1224-error-user-mapped-file-occurs
+
44 const int attempts = 1000;
+
45 const int sleep = 100;
+
46 for (int attempt = 0; attempt < attempts; ++attempt)
+
47 {
+
48 try
+
49 {
+
50 // Rename the unique file inside a loop with retries
+
51 CppCommon::Path::Rename(unique, filename);
+
52 return;
+
53 }
+
54 catch (const CppCommon::FileSystemException& ex)
+
55 {
+
56 if ((ex.system_error() == ERROR_ACCESS_DENIED) || (ex.system_error() == ERROR_USER_MAPPED_FILE))
+
57 {
+
58 CppCommon::Thread::Sleep(sleep);
+
59 continue;
+
60 }
+
61 throw;
+
62 }
+
63 }
+
64 throwex CppCommon::FileSystemException("Cannot generate the output file!").Attach(filename);
+
65#else
+
66 // Rename the unique file inside a loop with retries
+
67 CppCommon::Path::Rename(unique, filename);
+
68#endif
+
69}
+
+
70
+
71} // namespace FBE
+
void Store(const CppCommon::Path &filename)
Definition generator.cpp:17
+
std::string _buffer
Definition generator.h:24
+
Fast binary encoding generator definition.
+
Definition fbe.h:33
+
+ + +
+ + diff --git a/documents/html/generator_8h.html b/documents/html/generator_8h.html new file mode 100644 index 000000000..a183a6e6f --- /dev/null +++ b/documents/html/generator_8h.html @@ -0,0 +1,115 @@ + + + + + + + +FastBinaryEncoding: include/generator.h File Reference + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+ +
generator.h File Reference
+
+
+ +

Fast binary encoding generator definition. +More...

+
#include "fbe.h"
+#include "generator.inl"
+
+

Go to the source code of this file.

+ + + +

+Classes

class  FBE::Generator
+ + +

+Namespaces

namespace  FBE
+

Detailed Description

+

Fast binary encoding generator definition.

+
Author
Ivan Shynkarenka
+
Date
20.04.2018
+ + +

Definition in file generator.h.

+
+ + +
+ + diff --git a/documents/html/generator_8h_source.html b/documents/html/generator_8h_source.html new file mode 100644 index 000000000..7a1da1c1e --- /dev/null +++ b/documents/html/generator_8h_source.html @@ -0,0 +1,156 @@ + + + + + + + +FastBinaryEncoding: include/generator.h Source File + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+
generator.h
+
+
+Go to the documentation of this file.
1
+
8
+
9#ifndef GENERATOR_H
+
10#define GENERATOR_H
+
11
+
12#include "fbe.h"
+
13
+
14namespace FBE {
+
15
+
+ +
17{
+
18public:
+
19 Generator(const std::string& input, const std::string& output, int indent, char space);
+
20
+
21 virtual void Generate(const std::shared_ptr<Package>& package) = 0;
+
22
+
23protected:
+
24 std::string _buffer;
+
25 std::string _input;
+
26 std::string _output;
+
27 int _cursor{0};
+ +
29 char _space;
+
30
+
31 void Indent(int count);
+
32
+
33 void WriteBegin();
+
34 void Write(const std::string& str);
+
35 void WriteIndent();
+
36 void WriteIndent(const std::string& str);
+
37 void WriteLine();
+
38 void WriteLine(const std::string& str);
+
39 void WriteLineIndent(const std::string& str);
+
40 void WriteEnd();
+
41
+
42 void Store(const CppCommon::Path& filename);
+
43
+
44 static std::string EndLine();
+
45};
+
+
46
+
47} // namespace FBE
+
48
+
49#include "generator.inl"
+
50
+
51#endif // GENERATOR_H
+
void WriteBegin()
Definition generator.inl:24
+
void Store(const CppCommon::Path &filename)
Definition generator.cpp:17
+
static std::string EndLine()
Definition generator.inl:68
+ +
virtual void Generate(const std::shared_ptr< Package > &package)=0
+ +
std::string _input
Definition generator.h:25
+ + +
std::string _output
Definition generator.h:26
+
void WriteLineIndent(const std::string &str)
Definition generator.inl:58
+
std::string _buffer
Definition generator.h:24
+
Generator(const std::string &input, const std::string &output, int indent, char space)
Definition generator.inl:11
+
void Write(const std::string &str)
Definition generator.inl:29
+ +
void Indent(int count)
Definition generator.inl:19
+
void WriteIndent()
Definition generator.inl:34
+
Fast binary encoding definitions.
+
Fast binary encoding generator inline implementation.
+
Definition fbe.h:33
+
+ + +
+ + diff --git a/documents/html/generator_8inl.html b/documents/html/generator_8inl.html new file mode 100644 index 000000000..bffdd65a5 --- /dev/null +++ b/documents/html/generator_8inl.html @@ -0,0 +1,108 @@ + + + + + + + +FastBinaryEncoding: include/generator.inl File Reference + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+ +
generator.inl File Reference
+
+
+ +

Fast binary encoding generator inline implementation. +More...

+ +

Go to the source code of this file.

+ + + +

+Namespaces

namespace  FBE
+

Detailed Description

+

Fast binary encoding generator inline implementation.

+
Author
Ivan Shynkarenka
+
Date
20.04.2018
+ + +

Definition in file generator.inl.

+
+ + +
+ + diff --git a/documents/html/generator_8inl_source.html b/documents/html/generator_8inl_source.html new file mode 100644 index 000000000..1884fc636 --- /dev/null +++ b/documents/html/generator_8inl_source.html @@ -0,0 +1,194 @@ + + + + + + + +FastBinaryEncoding: include/generator.inl Source File + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+
generator.inl
+
+
+Go to the documentation of this file.
1
+
8
+
9namespace FBE {
+
10
+
+
11inline Generator::Generator(const std::string& input, const std::string& output, int indent, char space)
+
12 : _input(input),
+
13 _output(output),
+
14 _indent(indent),
+
15 _space(space)
+
16{
+
17}
+
+
18
+
+
19inline void Generator::Indent(int count)
+
20{
+
21 _cursor += _indent * count;
+
22}
+
23
+
+ +
25{
+
26 _buffer.clear();
+
27}
+
+
28
+
+
29inline void Generator::Write(const std::string& str)
+
30{
+
31 _buffer.append(str);
+
32}
+
+
33
+
+ +
35{
+
36 for (int i = 0; i < _cursor; ++i)
+
37 _buffer.append(1, _space);
+
38}
+
+
39
+
+
40inline void Generator::WriteIndent(const std::string& str)
+
41{
+
42 for (int i = 0; i < _cursor; ++i)
+
43 _buffer.append(1, _space);
+
44 _buffer.append(str);
+
45}
+
+
46
+
+ +
48{
+
49 Write(EndLine());
+
50}
+
+
51
+
+
52inline void Generator::WriteLine(const std::string& str)
+
53{
+
54 Write(str);
+
55 Write(EndLine());
+
56}
+
+
57
+
+
58inline void Generator::WriteLineIndent(const std::string& str)
+
59{
+
60 WriteIndent(str);
+
61 Write(EndLine());
+
62}
+
+
63
+
+ +
65{
+
66}
+
+
67
+
+
68inline std::string Generator::EndLine()
+
69{
+
70 return CppCommon::Environment::EndLine();
+
71}
+
+
72
+
73} // namespace FBE
+
+
void WriteBegin()
Definition generator.inl:24
+
static std::string EndLine()
Definition generator.inl:68
+ + +
std::string _input
Definition generator.h:25
+ + +
std::string _output
Definition generator.h:26
+
void WriteLineIndent(const std::string &str)
Definition generator.inl:58
+
std::string _buffer
Definition generator.h:24
+
Generator(const std::string &input, const std::string &output, int indent, char space)
Definition generator.inl:11
+
void Write(const std::string &str)
Definition generator.inl:29
+ +
void Indent(int count)
Definition generator.inl:19
+
void WriteIndent()
Definition generator.inl:34
+
Definition fbe.h:33
+
+ + +
+ + diff --git a/documents/html/generator__cpp_8cpp.html b/documents/html/generator__cpp_8cpp.html new file mode 100644 index 000000000..a07500a59 --- /dev/null +++ b/documents/html/generator__cpp_8cpp.html @@ -0,0 +1,109 @@ + + + + + + + +FastBinaryEncoding: source/generator_cpp.cpp File Reference + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+ +
generator_cpp.cpp File Reference
+
+
+ +

Fast binary encoding C++ generator implementation. +More...

+
#include "generator_cpp.h"
+
+

Go to the source code of this file.

+ + + +

+Namespaces

namespace  FBE
+

Detailed Description

+

Fast binary encoding C++ generator implementation.

+
Author
Ivan Shynkarenka
+
Date
20.04.2018
+ + +

Definition in file generator_cpp.cpp.

+
+ + +
+ + diff --git a/documents/html/generator__cpp_8cpp_source.html b/documents/html/generator__cpp_8cpp_source.html new file mode 100644 index 000000000..73d5b1985 --- /dev/null +++ b/documents/html/generator__cpp_8cpp_source.html @@ -0,0 +1,10740 @@ + + + + + + + +FastBinaryEncoding: source/generator_cpp.cpp Source File + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+
generator_cpp.cpp
+
+
+Go to the documentation of this file.
1
+
8
+
9#include "generator_cpp.h"
+
10
+
11namespace FBE {
+
12
+
+
13void GeneratorCpp::Generate(const std::shared_ptr<Package>& package)
+
14{
+
15 // Generate common files
+
16 GenerateFBE_Header(_output);
+
17 GenerateFBE_Source(_output);
+
18
+
19 // Generate common models files
+
20 GenerateFBEModels_Header(_output);
+
21 GenerateFBEModels_Inline(_output);
+
22 GenerateFBEModels_Source(_output);
+
23 if (Final())
+
24 {
+
25 GenerateFBEFinalModels_Header(_output);
+
26 GenerateFBEFinalModels_Inline(_output);
+
27 GenerateFBEFinalModels_Source(_output);
+
28 }
+
29
+
30 // Generate common protocol files
+
31 if (Proto())
+
32 {
+
33 GenerateFBEProtocol_Header(_output);
+
34 GenerateFBEProtocol_Source(_output);
+
35 }
+
36
+
37 // Generate common JSON files
+
38 if (JSON())
+
39 GenerateFBEJson_Header(_output);
+
40
+
41 // Generate package files
+
42 GeneratePackage_Header(package);
+
43 GeneratePackage_Source(package);
+
44 if (JSON())
+
45 GeneratePackage_Json(package);
+
46
+
47 // Generate package models files
+
48 GeneratePackageModels_Header(package);
+
49 GeneratePackageModels_Source(package);
+
50 if (Final())
+
51 {
+
52 GeneratePackageFinalModels_Header(package);
+
53 GeneratePackageFinalModels_Source(package);
+
54 }
+
55
+
56 // Generate package protocol files
+
57 if (Proto())
+
58 {
+
59 GeneratePackageProtocol_Header(package, false);
+
60 GeneratePackageProtocol_Source(package, false);
+
61 if (Final())
+
62 {
+
63 GeneratePackageProtocol_Header(package, true);
+
64 GeneratePackageProtocol_Source(package, true);
+
65 }
+
66 }
+
67}
+
+
68
+
69void GeneratorCpp::GenerateHeader(const std::string& source)
+
70{
+
71 std::string code = R"CODE(//------------------------------------------------------------------------------
+
72// Automatically generated by the Fast Binary Encoding compiler, do not modify!
+
73// https://github.com/chronoxor/FastBinaryEncoding
+
74// Source: _INPUT_
+
75// FBE version: _VERSION_
+
76//------------------------------------------------------------------------------
+
77
+
78#pragma once
+
79
+
80#if defined(__clang__)
+
81#pragma clang system_header
+
82#elif defined(__GNUC__)
+
83#pragma GCC system_header
+
84#elif defined(_MSC_VER)
+
85#pragma system_header
+
86#endif
+
87)CODE";
+
88
+
89 // Prepare code template
+
90 code = std::regex_replace(code, std::regex("_INPUT_"), source);
+
91 code = std::regex_replace(code, std::regex("_VERSION_"), version);
+
92 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
93
+
94 Write(code);
+
95}
+
96
+
97void GeneratorCpp::GenerateInline(const std::string& source)
+
98{
+
99 std::string code = R"CODE(//------------------------------------------------------------------------------
+
100// Automatically generated by the Fast Binary Encoding compiler, do not modify!
+
101// https://github.com/chronoxor/FastBinaryEncoding
+
102// Source: _INPUT_
+
103// FBE version: _VERSION_
+
104//------------------------------------------------------------------------------
+
105)CODE";
+
106
+
107 // Prepare code template
+
108 code = std::regex_replace(code, std::regex("_INPUT_"), source);
+
109 code = std::regex_replace(code, std::regex("_VERSION_"), version);
+
110 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
111
+
112 Write(code);
+
113}
+
114
+
115void GeneratorCpp::GenerateSource(const std::string& source)
+
116{
+
117 std::string code = R"CODE(//------------------------------------------------------------------------------
+
118// Automatically generated by the Fast Binary Encoding compiler, do not modify!
+
119// https://github.com/chronoxor/FastBinaryEncoding
+
120// Source: _INPUT_
+
121// FBE version: _VERSION_
+
122//------------------------------------------------------------------------------
+
123)CODE";
+
124
+
125 // Prepare code template
+
126 code = std::regex_replace(code, std::regex("_INPUT_"), source);
+
127 code = std::regex_replace(code, std::regex("_VERSION_"), version);
+
128 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
129
+
130 Write(code);
+
131}
+
132
+
133void GeneratorCpp::GenerateWarningsHeader()
+
134{
+
135 std::string code = R"CODE(
+
136#if defined(_MSC_VER)
+
137#pragma warning(push)
+
138#pragma warning(disable:4065) // C4065: switch statement contains 'default' but no 'case' labels
+
139#endif
+
140)CODE";
+
141
+
142 // Prepare code template
+
143 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
144
+
145 Write(code);
+
146}
+
147
+
148void GeneratorCpp::GenerateWarningsFooter()
+
149{
+
150 std::string code = R"CODE(
+
151#if defined(_MSC_VER)
+
152#pragma warning(pop)
+
153#endif
+
154)CODE";
+
155
+
156 // Prepare code template
+
157 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
158
+
159 Write(code);
+
160}
+
161
+
162void GeneratorCpp::GenerateFooter()
+
163{
+
164}
+
165
+
166void GeneratorCpp::GenerateImports()
+
167{
+
168 std::string code = R"CODE(
+
169#include <array>
+
170#include <bitset>
+
171#include <cassert>
+
172#include <cmath>
+
173#include <cstring>
+
174#include <cctype>
+
175#include <future>
+
176#include <iomanip>
+
177#include <limits>
+
178#include <list>
+
179#include <map>
+
180#include <memory>
+
181#include <mutex>
+
182#include <optional>
+
183#include <set>
+
184#include <sstream>
+
185#include <stdexcept>
+
186#include <string>
+
187#include <tuple>
+
188#include <type_traits>
+
189#include <unordered_map>
+
190#include <vector>
+
191
+
192#if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
+
193#include <time.h>
+
194#include <uuid/uuid.h>
+
195#elif defined(_WIN32) || defined(_WIN64)
+
196#undef DELETE
+
197#undef ERROR
+
198#undef Yield
+
199#undef min
+
200#undef max
+
201#undef uuid_t
+
202#endif
+
203)CODE";
+
204
+
205 // Prepare code template
+
206 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
207
+
208 Write(code);
+
209
+
210 // Generate logging protocol definitions
+
211 if (Logging())
+
212 {
+
213 WriteLine();
+
214 WriteLineIndent("#define LOGGING_PROTOCOL 1");
+
215 WriteLineIndent("#include <logging/logger.h>");
+
216 }
+
217}
+
218
+
219void GeneratorCpp::GenerateImportsSource()
+
220{
+
221 std::string code = R"CODE(
+
222#if defined(_WIN32) || defined(_WIN64)
+
223#include <windows.h>
+
224#include <rpc.h>
+
225#undef DELETE
+
226#undef ERROR
+
227#undef Yield
+
228#undef min
+
229#undef max
+
230#undef uuid_t
+
231#endif
+
232)CODE";
+
233
+
234 // Prepare code template
+
235 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
236
+
237 Write(code);
+
238}
+
239
+
240void GeneratorCpp::GenerateImports(const std::string& source)
+
241{
+
242 WriteLine();
+
243 WriteLineIndent("#include \"" + source + "\"");
+
244}
+
245
+
246void GeneratorCpp::GenerateImports(const std::shared_ptr<Package>& p)
+
247{
+
248 // Generate common imports
+
249 WriteLine();
+
250 WriteLineIndent("#include \"fbe.h\"");
+
251
+
252 // Generate packages import
+
253 if (p->import)
+
254 {
+
255 WriteLine();
+
256 for (const auto& import : p->import->imports)
+
257 WriteLineIndent("#include \"" + *import + ".h\"");
+
258 }
+
259
+
260 // Generate domain namespace using
+
261 WriteLine();
+
262 WriteLineIndent("namespace " + *p->name + " {");
+
263 WriteLineIndent("using namespace FBE;");
+
264 if (p->import)
+
265 {
+
266 for (const auto& import : p->import->imports)
+
267 WriteLineIndent("using namespace ::" + *import + ";");
+
268 }
+
269 WriteLineIndent("} // namespace " + *p->name);
+
270
+
271 // Generate FBE namespace using
+
272 WriteLine();
+
273 WriteLineIndent("namespace FBE {");
+
274 WriteLineIndent("using namespace ::" + *p->name + ";");
+
275 WriteLineIndent("} // namespace FBE");
+
276}
+
277
+
278void GeneratorCpp::GenerateImportsModels(const std::shared_ptr<Package>& p, bool final)
+
279{
+
280 // Generate common imports
+
281 WriteLine();
+
282 WriteLineIndent("#include \"" + *p->name + ".h\"");
+
283
+
284 // Generate packages import
+
285 if (p->import)
+
286 {
+
287 WriteLine();
+
288 for (const auto& import : p->import->imports)
+
289 WriteLineIndent("#include \"" + *import + (final ? "_final" : "") + "_models.h\"");
+
290 }
+
291}
+
292
+
293void GeneratorCpp::GenerateImportsProtocol(const std::shared_ptr<Package>& p, bool final)
+
294{
+
295 // Generate common imports
+
296 WriteLine();
+
297 WriteLineIndent("#include \"" + *p->name + (final ? "_final" : "") + "_models.h\"");
+
298
+
299 // Generate packages import
+
300 if (p->import)
+
301 {
+
302 WriteLine();
+
303 for (const auto& import : p->import->imports)
+
304 WriteLineIndent("#include \"" + *import + (final ? "_final" : "") + "_protocol.h\"");
+
305 }
+
306}
+
307
+
308void GeneratorCpp::GenerateImportsJson()
+
309{
+
310 WriteLine();
+
311 WriteLineIndent("#define RAPIDJSON_HAS_STDSTRING 1");
+
312 WriteLineIndent("#include <rapidjson/document.h>");
+
313 WriteLineIndent("#include <rapidjson/prettywriter.h>");
+
314}
+
315
+
316void GeneratorCpp::GenerateImportsJson(const std::shared_ptr<Package>& p)
+
317{
+
318 // Generate common imports
+
319 WriteLine();
+
320 WriteLineIndent("#include \"fbe_json.h\"");
+
321
+
322 // Generate common imports
+
323 WriteLine();
+
324 WriteLineIndent("#include \"" + *p->name + ".h\"");
+
325
+
326 // Generate packages import
+
327 if (p->import)
+
328 {
+
329 WriteLine();
+
330 for (const auto& import : p->import->imports)
+
331 WriteLineIndent("#include \"" + *import + "_json.h\"");
+
332 }
+
333}
+
334
+
335void GeneratorCpp::GenerateBufferWrapper_Header()
+
336{
+
337 std::string code = R"CODE(
+
339
+
343class buffer_t
+
344{
+
345public:
+
346 typedef std::vector<uint8_t>::iterator iterator;
+
347 typedef std::vector<uint8_t>::const_iterator const_iterator;
+
348 typedef std::vector<uint8_t>::reverse_iterator reverse_iterator;
+
349 typedef std::vector<uint8_t>::const_reverse_iterator const_reverse_iterator;
+
350
+
351 buffer_t() = default;
+
352 buffer_t(size_t capacity) { reserve(capacity); }
+
353 buffer_t(const std::string& str) { assign(str); }
+
354 buffer_t(size_t size, uint8_t value) { assign(size, value); }
+
355 buffer_t(const uint8_t* data, size_t size) { assign(data, size); }
+
356 buffer_t(const std::vector<uint8_t>& other) : _data(other) {}
+
357 buffer_t(std::vector<uint8_t>&& other) : _data(std::move(other)) {}
+
358 buffer_t(const buffer_t& other) = default;
+
359 buffer_t(buffer_t&& other) = default;
+
360 ~buffer_t() = default;
+
361
+
362 buffer_t& operator=(const std::string& str) { assign(str); return *this; }
+
363 buffer_t& operator=(const std::vector<uint8_t>& other) { _data = other; return *this; }
+
364 buffer_t& operator=(std::vector<uint8_t>&& other) { _data = std::move(other); return *this; }
+
365 buffer_t& operator=(const buffer_t& other) = default;
+
366 buffer_t& operator=(buffer_t&& other) = default;
+
367
+
368 uint8_t& operator[](size_t index) { return _data[index]; }
+
369 const uint8_t& operator[](size_t index) const { return _data[index]; }
+
370
+
371 bool empty() const { return _data.empty(); }
+
372 size_t capacity() const { return _data.capacity(); }
+
373 size_t size() const { return _data.size(); }
+
374 size_t max_size() const { return _data.max_size(); }
+
375
+
376 std::vector<uint8_t>& buffer() noexcept { return _data; }
+
377 const std::vector<uint8_t>& buffer() const noexcept { return _data; }
+
378 uint8_t* data() noexcept { return _data.data(); }
+
379 const uint8_t* data() const noexcept { return _data.data(); }
+
380 uint8_t& at(size_t index) { return _data.at(index); }
+
381 const uint8_t& at(size_t index) const { return _data.at(index); }
+
382 uint8_t& front() { return _data.front(); }
+
383 const uint8_t& front() const { return _data.front(); }
+
384 uint8_t& back() { return _data.back(); }
+
385 const uint8_t& back() const { return _data.back(); }
+
386
+
387 void reserve(size_t capacity) { _data.reserve(capacity); }
+
388 void resize(size_t size, uint8_t value = 0) { _data.resize(size, value); }
+
389 void shrink_to_fit() { _data.shrink_to_fit(); }
+
390
+
391 void assign(const std::string& str) { assign((const uint8_t*)str.c_str(), str.size()); }
+
392 void assign(const std::vector<uint8_t>& vec) { assign(vec.begin(), vec.end()); }
+
393 void assign(size_t size, uint8_t value) { _data.assign(size, value); }
+
394 void assign(const uint8_t* data, size_t size) { _data.assign(data, data + size); }
+
395 template <class InputIterator>
+
396 void assign(InputIterator first, InputIterator last) { _data.assign(first, last); }
+
397 iterator insert(const_iterator position, uint8_t value) { return _data.insert(position, value); }
+
398 iterator insert(const_iterator position, const std::string& str) { return insert(position, (const uint8_t*)str.c_str(), str.size()); }
+
399 iterator insert(const_iterator position, const std::vector<uint8_t>& vec) { return insert(position, vec.begin(), vec.end()); }
+
400 iterator insert(const_iterator position, size_t size, uint8_t value) { return _data.insert(position, size, value); }
+
401 iterator insert(const_iterator position, const uint8_t* data, size_t size) { return _data.insert(position, data, data + size); }
+
402 template <class InputIterator>
+
403 iterator insert(const_iterator position, InputIterator first, InputIterator last) { return _data.insert(position, first, last); }
+
404 iterator erase(const_iterator position) { return _data.erase(position); }
+
405 iterator erase(const_iterator first, const_iterator last) { return _data.erase(first, last); }
+
406 void clear() noexcept { _data.clear(); }
+
407
+
408 void push_back(uint8_t value) { _data.push_back(value); }
+
409 void pop_back() { _data.pop_back(); }
+
410
+
411 template <class... Args>
+
412 iterator emplace(const_iterator position, Args&&... args) { return _data.emplace(position, args...); }
+
413 template <class... Args>
+
414 void emplace_back(Args&&... args) { _data.emplace_back(args...); }
+
415
+
416 iterator begin() noexcept { return _data.begin(); }
+
417 const_iterator begin() const noexcept { return _data.begin(); }
+
418 const_iterator cbegin() const noexcept { return _data.cbegin(); }
+
419 reverse_iterator rbegin() noexcept { return _data.rbegin(); }
+
420 const_reverse_iterator rbegin() const noexcept { return _data.rbegin(); }
+
421 const_reverse_iterator crbegin() const noexcept { return _data.crbegin(); }
+
422 iterator end() noexcept { return _data.end(); }
+
423 const_iterator end() const noexcept { return _data.end(); }
+
424 const_iterator cend() const noexcept { return _data.cend(); }
+
425 reverse_iterator rend() noexcept { return _data.rend(); }
+
426 const_reverse_iterator rend() const noexcept { return _data.rend(); }
+
427 const_reverse_iterator crend() const noexcept { return _data.crend(); }
+
428
+
430 std::string string() const { return std::string(_data.begin(), _data.end()); }
+
431
+
433 std::string base64encode() const;
+
435 static buffer_t base64decode(const std::string& str);
+
436
+
438 void swap(buffer_t& value) noexcept
+
439 { using std::swap; swap(_data, value._data); }
+
440 friend void swap(buffer_t& value1, buffer_t& value2) noexcept
+
441 { value1.swap(value2); }
+
442
+
443private:
+
444 std::vector<uint8_t> _data;
+
445};
+
446)CODE";
+
447
+
448 // Prepare code template
+
449 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
450
+
451 Write(code);
+
452}
+
453
+
454void GeneratorCpp::GenerateBufferWrapper_Source()
+
455{
+
456 std::string code = R"CODE(
+
457std::string buffer_t::base64encode() const
+
458{
+
459 const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
460 std::string result;
+
461
+
462 int val = 0;
+
463 int valb = -6;
+
464 for (auto c : _data)
+
465 {
+
466 val = (val << 8) + c;
+
467 valb += 8;
+
468 while (valb >= 0)
+
469 {
+
470 result.push_back(base64[(val >> valb) & 0x3F]);
+
471 valb -= 6;
+
472 }
+
473 }
+
474
+
475 if (valb > -6)
+
476 result.push_back(base64[((val << 8) >> (valb + 8)) & 0x3F]);
+
477
+
478 while (result.size() % 4)
+
479 result.push_back('=');
+
480
+
481 return result;
+
482}
+
483
+
484buffer_t buffer_t::base64decode(const std::string& str)
+
485{
+
486 const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
487 buffer_t result;
+
488
+
489 std::vector<int> pattern(256, -1);
+
490 for (int i = 0; i < 64; ++i)
+
491 pattern[base64[i]] = i;
+
492
+
493 int val = 0;
+
494 int valb = -8;
+
495 for (auto c : str)
+
496 {
+
497 if (pattern[c] == -1)
+
498 break;
+
499
+
500 val = (val << 6) + pattern[c];
+
501 valb += 6;
+
502
+
503 if (valb >= 0)
+
504 {
+
505 result.push_back((uint8_t)((val >> valb) & 0xFF));
+
506 valb -= 8;
+
507 }
+
508 }
+
509
+
510 return result;
+
511}
+
512)CODE";
+
513
+
514 // Prepare code template
+
515 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
516
+
517 Write(code);
+
518}
+
519
+
520void GeneratorCpp::GenerateDecimalWrapper_Header()
+
521{
+
522 std::string code = R"CODE(
+
524
+
527class decimal_t
+
528{
+
529public:
+
530 decimal_t() noexcept { _value = 0.0; }
+
531 decimal_t(int8_t value) noexcept { _value = (double)value; }
+
532 decimal_t(uint8_t value) noexcept { _value = (double)value; }
+
533 decimal_t(int16_t value) noexcept { _value = (double)value; }
+
534 decimal_t(uint16_t value) noexcept { _value = (double)value; }
+
535 decimal_t(int32_t value) noexcept { _value = (double)value; }
+
536 decimal_t(uint32_t value) noexcept { _value = (double)value; }
+
537 decimal_t(int64_t value) noexcept { _value = (double)value; }
+
538 decimal_t(uint64_t value) noexcept { _value = (double)value; }
+
539 decimal_t(float value) noexcept { _value = (double)value; }
+
540 decimal_t(double value) noexcept { _value = value; }
+
541 template <typename T>
+
542 explicit decimal_t(const T& value) noexcept { _value = (double)value; }
+
543 decimal_t(const decimal_t& value) noexcept = default;
+
544 decimal_t(decimal_t&& value) noexcept = default;
+
545 ~decimal_t() noexcept = default;
+
546
+
547 template <typename T>
+
548 decimal_t& operator=(const T& value) noexcept { _value = (double)value; return *this; }
+
549 decimal_t& operator=(const decimal_t& value) noexcept = default;
+
550 decimal_t& operator=(decimal_t&& value) noexcept = default;
+
551
+
552 // Arithmetic operators
+
553 decimal_t operator+() const noexcept { return decimal_t(_value); }
+
554 decimal_t operator-() const noexcept { return decimal_t(-_value); }
+
555
+
556 decimal_t& operator++() noexcept { return *this += 1; }
+
557 decimal_t operator++(int) noexcept { decimal_t temp(*this); ++*this; return temp; }
+
558 decimal_t& operator--() noexcept { return *this -= 1; }
+
559 decimal_t operator--(int) noexcept { decimal_t temp(*this); --*this; return temp; }
+
560
+
561 decimal_t& operator+=(const decimal_t& value) noexcept { return *this = *this + value; }
+
562 decimal_t& operator-=(const decimal_t& value) noexcept { return *this = *this - value; }
+
563 decimal_t& operator*=(const decimal_t& value) noexcept { return *this = *this * value; }
+
564 decimal_t& operator/=(const decimal_t& value) { return *this = *this / value; }
+
565
+
566 template <typename T>
+
567 decimal_t& operator+=(const T& value) noexcept { return *this = *this + decimal_t(value); }
+
568 template <typename T>
+
569 decimal_t& operator-=(const T& value) noexcept { return *this = *this - decimal_t(value); }
+
570 template <typename T>
+
571 decimal_t& operator*=(const T& value) noexcept { return *this = *this * decimal_t(value); }
+
572 template <typename T>
+
573 decimal_t& operator/=(const T& value) { return *this = *this / decimal_t(value); }
+
574
+
575 template <typename T>
+
576 friend T& operator+=(T& value1, const decimal_t& value2) noexcept { return value1 = (T)(decimal_t(value1) + value2); }
+
577 template <typename T>
+
578 friend T& operator-=(T& value1, const decimal_t& value2) noexcept { return value1 = (T)(decimal_t(value1) - value2); }
+
579 template <typename T>
+
580 friend T& operator*=(T& value1, const decimal_t& value2) noexcept { return value1 = (T)(decimal_t(value1) * value2); }
+
581 template <typename T>
+
582 friend T& operator/=(T& value1, const decimal_t& value2) { return value1 = (T)(decimal_t(value1) / value2); }
+
583
+
584 template <typename T>
+
585 friend decimal_t operator+(const T& value1, const decimal_t& value2) noexcept { return decimal_t(value1) + value2; }
+
586 template <typename T>
+
587 friend decimal_t operator+(const decimal_t& value1, const T& value2) noexcept { return value1 + decimal_t(value2); }
+
588 friend decimal_t operator+(const decimal_t& value1, const decimal_t& value2) noexcept { return decimal_t(value1._value + value2._value); }
+
589
+
590 template <typename T>
+
591 friend decimal_t operator-(const T& value1, const decimal_t& value2) noexcept { return decimal_t(value1) - value2; }
+
592 template <typename T>
+
593 friend decimal_t operator-(const decimal_t& value1, const T& value2) noexcept { return value1 - decimal_t(value2); }
+
594 friend decimal_t operator-(const decimal_t& value1, const decimal_t& value2) noexcept { return decimal_t(value1._value - value2._value); }
+
595
+
596 template <typename T>
+
597 friend decimal_t operator*(const T& value1, const decimal_t& value2) noexcept { return decimal_t(value1) * value2; }
+
598 template <typename T>
+
599 friend decimal_t operator*(const decimal_t& value1, const T& value2) noexcept { return value1 * decimal_t(value2); }
+
600 friend decimal_t operator*(const decimal_t& value1, const decimal_t& value2) noexcept { return decimal_t(value1._value * value2._value); }
+
601
+
602 template <typename T>
+
603 friend decimal_t operator/(const T& value1, const decimal_t& value2) { return decimal_t(value1) / value2; }
+
604 template <typename T>
+
605 friend decimal_t operator/(const decimal_t& value1, const T& value2) { return value1 / decimal_t(value2); }
+
606 friend decimal_t operator/(const decimal_t& value1, const decimal_t& value2) { return decimal_t(value1._value / value2._value); }
+
607
+
608 // Comparison operators
+
609 template <typename T>
+
610 friend bool operator==(const T& value1, const decimal_t& value2) noexcept { return decimal_t(value1) == value2; }
+
611 template <typename T>
+
612 friend bool operator==(const decimal_t& value1, const T& value2) noexcept { return value1 == decimal_t(value2); }
+
613 friend bool operator==(const decimal_t& value1, const decimal_t& value2) noexcept { return value1._value == value2._value; }
+
614
+
615 template <typename T>
+
616 friend bool operator!=(const T& value1, const decimal_t& value2) noexcept { return decimal_t(value1) != value2; }
+
617 template <typename T>
+
618 friend bool operator!=(const decimal_t& value1, const T& value2) noexcept { return value1 != decimal_t(value2); }
+
619 friend bool operator!=(const decimal_t& value1, const decimal_t& value2) noexcept { return value1._value != value2._value; }
+
620
+
621 template <typename T>
+
622 friend bool operator<(const T& value1, const decimal_t& value2) noexcept { return decimal_t(value1) < value2; }
+
623 template <typename T>
+
624 friend bool operator<(const decimal_t& value1, const T& value2) noexcept { return value1 < decimal_t(value2); }
+
625 friend bool operator<(const decimal_t& value1, const decimal_t& value2) noexcept { return value1._value < value2._value; }
+
626
+
627 template <typename T>
+
628 friend bool operator>(const T& value1, const decimal_t& value2) noexcept { return decimal_t(value1) > value2; }
+
629 template <typename T>
+
630 friend bool operator>(const decimal_t& value1, const T& value2) noexcept { return value1 > decimal_t(value2); }
+
631 friend bool operator>(const decimal_t& value1, const decimal_t& value2) noexcept { return value1._value > value2._value; }
+
632
+
633 template <typename T>
+
634 friend bool operator<=(const T& value1, const decimal_t& value2) noexcept { return decimal_t(value1) <= value2; }
+
635 template <typename T>
+
636 friend bool operator<=(const decimal_t& value1, const T& value2) noexcept { return value1 <= decimal_t(value2); }
+
637 friend bool operator<=(const decimal_t& value1, const decimal_t& value2) noexcept { return value1._value <= value2._value; }
+
638
+
639 template <typename T>
+
640 friend bool operator>=(const T& value1, const decimal_t& value2) noexcept { return decimal_t(value1) >= value2; }
+
641 template <typename T>
+
642 friend bool operator>=(const decimal_t& value1, const T& value2) noexcept { return value1 >= decimal_t(value2); }
+
643 friend bool operator>=(const decimal_t& value1, const decimal_t& value2) noexcept { return value1._value >= value2._value; }
+
644
+
645 // Type cast
+
646 operator bool() const noexcept { return (_value != 0.0); }
+
647 operator uint8_t() const noexcept { return (uint8_t)_value; }
+
648 operator uint16_t() const noexcept { return (uint16_t)_value; }
+
649 operator uint32_t() const noexcept { return (uint32_t)_value; }
+
650 operator uint64_t() const noexcept { return (uint64_t)_value; }
+
651 operator float() const noexcept { return (float)_value; }
+
652 operator double() const noexcept { return (double)_value; }
+
653
+
655 std::string string() const { return std::to_string(_value); }
+
656
+
658 friend std::istream& operator>>(std::istream& is, decimal_t& value)
+
659 { is >> value._value; return is; }
+
661 friend std::ostream& operator<<(std::ostream& os, const decimal_t& value)
+
662 { os << value.string(); return os; }
+
663
+
664#if defined(LOGGING_PROTOCOL)
+
666 friend CppLogging::Record& operator<<(CppLogging::Record& record, const decimal_t& value)
+
667 { return record.StoreCustom(value._value); }
+
668#endif
+
669
+
671 void swap(decimal_t& value) noexcept
+
672 { using std::swap; swap(_value, value._value); }
+
673 friend void swap(decimal_t& value1, decimal_t& value2) noexcept
+
674 { value1.swap(value2); }
+
675
+
676private:
+
677 double _value;
+
678};
+
679
+
680} // namespace FBE
+
681
+
682#if defined(FMT_VERSION) && (FMT_VERSION >= 90000)
+
683template <>
+
684struct fmt::formatter<FBE::decimal_t> : formatter<std::string_view>
+
685{
+
686 template <typename FormatContext>
+
687 auto format(const FBE::decimal_t& value, FormatContext& ctx) const
+
688 {
+
689 return formatter<string_view>::format((double)value, ctx);
+
690 }
+
691};
+
692#endif
+
693
+
694template <>
+
695struct std::hash<FBE::decimal_t>
+
696{
+
697 typedef FBE::decimal_t argument_type;
+
698 typedef size_t result_type;
+
699
+
700 result_type operator() (const argument_type& value) const
+
701 {
+
702 result_type result = 17;
+
703 result = result * 31 + std::hash<double>()((double)value);
+
704 return result;
+
705 }
+
706};
+
707
+
708namespace FBE {
+
709)CODE";
+
710
+
711 // Prepare code template
+
712 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
713
+
714 Write(code);
+
715}
+
716
+
717void GeneratorCpp::GenerateFlagsWrapper_Header()
+
718{
+
719 std::string code = R"CODE(
+
720// Register a new enum-based flags macro
+
721#define FBE_ENUM_FLAGS(type)\
+
722inline FBE::Flags<type> operator|(type f1, type f2) noexcept { return FBE::Flags<type>(f1) | FBE::Flags<type>(f2); }\
+
723inline FBE::Flags<type> operator&(type f1, type f2) noexcept { return FBE::Flags<type>(f1) & FBE::Flags<type>(f2); }\
+
724inline FBE::Flags<type> operator^(type f1, type f2) noexcept { return FBE::Flags<type>(f1) ^ FBE::Flags<type>(f2); }
+
725
+
726// Enum-based flags
+
727template <typename TEnum>
+
728class Flags
+
729{
+
730 // Enum underlying type
+
731 typedef typename std::make_unsigned<typename std::underlying_type<TEnum>::type>::type type;
+
732
+
733public:
+
734 Flags() noexcept : _value(0) {}
+
735 explicit Flags(type value) noexcept : _value(value) {}
+
736 explicit Flags(TEnum value) noexcept : _value((type)value) {}
+
737 Flags(const Flags&) noexcept = default;
+
738 Flags(Flags&&) noexcept = default;
+
739 ~Flags() noexcept = default;
+
740
+
741 Flags& operator=(type value) noexcept
+
742 { _value = value; return *this; }
+
743 Flags& operator=(TEnum value) noexcept
+
744 { _value = (type)value; return *this; }
+
745 Flags& operator=(const Flags&) noexcept = default;
+
746 Flags& operator=(Flags&&) noexcept = default;
+
747
+
748 // Is any flag set?
+
749 explicit operator bool() const noexcept { return isset(); }
+
750
+
751 // Is no flag set?
+
752 bool operator!() const noexcept { return !isset(); }
+
753
+
754 // Reverse all flags
+
755 Flags operator~() const noexcept { return Flags(~_value); }
+
756
+
757 // Flags logical assign operators
+
758 Flags& operator&=(const Flags& flags) noexcept
+
759 { _value &= flags._value; return *this; }
+
760 Flags& operator|=(const Flags& flags) noexcept
+
761 { _value |= flags._value; return *this; }
+
762 Flags& operator^=(const Flags& flags) noexcept
+
763 { _value ^= flags._value; return *this; }
+
764
+
765 // Flags logical friend operators
+
766 friend Flags operator&(const Flags& flags1, const Flags& flags2) noexcept
+
767 { return Flags(flags1._value & flags2._value); }
+
768 friend Flags operator|(const Flags& flags1, const Flags& flags2) noexcept
+
769 { return Flags(flags1._value | flags2._value); }
+
770 friend Flags operator^(const Flags& flags1, const Flags& flags2) noexcept
+
771 { return Flags(flags1._value ^ flags2._value); }
+
772
+
773 // Flags comparison
+
774 friend bool operator==(const Flags& flags1, const Flags& flags2) noexcept
+
775 { return flags1._value == flags2._value; }
+
776 friend bool operator!=(const Flags& flags1, const Flags& flags2) noexcept
+
777 { return flags1._value != flags2._value; }
+
778
+
779 // Convert to the enum value
+
780 operator TEnum() const noexcept { return (TEnum)_value; }
+
781
+
783 bool isset() const noexcept { return (_value != 0); }
+
785 bool isset(type value) const noexcept { return (_value & value) != 0; }
+
787 bool isset(TEnum value) const noexcept { return (_value & (type)value) != 0; }
+
788
+
789 // Get the enum value
+
790 TEnum value() const noexcept { return (TEnum)_value; }
+
791 // Get the underlying enum value
+
792 type underlying() const noexcept { return _value; }
+
793 // Get the bitset value
+
794 std::bitset<sizeof(type) * 8> bitset() const noexcept { return {_value}; }
+
795
+
796 // Swap two instances
+
797 void swap(Flags& flags) noexcept { using std::swap; swap(_value, flags._value); }
+
798 template <typename UEnum>
+
799 friend void swap(Flags<UEnum>& flags1, Flags<UEnum>& flags2) noexcept;
+
800
+
801private:
+
802 type _value;
+
803};
+
804
+
805template <typename TEnum>
+
806inline void swap(Flags<TEnum>& flags1, Flags<TEnum>& flags2) noexcept
+
807{
+
808 flags1.swap(flags2);
+
809}
+
810)CODE";
+
811
+
812 // Prepare code template
+
813 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
814
+
815 Write(code);
+
816}
+
817
+
818void GeneratorCpp::GenerateTimeWrapper_Header()
+
819{
+
820 std::string code = R"CODE(
+
821// Get Epoch timestamp
+
822inline uint64_t epoch() { return 0ull; }
+
823// Get UTC timestamp
+
824uint64_t utc();
+
825)CODE";
+
826
+
827 // Prepare code template
+
828 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
829
+
830 Write(code);
+
831}
+
832
+
833void GeneratorCpp::GenerateTimeWrapper_Source()
+
834{
+
835 std::string code = R"CODE(
+
836uint64_t utc()
+
837{
+
838#if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
+
839 struct timespec timestamp;
+
840 if (clock_gettime(CLOCK_REALTIME, &timestamp) != 0)
+
841 throw std::runtime_error("Cannot get value of CLOCK_REALTIME timer!");
+
842 return (timestamp.tv_sec * 1000000000) + timestamp.tv_nsec;
+
843#elif defined(_WIN32) || defined(_WIN64)
+
844 FILETIME ft;
+
845 GetSystemTimePreciseAsFileTime(&ft);
+
846
+
847 ULARGE_INTEGER result;
+
848 result.LowPart = ft.dwLowDateTime;
+
849 result.HighPart = ft.dwHighDateTime;
+
850 return (result.QuadPart - 116444736000000000ull) * 100;
+
851#endif
+
852}
+
853)CODE";
+
854
+
855 // Prepare code template
+
856 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
857
+
858 Write(code);
+
859}
+
860
+
861void GeneratorCpp::GenerateUUIDWrapper_Header()
+
862{
+
863 std::string code = R"CODE(
+
865
+
878class uuid_t
+
879{
+
880public:
+
882 uuid_t() : _data() { _data.fill(0); }
+
884
+
887 explicit uuid_t(const std::string& uuid);
+
889
+
892 explicit uuid_t(const std::array<uint8_t, 16>& data) : _data(data) {}
+
893 uuid_t(const uuid_t&) = default;
+
894 uuid_t(uuid_t&&) noexcept = default;
+
895 ~uuid_t() = default;
+
896
+
897 uuid_t& operator=(const std::string& uuid)
+
898 { _data = uuid_t(uuid).data(); return *this; }
+
899 uuid_t& operator=(const std::array<uint8_t, 16>& data)
+
900 { _data = data; return *this; }
+
901 uuid_t& operator=(const uuid_t&) = default;
+
902 uuid_t& operator=(uuid_t&&) noexcept = default;
+
903
+
904 // UUID comparison
+
905 friend bool operator==(const uuid_t& uuid1, const uuid_t& uuid2)
+
906 { return uuid1._data == uuid2._data; }
+
907 friend bool operator!=(const uuid_t& uuid1, const uuid_t& uuid2)
+
908 { return uuid1._data != uuid2._data; }
+
909 friend bool operator<(const uuid_t& uuid1, const uuid_t& uuid2)
+
910 { return uuid1._data < uuid2._data; }
+
911 friend bool operator>(const uuid_t& uuid1, const uuid_t& uuid2)
+
912 { return uuid1._data > uuid2._data; }
+
913 friend bool operator<=(const uuid_t& uuid1, const uuid_t& uuid2)
+
914 { return uuid1._data <= uuid2._data; }
+
915 friend bool operator>=(const uuid_t& uuid1, const uuid_t& uuid2)
+
916 { return uuid1._data >= uuid2._data; }
+
917
+
919 explicit operator bool() const noexcept { return *this != nil(); }
+
920
+
922 std::array<uint8_t, 16>& data() noexcept { return _data; }
+
924 const std::array<uint8_t, 16>& data() const noexcept { return _data; }
+
925
+
927 std::string string() const;
+
928
+
930 static uuid_t nil() { return uuid_t(); }
+
932 static uuid_t sequential();
+
934 static uuid_t random();
+
935
+
937 friend std::ostream& operator<<(std::ostream& os, const uuid_t& uuid)
+
938 { os << uuid.string(); return os; }
+
939
+
940#if defined(LOGGING_PROTOCOL)
+
942 friend CppLogging::Record& operator<<(CppLogging::Record& record, const uuid_t& uuid);
+
943#endif
+
944
+
946 void swap(uuid_t& uuid) noexcept
+
947 { using std::swap; swap(_data, uuid._data); }
+
948 friend void swap(uuid_t& uuid1, uuid_t& uuid2) noexcept
+
949 { uuid1.swap(uuid2); }
+
950
+
951private:
+
952 std::array<uint8_t, 16> _data;
+
953};
+
954
+
955} // namespace FBE
+
956
+
957#if defined(FMT_VERSION) && (FMT_VERSION >= 90000)
+
958template <>
+
959struct fmt::formatter<FBE::uuid_t> : formatter<std::string_view>
+
960{
+
961 template <typename FormatContext>
+
962 auto format(const FBE::uuid_t& value, FormatContext& ctx) const
+
963 {
+
964 return formatter<string_view>::format(value.string(), ctx);
+
965 }
+
966};
+
967#endif
+
968
+
969template <>
+
970struct std::hash<FBE::uuid_t>
+
971{
+
972 typedef FBE::uuid_t argument_type;
+
973 typedef size_t result_type;
+
974
+
975 result_type operator() (const argument_type& value) const
+
976 {
+
977 result_type result = 17;
+
978 std::hash<uint8_t> hasher;
+
979 for (size_t i = 0; i < value.data().size(); ++i)
+
980 result = result * 31 + hasher(value.data()[i]);
+
981 return result;
+
982 }
+
983};
+
984
+
985namespace FBE {
+
986)CODE";
+
987
+
988 // Prepare code template
+
989 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
990
+
991 Write(code);
+
992}
+
993
+
994void GeneratorCpp::GenerateUUIDWrapper_Source()
+
995{
+
996 std::string code = R"CODE(
+
997uint8_t unhex(char ch)
+
998{
+
999 if ((ch >= '0') && (ch <= '9'))
+
1000 return ch - '0';
+
1001 else if ((ch >= 'a') && (ch <= 'f'))
+
1002 return 10 + ch - 'a';
+
1003 else if ((ch >= 'A') && (ch <= 'F'))
+
1004 return 10 + ch - 'A';
+
1005 else
+
1006 return 255;
+
1007}
+
1008
+
1009uuid_t::uuid_t(const std::string& uuid)
+
1010{
+
1011 char v1 = 0;
+
1012 char v2 = 0;
+
1013 bool pack = false;
+
1014 size_t index = 0;
+
1015
+
1016 // Parse UUID string
+
1017 for (auto ch : uuid)
+
1018 {
+
1019 if ((ch == '-') || (ch == '{') || (ch == '}'))
+
1020 continue;
+
1021
+
1022 if (pack)
+
1023 {
+
1024 v2 = ch;
+
1025 pack = false;
+
1026 uint8_t ui1 = unhex(v1);
+
1027 uint8_t ui2 = unhex(v2);
+
1028 if ((ui1 > 15) || (ui2 > 15))
+
1029 throw std::invalid_argument("Invalid UUID string: " + uuid);
+
1030 _data[index++] = ui1 * 16 + ui2;
+
1031 if (index >= 16)
+
1032 break;
+
1033 }
+
1034 else
+
1035 {
+
1036 v1 = ch;
+
1037 pack = true;
+
1038 }
+
1039 }
+
1040
+
1041 // Fill remaining data with zeros
+
1042 for (; index < 16; ++index)
+
1043 _data[index++] = 0;
+
1044}
+
1045
+
1046std::string uuid_t::string() const
+
1047{
+
1048 const char* digits = "0123456789abcdef";
+
1049
+
1050 std::string result(36, '0');
+
1051
+
1052 int index = 0;
+
1053 for (auto value : _data)
+
1054 {
+
1055 result[index++] = digits[(value >> 4) & 0x0F];
+
1056 result[index++] = digits[(value >> 0) & 0x0F];
+
1057 if ((index == 8) || (index == 13) || (index == 18) || (index == 23))
+
1058 result[index++] = '-';
+
1059 }
+
1060
+
1061 return result;
+
1062}
+
1063
+
1064uuid_t uuid_t::sequential()
+
1065{
+
1066 uuid_t result;
+
1067#if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
+
1068 ::uuid_t uuid;
+
1069 uuid_generate_time(uuid);
+
1070 result._data[0] = uuid[0];
+
1071 result._data[1] = uuid[1];
+
1072 result._data[2] = uuid[2];
+
1073 result._data[3] = uuid[3];
+
1074 result._data[4] = uuid[4];
+
1075 result._data[5] = uuid[5];
+
1076 result._data[6] = uuid[6];
+
1077 result._data[7] = uuid[7];
+
1078 result._data[8] = uuid[8];
+
1079 result._data[9] = uuid[9];
+
1080 result._data[10] = uuid[10];
+
1081 result._data[11] = uuid[11];
+
1082 result._data[12] = uuid[12];
+
1083 result._data[13] = uuid[13];
+
1084 result._data[14] = uuid[14];
+
1085 result._data[15] = uuid[15];
+
1086#elif defined(_WIN32) || defined(_WIN64)
+
1087 ::UUID uuid;
+
1088 if (UuidCreateSequential(&uuid) != RPC_S_OK)
+
1089 throw std::runtime_error("Cannot generate sequential UUID!");
+
1090
+
1091 result._data[0] = (uuid.Data1 >> 24) & 0xFF;
+
1092 result._data[1] = (uuid.Data1 >> 16) & 0xFF;
+
1093 result._data[2] = (uuid.Data1 >> 8) & 0xFF;
+
1094 result._data[3] = (uuid.Data1 >> 0) & 0xFF;
+
1095 result._data[4] = (uuid.Data2 >> 8) & 0xFF;
+
1096 result._data[5] = (uuid.Data2 >> 0) & 0xFF;
+
1097
+
1098 result._data[6] = (uuid.Data3 >> 8) & 0xFF;
+
1099 result._data[7] = (uuid.Data3 >> 0) & 0xFF;
+
1100
+
1101 result._data[8] = uuid.Data4[0];
+
1102 result._data[9] = uuid.Data4[1];
+
1103
+
1104 result._data[10] = uuid.Data4[2];
+
1105 result._data[11] = uuid.Data4[3];
+
1106 result._data[12] = uuid.Data4[4];
+
1107 result._data[13] = uuid.Data4[5];
+
1108 result._data[14] = uuid.Data4[6];
+
1109 result._data[15] = uuid.Data4[7];
+
1110#endif
+
1111 return result;
+
1112}
+
1113
+
1114uuid_t uuid_t::random()
+
1115{
+
1116 uuid_t result;
+
1117#if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
+
1118 ::uuid_t uuid;
+
1119 uuid_generate_random(uuid);
+
1120 result._data[0] = uuid[0];
+
1121 result._data[1] = uuid[1];
+
1122 result._data[2] = uuid[2];
+
1123 result._data[3] = uuid[3];
+
1124 result._data[4] = uuid[4];
+
1125 result._data[5] = uuid[5];
+
1126 result._data[6] = uuid[6];
+
1127 result._data[7] = uuid[7];
+
1128 result._data[8] = uuid[8];
+
1129 result._data[9] = uuid[9];
+
1130 result._data[10] = uuid[10];
+
1131 result._data[11] = uuid[11];
+
1132 result._data[12] = uuid[12];
+
1133 result._data[13] = uuid[13];
+
1134 result._data[14] = uuid[14];
+
1135 result._data[15] = uuid[15];
+
1136#elif defined(_WIN32) || defined(_WIN64)
+
1137 ::UUID uuid;
+
1138 if (UuidCreate(&uuid) != RPC_S_OK)
+
1139 throw std::runtime_error("Cannot generate random UUID!");
+
1140
+
1141 result._data[0] = (uuid.Data1 >> 24) & 0xFF;
+
1142 result._data[1] = (uuid.Data1 >> 16) & 0xFF;
+
1143 result._data[2] = (uuid.Data1 >> 8) & 0xFF;
+
1144 result._data[3] = (uuid.Data1 >> 0) & 0xFF;
+
1145 result._data[4] = (uuid.Data2 >> 8) & 0xFF;
+
1146 result._data[5] = (uuid.Data2 >> 0) & 0xFF;
+
1147
+
1148 result._data[6] = (uuid.Data3 >> 8) & 0xFF;
+
1149 result._data[7] = (uuid.Data3 >> 0) & 0xFF;
+
1150
+
1151 result._data[8] = uuid.Data4[0];
+
1152 result._data[9] = uuid.Data4[1];
+
1153
+
1154 result._data[10] = uuid.Data4[2];
+
1155 result._data[11] = uuid.Data4[3];
+
1156 result._data[12] = uuid.Data4[4];
+
1157 result._data[13] = uuid.Data4[5];
+
1158 result._data[14] = uuid.Data4[6];
+
1159 result._data[15] = uuid.Data4[7];
+
1160#endif
+
1161 return result;
+
1162}
+
1163
+
1164#if defined(LOGGING_PROTOCOL)
+
1165CppLogging::Record& operator<<(CppLogging::Record& record, const uuid_t& uuid)
+
1166{
+
1167 const char* digits = "0123456789abcdef";
+
1168
+
1169 std::array<char, 36> result;
+
1170
+
1171 int index = 0;
+
1172 for (auto value : uuid.data())
+
1173 {
+
1174 result[index++] = digits[(value >> 4) & 0x0F];
+
1175 result[index++] = digits[(value >> 0) & 0x0F];
+
1176 if ((index == 8) || (index == 13) || (index == 18) || (index == 23))
+
1177 result[index++] = '-';
+
1178 }
+
1179
+
1180 return record.StoreCustom(std::string_view(result.data(), result.size()));
+
1181}
+
1182#endif
+
1183)CODE";
+
1184
+
1185 // Prepare code template
+
1186 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
1187
+
1188 Write(code);
+
1189}
+
1190
+
1191void GeneratorCpp::GenerateFBEBuffer_Header()
+
1192{
+
1193 std::string code = R"CODE(
+
1194// Fast Binary Encoding buffer based on the dynamic byte buffer
+
1195class FBEBuffer
+
1196{
+
1197public:
+
1198 FBEBuffer() : _data(nullptr), _capacity(0), _size(0), _offset(0) {}
+
1199 // Initialize the read buffer with the given byte buffer and offset
+
1200 explicit FBEBuffer(const void* data, size_t size, size_t offset = 0) { attach(data, size, offset); }
+
1201 // Initialize the read buffer with the given byte vector and offset
+
1202 explicit FBEBuffer(const std::vector<uint8_t>& buffer, size_t offset = 0) { attach(buffer, offset); }
+
1203 // Initialize the read buffer with another buffer and offset
+
1204 explicit FBEBuffer(const FBEBuffer& buffer, size_t offset = 0) { attach(buffer.data(), buffer.size(), offset); }
+
1205 // Initialize the write buffer with the given capacity
+
1206 explicit FBEBuffer(size_t capacity) : FBEBuffer() { reserve(capacity); }
+
1207 FBEBuffer(const FBEBuffer&) = delete;
+
1208 FBEBuffer(FBEBuffer&&) noexcept = delete;
+
1209 ~FBEBuffer() { if (_capacity > 0) std::free(_data); }
+
1210
+
1211 FBEBuffer& operator=(const FBEBuffer&) = delete;
+
1212 FBEBuffer& operator=(FBEBuffer&&) noexcept = delete;
+
1213
+
1214 bool empty() const noexcept { return (_data == nullptr) || (_size == 0); }
+
1215 const uint8_t* data() const noexcept { return _data; }
+
1216 uint8_t* data() noexcept { return _data; }
+
1217 size_t capacity() const noexcept { return _capacity; }
+
1218 size_t size() const noexcept { return _size; }
+
1219 size_t offset() const noexcept { return _offset; }
+
1220
+
1221 // Attach the given buffer with a given offset to the current read buffer
+
1222 void attach(const void* data, size_t size, size_t offset = 0);
+
1223 // Attach the given byte vector with a given offset to the current read buffer
+
1224 void attach(const std::vector<uint8_t>& buffer, size_t offset = 0);
+
1225
+
1226 // Clone the given buffer with a given offset to the current buffer
+
1227 void clone(const void* data, size_t size, size_t offset = 0);
+
1228 // Clone the given vector with a given offset to the current buffer
+
1229 void clone(const std::vector<uint8_t>& buffer, size_t offset = 0);
+
1230
+
1231 // Allocate memory in the current write buffer and return offset to the allocated memory block
+
1232 size_t allocate(size_t size);
+
1233 // Remove some memory of the given size from the current write buffer
+
1234 void remove(size_t offset, size_t size);
+
1235 // Reserve memory of the given capacity in the current write buffer
+
1236 void reserve(size_t capacity);
+
1237 // Resize the current write buffer
+
1238 void resize(size_t size);
+
1239 // Reset the current write buffer and its offset
+
1240 void reset();
+
1241
+
1242 // Shift the current write buffer offset
+
1243 void shift(size_t offset) { _offset += offset; }
+
1244 // Unshift the current write buffer offset
+
1245 void unshift(size_t offset) { _offset -= offset; }
+
1246
+
1247private:
+
1248 uint8_t* _data;
+
1249 size_t _capacity;
+
1250 size_t _size;
+
1251 size_t _offset;
+
1252};
+
1253)CODE";
+
1254
+
1255 // Prepare code template
+
1256 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
1257
+
1258 Write(code);
+
1259}
+
1260
+
1261void GeneratorCpp::GenerateFBEBuffer_Source()
+
1262{
+
1263 std::string code = R"CODE(
+
1264void FBEBuffer::attach(const void* data, size_t size, size_t offset)
+
1265{
+
1266 assert((data != nullptr) && "Invalid buffer!");
+
1267 if (data == nullptr)
+
1268 throw std::invalid_argument("Invalid buffer!");
+
1269 assert((size > 0) && "Invalid size!");
+
1270 if (size == 0)
+
1271 throw std::invalid_argument("Invalid size!");
+
1272 assert((offset <= size) && "Invalid offset!");
+
1273 if (offset > size)
+
1274 throw std::invalid_argument("Invalid offset!");
+
1275
+
1276 _data = (uint8_t*)data;
+
1277 _capacity = 0;
+
1278 _size = size;
+
1279 _offset = offset;
+
1280}
+
1281
+
1282void FBEBuffer::attach(const std::vector<uint8_t>& buffer, size_t offset)
+
1283{
+
1284 assert((buffer.data() != nullptr) && "Invalid buffer!");
+
1285 if (buffer.data() == nullptr)
+
1286 throw std::invalid_argument("Invalid buffer!");
+
1287 assert((buffer.size() > 0) && "Invalid size!");
+
1288 if (buffer.size() == 0)
+
1289 throw std::invalid_argument("Invalid size!");
+
1290 assert((offset <= buffer.size()) && "Invalid offset!");
+
1291 if (offset > buffer.size())
+
1292 throw std::invalid_argument("Invalid offset!");
+
1293
+
1294 _data = (uint8_t*)buffer.data();
+
1295 _capacity = 0;
+
1296 _size = buffer.size();
+
1297 _offset = offset;
+
1298}
+
1299
+
1300void FBEBuffer::clone(const void* data, size_t size, size_t offset)
+
1301{
+
1302 assert((offset <= size) && "Invalid offset!");
+
1303 if (offset > size)
+
1304 throw std::invalid_argument("Invalid offset!");
+
1305
+
1306 reserve(size);
+
1307 std::memcpy(_data, data, size);
+
1308 _capacity = size;
+
1309 _size = size;
+
1310 _offset = offset;
+
1311}
+
1312
+
1313void FBEBuffer::clone(const std::vector<uint8_t>& buffer, size_t offset)
+
1314{
+
1315 assert((offset <= buffer.size()) && "Invalid offset!");
+
1316 if (offset > buffer.size())
+
1317 throw std::invalid_argument("Invalid offset!");
+
1318
+
1319 size_t size = buffer.size();
+
1320
+
1321 reserve(size);
+
1322 std::memcpy(_data, buffer.data(), size);
+
1323 _capacity = size;
+
1324 _size = size;
+
1325 _offset = offset;
+
1326}
+
1327
+
1328size_t FBEBuffer::allocate(size_t size)
+
1329{
+
1330 size_t offset = _size;
+
1331
+
1332 // Calculate a new buffer size
+
1333 size_t total = _size + size;
+
1334
+
1335 if (total <= _capacity)
+
1336 {
+
1337 _size = total;
+
1338 return offset;
+
1339 }
+
1340
+
1341 _capacity = std::max(total, 2 * _capacity);
+
1342 uint8_t* data = (uint8_t*)std::malloc(_capacity);
+
1343 std::memcpy(data, _data, _size);
+
1344 std::free(_data);
+
1345 _data = data;
+
1346 _size = total;
+
1347 return offset;
+
1348}
+
1349
+
1350void FBEBuffer::remove(size_t offset, size_t size)
+
1351{
+
1352 assert(((offset + size) <= _size) && "Invalid offset & size!");
+
1353 if ((offset + size) > _size)
+
1354 throw std::invalid_argument("Invalid offset & size!");
+
1355
+
1356 std::memcpy(_data + offset, _data + offset + size, _size - size - offset);
+
1357 _size -= size;
+
1358 if (_offset >= (offset + size))
+
1359 _offset -= size;
+
1360 else if (_offset >= offset)
+
1361 {
+
1362 _offset -= _offset - offset;
+
1363 if (_offset > _size)
+
1364 _offset = _size;
+
1365 }
+
1366}
+
1367
+
1368void FBEBuffer::reserve(size_t capacity)
+
1369{
+
1370 if (capacity > _capacity)
+
1371 {
+
1372 _capacity = std::max(capacity, 2 * _capacity);
+
1373 uint8_t* data = (uint8_t*)std::malloc(_capacity);
+
1374 std::memcpy(data, _data, _size);
+
1375 std::free(_data);
+
1376 _data = data;
+
1377 }
+
1378}
+
1379
+
1380void FBEBuffer::resize(size_t size)
+
1381{
+
1382 reserve(size);
+
1383 _size = size;
+
1384 if (_offset > _size)
+
1385 _offset = _size;
+
1386}
+
1387
+
1388void FBEBuffer::reset()
+
1389{
+
1390 _size = 0;
+
1391 _offset = 0;
+
1392}
+
1393)CODE";
+
1394
+
1395 // Prepare code template
+
1396 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
1397
+
1398 Write(code);
+
1399}
+
1400
+
1401void GeneratorCpp::GenerateFBEBaseModel_Header()
+
1402{
+
1403 std::string code = R"CODE(
+
1404// Fast Binary Encoding base model
+
1405class Model
+
1406{
+
1407public:
+
1408 Model() : Model(nullptr) {}
+
1409 Model(const std::shared_ptr<FBEBuffer>& buffer) { _buffer = buffer ? buffer : std::make_shared<FBEBuffer>(); }
+
1410 Model(const Model&) = default;
+
1411 Model(Model&&) noexcept = default;
+
1412 ~Model() = default;
+
1413
+
1414 Model& operator=(const Model&) = default;
+
1415 Model& operator=(Model&&) noexcept = default;
+
1416
+
1417 // Get the model buffer
+
1418 FBEBuffer& buffer() noexcept { return *_buffer; }
+
1419 const FBEBuffer& buffer() const noexcept { return *_buffer; }
+
1420
+
1421 // Attach the model buffer
+
1422 void attach(const void* data, size_t size, size_t offset = 0) { _buffer->attach(data, size, offset); }
+
1423 void attach(const std::vector<uint8_t>& buffer, size_t offset = 0) { _buffer->attach(buffer, offset); }
+
1424 void attach(const FBEBuffer& buffer, size_t offset = 0) { _buffer->attach(buffer.data(), buffer.size(), offset); }
+
1425
+
1426 // Model buffer operations
+
1427 size_t allocate(size_t size) { return _buffer->allocate(size); }
+
1428 void remove(size_t offset, size_t size) { _buffer->remove(offset, size); }
+
1429 void reserve(size_t capacity) { _buffer->reserve(capacity); }
+
1430 void resize(size_t size) { _buffer->resize(size); }
+
1431 void reset() { _buffer->reset(); }
+
1432 void shift(size_t offset) { _buffer->shift(offset); }
+
1433 void unshift(size_t offset) { _buffer->unshift(offset); }
+
1434
+
1435private:
+
1436 std::shared_ptr<FBEBuffer> _buffer;
+
1437};
+
1438)CODE";
+
1439
+
1440 // Prepare code template
+
1441 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
1442
+
1443 Write(code);
+
1444}
+
1445
+
1446void GeneratorCpp::GenerateFBEFieldModel_Header()
+
1447{
+
1448 std::string code = R"CODE(
+
1449// Fast Binary Encoding base field model
+
1450template <typename T, typename TBase = T>
+
1451class FieldModelBase
+
1452{
+
1453public:
+
1454 FieldModelBase(FBEBuffer& buffer, size_t offset) noexcept : _buffer(buffer), _offset(offset) {}
+
1455
+
1456 // Get the field offset
+
1457 size_t fbe_offset() const noexcept { return _offset; }
+
1458 // Get the field size
+
1459 size_t fbe_size() const noexcept { return sizeof(TBase); }
+
1460 // Get the field extra size
+
1461 size_t fbe_extra() const noexcept { return 0; }
+
1462
+
1463 // Shift the current field offset
+
1464 void fbe_shift(size_t size) noexcept { _offset += size; }
+
1465 // Unshift the current field offset
+
1466 void fbe_unshift(size_t size) noexcept { _offset -= size; }
+
1467
+
1468 // Check if the value is valid
+
1469 bool verify() const noexcept { return true; }
+
1470
+
1471 // Get the field value
+
1472 void get(T& value, T defaults = (T)0) const noexcept;
+
1473 // Set the field value
+
1474 void set(T value) noexcept;
+
1475
+
1476private:
+
1477 FBEBuffer& _buffer;
+
1478 size_t _offset;
+
1479};
+
1480
+
1481// Fast Binary Encoding field model
+
1482template <typename T>
+
1483class FieldModel : public FieldModelBase<T>
+
1484{
+
1485public:
+
1486 using FieldModelBase<T>::FieldModelBase;
+
1487};
+
1488
+
1489// Fast Binary Encoding field model bool specialization
+
1490template <>
+
1491class FieldModel<bool> : public FieldModelBase<bool, uint8_t>
+
1492{
+
1493public:
+
1494 using FieldModelBase<bool, uint8_t>::FieldModelBase;
+
1495};
+
1496
+
1497// Fast Binary Encoding field model char specialization
+
1498template <>
+
1499class FieldModel<char> : public FieldModelBase<char, uint8_t>
+
1500{
+
1501public:
+
1502 using FieldModelBase<char, uint8_t>::FieldModelBase;
+
1503};
+
1504
+
1505// Fast Binary Encoding field model wchar specialization
+
1506template <>
+
1507class FieldModel<wchar_t> : public FieldModelBase<wchar_t, uint32_t>
+
1508{
+
1509public:
+
1510 using FieldModelBase<wchar_t, uint32_t>::FieldModelBase;
+
1511};
+
1512)CODE";
+
1513
+
1514 // Prepare code template
+
1515 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
1516
+
1517 Write(code);
+
1518}
+
1519
+
1520void GeneratorCpp::GenerateFBEFieldModel_Inline()
+
1521{
+
1522 std::string code = R"CODE(
+
1523template <typename T, typename TBase>
+
1524inline void FieldModelBase<T, TBase>::get(T& value, T defaults) const noexcept
+
1525{
+
1526 if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size())
+
1527 {
+
1528 value = defaults;
+
1529 return;
+
1530 }
+
1531
+
1532 value = (T)(*((const TBase*)(_buffer.data() + _buffer.offset() + fbe_offset())));
+
1533}
+
1534
+
1535template <typename T, typename TBase>
+
1536inline void FieldModelBase<T, TBase>::set(T value) noexcept
+
1537{
+
1538 assert(((_buffer.offset() + fbe_offset() + fbe_size()) <= _buffer.size()) && "Model is broken!");
+
1539 if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size())
+
1540 return;
+
1541
+
1542 *((TBase*)(_buffer.data() + _buffer.offset() + fbe_offset())) = (TBase)value;
+
1543}
+
1544)CODE";
+
1545
+
1546 // Prepare code template
+
1547 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
1548
+
1549 Write(code);
+
1550}
+
1551
+
1552void GeneratorCpp::GenerateFBEFieldModelDecimal_Header()
+
1553{
+
1554 std::string code = R"CODE(
+
1555// Fast Binary Encoding field model decimal specialization
+
1556template <>
+
1557class FieldModel<decimal_t>
+
1558{
+
1559public:
+
1560 FieldModel(FBEBuffer& buffer, size_t offset) noexcept : _buffer(buffer), _offset(offset) {}
+
1561
+
1562 // Get the field offset
+
1563 size_t fbe_offset() const noexcept { return _offset; }
+
1564 // Get the field size
+
1565 size_t fbe_size() const noexcept { return 16; }
+
1566 // Get the field extra size
+
1567 size_t fbe_extra() const noexcept { return 0; }
+
1568
+
1569 // Shift the current field offset
+
1570 void fbe_shift(size_t size) noexcept { _offset += size; }
+
1571 // Unshift the current field offset
+
1572 void fbe_unshift(size_t size) noexcept { _offset -= size; }
+
1573
+
1574 // Check if the decimal value is valid
+
1575 bool verify() const noexcept { return true; }
+
1576
+
1577 // Get the decimal value
+
1578 void get(decimal_t& value, decimal_t defaults = decimal_t()) const noexcept;
+
1579 // Set the decimal value
+
1580 void set(decimal_t value) noexcept;
+
1581
+
1582private:
+
1583 FBEBuffer& _buffer;
+
1584 size_t _offset;
+
1585
+
1586 static uint64_t extract(double a) noexcept;
+
1587 static uint64_t uint32x32(uint32_t a, uint32_t b) noexcept;
+
1588 static void uint64x64(uint64_t a, uint64_t b, uint64_t& low64, uint32_t& high32) noexcept;
+
1589};
+
1590)CODE";
+
1591
+
1592 // Prepare code template
+
1593 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
1594
+
1595 Write(code);
+
1596}
+
1597
+
1598void GeneratorCpp::GenerateFBEFieldModelDecimal_Source()
+
1599{
+
1600 std::string code = R"CODE(
+
1601uint64_t FieldModel<decimal_t>::extract(double a) noexcept
+
1602{
+
1603 uint64_t result;
+
1604 std::memcpy(&result, &a, sizeof(double));
+
1605 return result;
+
1606}
+
1607
+
1608uint64_t FieldModel<decimal_t>::uint32x32(uint32_t a, uint32_t b) noexcept
+
1609{
+
1610 return (uint64_t)a * (uint64_t)b;
+
1611}
+
1612
+
1613void FieldModel<decimal_t>::uint64x64(uint64_t a, uint64_t b, uint64_t& low64, uint32_t& high32) noexcept
+
1614{
+
1615 uint64_t low = uint32x32((uint32_t)a, (uint32_t)b);
+
1616 uint64_t mid = uint32x32((uint32_t)a, (uint32_t)(b >> 32));
+
1617 uint64_t high = uint32x32((uint32_t)(a >> 32), (uint32_t)(b >> 32));
+
1618 high += (mid >> 32);
+
1619 low += (mid <<= 32);
+
1620 // Test for carry
+
1621 if (low < mid)
+
1622 high++;
+
1623
+
1624 mid = uint32x32((uint32_t)(a >> 32), (uint32_t)b);
+
1625 high += (mid >> 32);
+
1626 low += (mid <<= 32);
+
1627 // Test for carry
+
1628 if (low < mid)
+
1629 high++;
+
1630
+
1631 if (high > 0xFFFFFFFFu)
+
1632 {
+
1633 low64 = 0;
+
1634 high32 = 0;
+
1635 }
+
1636 low64 = low;
+
1637 high32 = (uint32_t)high;
+
1638}
+
1639
+
1640void FieldModel<decimal_t>::get(decimal_t& value, decimal_t defaults) const noexcept
+
1641{
+
1642 if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size())
+
1643 {
+
1644 value = defaults;
+
1645 return;
+
1646 }
+
1647
+
1648 // Value taken via reverse engineering the double that corresponds to 2^64
+
1649 const double ds2to64 = 1.8446744073709552e+019;
+
1650
+
1651 // Read decimal parts
+
1652 uint64_t low = *((const uint64_t*)(_buffer.data() + _buffer.offset() + fbe_offset()));
+
1653 uint32_t high = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset() + 8));
+
1654 uint32_t flags = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset() + 12));
+
1655
+
1656 // Calculate decimal value
+
1657 double dValue = ((double)low + (double)high * ds2to64) / pow(10.0, (uint8_t)(flags >> 16));
+
1658 if (flags & 0x80000000)
+
1659 dValue = -dValue;
+
1660
+
1661 value = dValue;
+
1662}
+
1663
+
1664void FieldModel<decimal_t>::set(decimal_t value) noexcept
+
1665{
+
1666 assert(((_buffer.offset() + fbe_offset() + fbe_size()) <= _buffer.size()) && "Model is broken!");
+
1667 if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size())
+
1668 return;
+
1669
+
1670 // The most we can scale by is 10^28, which is just slightly more
+
1671 // than 2^93. So a float with an exponent of -94 could just
+
1672 // barely reach 0.5, but smaller exponents will always round to zero.
+
1673 const uint32_t DBLBIAS = 1022;
+
1674
+
1675 // Get exponent value
+
1676 double dValue = (double)value;
+
1677 int32_t iExp = (int32_t)(((uint32_t)(extract(dValue) >> 52) & 0x7FFu) - DBLBIAS);
+
1678 if ((iExp < -94) || (iExp > 96))
+
1679 {
+
1680 // Value too big for .NET Decimal (exponent is limited to [-94, 96])
+
1681 memset((uint8_t*)(_buffer.data() + _buffer.offset() + fbe_offset()), 0, 16);
+
1682 return;
+
1683 }
+
1684
+
1685 uint32_t flags = 0;
+
1686 if (dValue < 0)
+
1687 {
+
1688 dValue = -dValue;
+
1689 flags = 0x80000000;
+
1690 }
+
1691
+
1692 // Round the input to a 15-digit integer. The R8 format has
+
1693 // only 15 digits of precision, and we want to keep garbage digits
+
1694 // out of the Decimal were making.
+
1695
+
1696 // Calculate max power of 10 input value could have by multiplying
+
1697 // the exponent by log10(2). Using scaled integer multiplcation,
+
1698 // log10(2) * 2 ^ 16 = .30103 * 65536 = 19728.3.
+
1699 int32_t iPower = 14 - ((iExp * 19728) >> 16);
+
1700
+
1701 // iPower is between -14 and 43
+
1702 if (iPower >= 0)
+
1703 {
+
1704 // We have less than 15 digits, scale input up.
+
1705 if (iPower > 28)
+
1706 iPower = 28;
+
1707
+
1708 dValue *= pow(10.0, iPower);
+
1709 }
+
1710 else
+
1711 {
+
1712 if ((iPower != -1) || (dValue >= 1E15))
+
1713 dValue /= pow(10.0, -iPower);
+
1714 else
+
1715 iPower = 0; // didn't scale it
+
1716 }
+
1717
+
1718 assert(dValue < 1E15);
+
1719 if ((dValue < 1E14) && (iPower < 28))
+
1720 {
+
1721 dValue *= 10;
+
1722 iPower++;
+
1723 assert(dValue >= 1E14);
+
1724 }
+
1725
+
1726 // Round to int64
+
1727 uint64_t ulMant;
+
1728 ulMant = (uint64_t)(int64_t)dValue;
+
1729 dValue -= (int64_t)ulMant; // difference between input & integer
+
1730 if ((dValue > 0.5) || ((dValue == 0.5) && ((ulMant & 1) != 0)))
+
1731 ulMant++;
+
1732
+
1733 if (ulMant == 0)
+
1734 {
+
1735 // Mantissa is 0
+
1736 memset((uint8_t*)(_buffer.data() + _buffer.offset() + fbe_offset()), 0, 16);
+
1737 return;
+
1738 }
+
1739
+
1740 if (iPower < 0)
+
1741 {
+
1742 // Add -iPower factors of 10, -iPower <= (29 - 15) = 14
+
1743 iPower = -iPower;
+
1744 if (iPower < 10)
+
1745 {
+
1746 double pow10 = (double)powl(10.0, iPower);
+
1747 uint64_t low64 = uint32x32((uint32_t)ulMant, (uint32_t)pow10);
+
1748 uint64_t high64 = uint32x32((uint32_t)(ulMant >> 32), (uint32_t)pow10);
+
1749 *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())) = (uint32_t)low64;
+
1750 high64 += low64 >> 32;
+
1751 *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset() + 4)) = (uint32_t)high64;
+
1752 high64 >>= 32;
+
1753 *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset() + 8)) = (uint32_t)high64;
+
1754 }
+
1755 else
+
1756 {
+
1757 // Have a big power of 10.
+
1758 assert(iPower <= 14);
+
1759 uint64_t low64;
+
1760 uint32_t high32;
+
1761 uint64x64(ulMant, (uint64_t)pow(10.0, iPower), low64, high32);
+
1762 *((uint64_t*)(_buffer.data() + _buffer.offset() + fbe_offset())) = low64;
+
1763 *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset() + 8)) = high32;
+
1764 }
+
1765 }
+
1766 else
+
1767 {
+
1768 // Factor out powers of 10 to reduce the scale, if possible.
+
1769 // The maximum number we could factor out would be 14. This
+
1770 // comes from the fact we have a 15-digit number, and the
+
1771 // MSD must be non-zero -- but the lower 14 digits could be
+
1772 // zero. Note also the scale factor is never negative, so
+
1773 // we can't scale by any more than the power we used to
+
1774 // get the integer.
+
1775 int lmax = iPower;
+
1776 if (lmax > 14)
+
1777 lmax = 14;
+
1778
+
1779 if ((((uint8_t)ulMant) == 0) && (lmax >= 8))
+
1780 {
+
1781 const uint32_t den = 100000000;
+
1782 uint64_t div = ulMant / den;
+
1783 if ((uint32_t)ulMant == (uint32_t)(div * den))
+
1784 {
+
1785 ulMant = div;
+
1786 iPower -= 8;
+
1787 lmax -= 8;
+
1788 }
+
1789 }
+
1790
+
1791 if ((((uint32_t)ulMant & 0xF) == 0) && (lmax >= 4))
+
1792 {
+
1793 const uint32_t den = 10000;
+
1794 uint64_t div = ulMant / den;
+
1795 if ((uint32_t)ulMant == (uint32_t)(div * den))
+
1796 {
+
1797 ulMant = div;
+
1798 iPower -= 4;
+
1799 lmax -= 4;
+
1800 }
+
1801 }
+
1802
+
1803 if ((((uint32_t)ulMant & 3) == 0) && (lmax >= 2))
+
1804 {
+
1805 const uint32_t den = 100;
+
1806 uint64_t div = ulMant / den;
+
1807 if ((uint32_t)ulMant == (uint32_t)(div * den))
+
1808 {
+
1809 ulMant = div;
+
1810 iPower -= 2;
+
1811 lmax -= 2;
+
1812 }
+
1813 }
+
1814
+
1815 if ((((uint32_t)ulMant & 1) == 0) && (lmax >= 1))
+
1816 {
+
1817 const uint32_t den = 10;
+
1818 uint64_t div = ulMant / den;
+
1819 if ((uint32_t)ulMant == (uint32_t)(div * den))
+
1820 {
+
1821 ulMant = div;
+
1822 iPower--;
+
1823 }
+
1824 }
+
1825
+
1826 flags |= (uint32_t)iPower << 16;
+
1827
+
1828 *((uint64_t*)(_buffer.data() + _buffer.offset() + fbe_offset())) = ulMant;
+
1829 *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset() + 8)) = 0;
+
1830 }
+
1831
+
1832 *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset() + 12)) = flags;
+
1833}
+
1834)CODE";
+
1835
+
1836 // Prepare code template
+
1837 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
1838
+
1839 Write(code);
+
1840}
+
1841
+
1842void GeneratorCpp::GenerateFBEFieldModelUUID_Header()
+
1843{
+
1844 std::string code = R"CODE(
+
1845// Fast Binary Encoding field model UUID specialization
+
1846template <>
+
1847class FieldModel<uuid_t>
+
1848{
+
1849public:
+
1850 FieldModel(FBEBuffer& buffer, size_t offset) noexcept : _buffer(buffer), _offset(offset) {}
+
1851
+
1852 // Get the field offset
+
1853 size_t fbe_offset() const noexcept { return _offset; }
+
1854 // Get the field size
+
1855 size_t fbe_size() const noexcept { return 16; }
+
1856 // Get the field extra size
+
1857 size_t fbe_extra() const noexcept { return 0; }
+
1858
+
1859 // Shift the current field offset
+
1860 void fbe_shift(size_t size) noexcept { _offset += size; }
+
1861 // Unshift the current field offset
+
1862 void fbe_unshift(size_t size) noexcept { _offset -= size; }
+
1863
+
1864 // Check if the UUID value is valid
+
1865 bool verify() const noexcept { return true; }
+
1866
+
1867 // Get the UUID value
+
1868 void get(uuid_t& value, uuid_t defaults = uuid_t::nil()) const noexcept;
+
1869 // Set the UUID value
+
1870 void set(uuid_t value) noexcept;
+
1871
+
1872private:
+
1873 FBEBuffer& _buffer;
+
1874 size_t _offset;
+
1875};
+
1876)CODE";
+
1877
+
1878 // Prepare code template
+
1879 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
1880
+
1881 Write(code);
+
1882}
+
1883
+
1884void GeneratorCpp::GenerateFBEFieldModelUUID_Source()
+
1885{
+
1886 std::string code = R"CODE(
+
1887void FieldModel<uuid_t>::get(uuid_t& value, uuid_t defaults) const noexcept
+
1888{
+
1889 if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size())
+
1890 {
+
1891 value = defaults;
+
1892 return;
+
1893 }
+
1894
+
1895 std::memcpy(value.data().data(), (const uint8_t*)(_buffer.data() + _buffer.offset() + fbe_offset()), fbe_size());
+
1896}
+
1897
+
1898void FieldModel<uuid_t>::set(uuid_t value) noexcept
+
1899{
+
1900 assert(((_buffer.offset() + fbe_offset() + fbe_size()) <= _buffer.size()) && "Model is broken!");
+
1901 if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size())
+
1902 return;
+
1903
+
1904 std::memcpy((uint8_t*)(_buffer.data() + _buffer.offset() + fbe_offset()), value.data().data(), fbe_size());
+
1905}
+
1906)CODE";
+
1907
+
1908 // Prepare code template
+
1909 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
1910
+
1911 Write(code);
+
1912}
+
1913
+
1914void GeneratorCpp::GenerateFBEFieldModelBytes_Header()
+
1915{
+
1916 std::string code = R"CODE(
+
1917// Fast Binary Encoding field model bytes specialization
+
1918template <>
+
1919class FieldModel<buffer_t>
+
1920{
+
1921public:
+
1922 FieldModel(FBEBuffer& buffer, size_t offset) noexcept : _buffer(buffer), _offset(offset) {}
+
1923
+
1924 // Get the field offset
+
1925 size_t fbe_offset() const noexcept { return _offset; }
+
1926 // Get the field size
+
1927 size_t fbe_size() const noexcept { return 4; }
+
1928 // Get the field extra size
+
1929 size_t fbe_extra() const noexcept;
+
1930
+
1931 // Shift the current field offset
+
1932 void fbe_shift(size_t size) noexcept { _offset += size; }
+
1933 // Unshift the current field offset
+
1934 void fbe_unshift(size_t size) noexcept { _offset -= size; }
+
1935
+
1936 // Check if the bytes value is valid
+
1937 bool verify() const noexcept;
+
1938
+
1939 // Get the bytes value
+
1940 size_t get(void* data, size_t size) const noexcept;
+
1941 // Get the bytes value
+
1942 template <size_t N>
+
1943 size_t get(uint8_t (&data)[N]) const noexcept { return get(data, N); }
+
1944 // Get the bytes value
+
1945 template <size_t N>
+
1946 size_t get(std::array<uint8_t, N>& data) const noexcept { return get(data.data(), data.size()); }
+
1947 // Get the bytes value
+
1948 void get(std::vector<uint8_t>& value) const noexcept;
+
1949 // Get the bytes value
+
1950 void get(buffer_t& value) const noexcept { get(value.buffer()); }
+
1951
+
1952 // Set the bytes value
+
1953 void set(const void* data, size_t size);
+
1954 // Set the bytes value
+
1955 template <size_t N>
+
1956 void set(const uint8_t (&data)[N]) { set(data, N); }
+
1957 // Set the bytes value
+
1958 template <size_t N>
+
1959 void set(const std::array<uint8_t, N>& data) { set(data.data(), data.size()); }
+
1960 // Set the bytes value
+
1961 void set(const std::vector<uint8_t>& value) { set(value.data(), value.size()); }
+
1962 // Set the bytes value
+
1963 void set(const buffer_t& value) { set(value.buffer()); }
+
1964
+
1965private:
+
1966 FBEBuffer& _buffer;
+
1967 size_t _offset;
+
1968};
+
1969)CODE";
+
1970
+
1971 // Prepare code template
+
1972 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
1973
+
1974 Write(code);
+
1975}
+
1976
+
1977void GeneratorCpp::GenerateFBEFieldModelBytes_Source()
+
1978{
+
1979 std::string code = R"CODE(
+
1980size_t FieldModel<buffer_t>::fbe_extra() const noexcept
+
1981{
+
1982 if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size())
+
1983 return 0;
+
1984
+
1985 uint32_t fbe_bytes_offset = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset()));
+
1986 if ((fbe_bytes_offset == 0) || ((_buffer.offset() + fbe_bytes_offset + 4) > _buffer.size()))
+
1987 return 0;
+
1988
+
1989 uint32_t fbe_bytes_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_bytes_offset));
+
1990 return (size_t)(4 + fbe_bytes_size);
+
1991}
+
1992
+
1993bool FieldModel<buffer_t>::verify() const noexcept
+
1994{
+
1995 if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size())
+
1996 return true;
+
1997
+
1998 uint32_t fbe_bytes_offset = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset()));
+
1999 if (fbe_bytes_offset == 0)
+
2000 return true;
+
2001
+
2002 if ((_buffer.offset() + fbe_bytes_offset + 4) > _buffer.size())
+
2003 return false;
+
2004
+
2005 uint32_t fbe_bytes_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_bytes_offset));
+
2006 if ((_buffer.offset() + fbe_bytes_offset + 4 + fbe_bytes_size) > _buffer.size())
+
2007 return false;
+
2008
+
2009 return true;
+
2010}
+
2011
+
2012size_t FieldModel<buffer_t>::get(void* data, size_t size) const noexcept
+
2013{
+
2014 assert(((size == 0) || (data != nullptr)) && "Invalid buffer!");
+
2015 if ((size > 0) && (data == nullptr))
+
2016 return 0;
+
2017
+
2018 if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size())
+
2019 return 0;
+
2020
+
2021 uint32_t fbe_bytes_offset = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset()));
+
2022 if (fbe_bytes_offset == 0)
+
2023 return 0;
+
2024
+
2025 assert(((_buffer.offset() + fbe_bytes_offset + 4) <= _buffer.size()) && "Model is broken!");
+
2026 if ((_buffer.offset() + fbe_bytes_offset + 4) > _buffer.size())
+
2027 return 0;
+
2028
+
2029 uint32_t fbe_bytes_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_bytes_offset));
+
2030 assert(((_buffer.offset() + fbe_bytes_offset + 4 + fbe_bytes_size) <= _buffer.size()) && "Model is broken!");
+
2031 if ((_buffer.offset() + fbe_bytes_offset + 4 + fbe_bytes_size) > _buffer.size())
+
2032 return 0;
+
2033
+
2034 size_t result = std::min(size, (size_t)fbe_bytes_size);
+
2035 memcpy(data, (const char*)(_buffer.data() + _buffer.offset() + fbe_bytes_offset + 4), result);
+
2036 return result;
+
2037}
+
2038
+
2039void FieldModel<buffer_t>::get(std::vector<uint8_t>& value) const noexcept
+
2040{
+
2041 value.clear();
+
2042
+
2043 if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size())
+
2044 return;
+
2045
+
2046 uint32_t fbe_bytes_offset = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset()));
+
2047 if (fbe_bytes_offset == 0)
+
2048 return;
+
2049
+
2050 assert(((_buffer.offset() + fbe_bytes_offset + 4) <= _buffer.size()) && "Model is broken!");
+
2051 if ((_buffer.offset() + fbe_bytes_offset + 4) > _buffer.size())
+
2052 return;
+
2053
+
2054 uint32_t fbe_bytes_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_bytes_offset));
+
2055 assert(((_buffer.offset() + fbe_bytes_offset + 4 + fbe_bytes_size) <= _buffer.size()) && "Model is broken!");
+
2056 if ((_buffer.offset() + fbe_bytes_offset + 4 + fbe_bytes_size) > _buffer.size())
+
2057 return;
+
2058
+
2059 const char* fbe_bytes = (const char*)(_buffer.data() + _buffer.offset() + fbe_bytes_offset + 4);
+
2060 value.assign(fbe_bytes, fbe_bytes + fbe_bytes_size);
+
2061}
+
2062
+
2063void FieldModel<buffer_t>::set(const void* data, size_t size)
+
2064{
+
2065 assert(((size == 0) || (data != nullptr)) && "Invalid buffer!");
+
2066 if ((size > 0) && (data == nullptr))
+
2067 return;
+
2068
+
2069 assert(((_buffer.offset() + fbe_offset() + fbe_size()) <= _buffer.size()) && "Model is broken!");
+
2070 if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size())
+
2071 return;
+
2072
+
2073 uint32_t fbe_bytes_size = (uint32_t)size;
+
2074 uint32_t fbe_bytes_offset = (uint32_t)(_buffer.allocate(4 + fbe_bytes_size) - _buffer.offset());
+
2075 assert(((fbe_bytes_offset > 0) && ((_buffer.offset() + fbe_bytes_offset + 4 + fbe_bytes_size) <= _buffer.size())) && "Model is broken!");
+
2076 if ((fbe_bytes_offset == 0) || ((_buffer.offset() + fbe_bytes_offset + 4 + fbe_bytes_size) > _buffer.size()))
+
2077 return;
+
2078
+
2079 *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())) = fbe_bytes_offset;
+
2080 *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_bytes_offset)) = fbe_bytes_size;
+
2081
+
2082 memcpy((char*)(_buffer.data() + _buffer.offset() + fbe_bytes_offset + 4), data, fbe_bytes_size);
+
2083}
+
2084)CODE";
+
2085
+
2086 // Prepare code template
+
2087 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2088
+
2089 Write(code);
+
2090}
+
2091
+
2092void GeneratorCpp::GenerateFBEFieldModelString_Header()
+
2093{
+
2094 std::string code = R"CODE(
+
2095// Fast Binary Encoding field model string specialization
+
2096template <>
+
2097class FieldModel<std::string>
+
2098{
+
2099public:
+
2100 FieldModel(FBEBuffer& buffer, size_t offset) noexcept : _buffer(buffer), _offset(offset) {}
+
2101
+
2102 // Get the field offset
+
2103 size_t fbe_offset() const noexcept { return _offset; }
+
2104 // Get the field size
+
2105 size_t fbe_size() const noexcept { return 4; }
+
2106 // Get the field extra size
+
2107 size_t fbe_extra() const noexcept;
+
2108
+
2109 // Shift the current field offset
+
2110 void fbe_shift(size_t size) noexcept { _offset += size; }
+
2111 // Unshift the current field offset
+
2112 void fbe_unshift(size_t size) noexcept { _offset -= size; }
+
2113
+
2114 // Check if the string value is valid
+
2115 bool verify() const noexcept;
+
2116
+
2117 // Get the string value
+
2118 size_t get(char* data, size_t size) const noexcept;
+
2119 // Get the string value
+
2120 template <size_t N>
+
2121 size_t get(char (&data)[N]) const noexcept { return get(data, N); }
+
2122 // Get the string value
+
2123 template <size_t N>
+
2124 size_t get(std::array<char, N>& data) const noexcept { return get(data.data(), data.size()); }
+
2125 // Get the string value
+
2126 void get(std::string& value) const noexcept;
+
2127 // Get the string value
+
2128 void get(std::string& value, const std::string& defaults) const noexcept;
+
2129
+
2130 // Set the string value
+
2131 void set(const char* data, size_t size);
+
2132 // Set the string value
+
2133 template <size_t N>
+
2134 void set(const char (&data)[N]) { set(data, N); }
+
2135 // Set the string value
+
2136 template <size_t N>
+
2137 void set(const std::array<char, N>& data) { set(data.data(), data.size()); }
+
2138 // Set the string value
+
2139 void set(const std::string& value);
+
2140
+
2141private:
+
2142 FBEBuffer& _buffer;
+
2143 size_t _offset;
+
2144};
+
2145)CODE";
+
2146
+
2147 // Prepare code template
+
2148 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2149
+
2150 Write(code);
+
2151}
+
2152
+
2153void GeneratorCpp::GenerateFBEFieldModelString_Source()
+
2154{
+
2155 std::string code = R"CODE(
+
2156size_t FieldModel<std::string>::fbe_extra() const noexcept
+
2157{
+
2158 if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size())
+
2159 return 0;
+
2160
+
2161 uint32_t fbe_string_offset = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset()));
+
2162 if ((fbe_string_offset == 0) || ((_buffer.offset() + fbe_string_offset + 4) > _buffer.size()))
+
2163 return 0;
+
2164
+
2165 uint32_t fbe_string_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_string_offset));
+
2166 return (size_t)(4 + fbe_string_size);
+
2167}
+
2168
+
2169bool FieldModel<std::string>::verify() const noexcept
+
2170{
+
2171 if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size())
+
2172 return true;
+
2173
+
2174 uint32_t fbe_string_offset = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset()));
+
2175 if (fbe_string_offset == 0)
+
2176 return true;
+
2177
+
2178 if ((_buffer.offset() + fbe_string_offset + 4) > _buffer.size())
+
2179 return false;
+
2180
+
2181 uint32_t fbe_string_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_string_offset));
+
2182 if ((_buffer.offset() + fbe_string_offset + 4 + fbe_string_size) > _buffer.size())
+
2183 return false;
+
2184
+
2185 return true;
+
2186}
+
2187
+
2188size_t FieldModel<std::string>::get(char* data, size_t size) const noexcept
+
2189{
+
2190 assert(((size == 0) || (data != nullptr)) && "Invalid buffer!");
+
2191 if ((size > 0) && (data == nullptr))
+
2192 return 0;
+
2193
+
2194 if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size())
+
2195 return 0;
+
2196
+
2197 uint32_t fbe_string_offset = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset()));
+
2198 if (fbe_string_offset == 0)
+
2199 return 0;
+
2200
+
2201 assert(((_buffer.offset() + fbe_string_offset + 4) <= _buffer.size()) && "Model is broken!");
+
2202 if ((_buffer.offset() + fbe_string_offset + 4) > _buffer.size())
+
2203 return 0;
+
2204
+
2205 uint32_t fbe_string_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_string_offset));
+
2206 assert(((_buffer.offset() + fbe_string_offset + 4 + fbe_string_size) <= _buffer.size()) && "Model is broken!");
+
2207 if ((_buffer.offset() + fbe_string_offset + 4 + fbe_string_size) > _buffer.size())
+
2208 return 0;
+
2209
+
2210 size_t result = std::min(size, (size_t)fbe_string_size);
+
2211 memcpy(data, (const char*)(_buffer.data() + _buffer.offset() + fbe_string_offset + 4), result);
+
2212 return result;
+
2213}
+
2214
+
2215void FieldModel<std::string>::get(std::string& value) const noexcept
+
2216{
+
2217 value.clear();
+
2218
+
2219 if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size())
+
2220 return;
+
2221
+
2222 uint32_t fbe_string_offset = *((const uint32_t*)(_buffer.data() + _buffer.offset() + _offset));
+
2223 if (fbe_string_offset == 0)
+
2224 return;
+
2225
+
2226 assert(((_buffer.offset() + fbe_string_offset + 4) <= _buffer.size()) && "Model is broken!");
+
2227 if ((_buffer.offset() + fbe_string_offset + 4) > _buffer.size())
+
2228 return;
+
2229
+
2230 uint32_t fbe_string_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_string_offset));
+
2231 assert(((_buffer.offset() + fbe_string_offset + 4 + fbe_string_size) <= _buffer.size()) && "Model is broken!");
+
2232 if ((_buffer.offset() + fbe_string_offset + 4 + fbe_string_size) > _buffer.size())
+
2233 return;
+
2234
+
2235 value.assign((const char*)(_buffer.data() + _buffer.offset() + fbe_string_offset + 4), fbe_string_size);
+
2236}
+
2237
+
2238void FieldModel<std::string>::get(std::string& value, const std::string& defaults) const noexcept
+
2239{
+
2240 value = defaults;
+
2241
+
2242 if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size())
+
2243 return;
+
2244
+
2245 uint32_t fbe_string_offset = *((const uint32_t*)(_buffer.data() + _buffer.offset() + _offset));
+
2246 if (fbe_string_offset == 0)
+
2247 return;
+
2248
+
2249 assert(((_buffer.offset() + fbe_string_offset + 4) <= _buffer.size()) && "Model is broken!");
+
2250 if ((_buffer.offset() + fbe_string_offset + 4) > _buffer.size())
+
2251 return;
+
2252
+
2253 uint32_t fbe_string_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_string_offset));
+
2254 assert(((_buffer.offset() + fbe_string_offset + 4 + fbe_string_size) <= _buffer.size()) && "Model is broken!");
+
2255 if ((_buffer.offset() + fbe_string_offset + 4 + fbe_string_size) > _buffer.size())
+
2256 return;
+
2257
+
2258 value.assign((const char*)(_buffer.data() + _buffer.offset() + fbe_string_offset + 4), fbe_string_size);
+
2259}
+
2260
+
2261void FieldModel<std::string>::set(const char* data, size_t size)
+
2262{
+
2263 assert(((size == 0) || (data != nullptr)) && "Invalid buffer!");
+
2264 if ((size > 0) && (data == nullptr))
+
2265 return;
+
2266
+
2267 assert(((_buffer.offset() + fbe_offset() + fbe_size()) <= _buffer.size()) && "Model is broken!");
+
2268 if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size())
+
2269 return;
+
2270
+
2271 uint32_t fbe_string_size = (uint32_t)size;
+
2272 uint32_t fbe_string_offset = (uint32_t)(_buffer.allocate(4 + fbe_string_size) - _buffer.offset());
+
2273 assert(((fbe_string_offset > 0) && ((_buffer.offset() + fbe_string_offset + 4 + fbe_string_size) <= _buffer.size())) && "Model is broken!");
+
2274 if ((fbe_string_offset == 0) || ((_buffer.offset() + fbe_string_offset + 4 + fbe_string_size) > _buffer.size()))
+
2275 return;
+
2276
+
2277 *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())) = fbe_string_offset;
+
2278 *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_string_offset)) = fbe_string_size;
+
2279
+
2280 memcpy((char*)(_buffer.data() + _buffer.offset() + fbe_string_offset + 4), data, fbe_string_size);
+
2281}
+
2282
+
2283void FieldModel<std::string>::set(const std::string& value)
+
2284{
+
2285 assert(((_buffer.offset() + fbe_offset() + fbe_size()) <= _buffer.size()) && "Model is broken!");
+
2286 if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size())
+
2287 return;
+
2288
+
2289 uint32_t fbe_string_size = (uint32_t)value.size();
+
2290 uint32_t fbe_string_offset = (uint32_t)(_buffer.allocate(4 + fbe_string_size) - _buffer.offset());
+
2291 assert(((fbe_string_offset > 0) && ((_buffer.offset() + fbe_string_offset + 4 + fbe_string_size) <= _buffer.size())) && "Model is broken!");
+
2292 if ((fbe_string_offset == 0) || ((_buffer.offset() + fbe_string_offset + 4 + fbe_string_size) > _buffer.size()))
+
2293 return;
+
2294
+
2295 *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())) = fbe_string_offset;
+
2296 *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_string_offset)) = fbe_string_size;
+
2297
+
2298 memcpy((char*)(_buffer.data() + _buffer.offset() + fbe_string_offset + 4), value.data(), fbe_string_size);
+
2299}
+
2300)CODE";
+
2301
+
2302 // Prepare code template
+
2303 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2304
+
2305 Write(code);
+
2306}
+
2307
+
2308void GeneratorCpp::GenerateFBEFieldModelOptional_Header()
+
2309{
+
2310 std::string code = R"CODE(
+
2311// Fast Binary Encoding field model optional specialization
+
2312template <typename T>
+
2313class FieldModel<std::optional<T>>
+
2314{
+
2315public:
+
2316 FieldModel(FBEBuffer& buffer, size_t offset) noexcept : _buffer(buffer), _offset(offset), value(buffer, 0) {}
+
2317
+
2318 // Get the field offset
+
2319 size_t fbe_offset() const noexcept { return _offset; }
+
2320 // Get the field size
+
2321 size_t fbe_size() const noexcept { return 1 + 4; }
+
2322 // Get the field extra size
+
2323 size_t fbe_extra() const noexcept;
+
2324
+
2325 // Shift the current field offset
+
2326 void fbe_shift(size_t size) noexcept { _offset += size; }
+
2327 // Unshift the current field offset
+
2328 void fbe_unshift(size_t size) noexcept { _offset -= size; }
+
2329
+
2331 explicit operator bool() const noexcept { return has_value(); }
+
2332
+
2333 // Checks if the object contains a value
+
2334 bool has_value() const noexcept;
+
2335
+
2336 // Check if the optional value is valid
+
2337 bool verify() const noexcept;
+
2338
+
2339 // Get the optional value (being phase)
+
2340 size_t get_begin() const noexcept;
+
2341 // Get the optional value (end phase)
+
2342 void get_end(size_t fbe_begin) const noexcept;
+
2343
+
2344 // Get the optional value
+
2345 void get(std::optional<T>& opt, const std::optional<T>& defaults = std::nullopt) const noexcept;
+
2346
+
2347 // Set the optional value (begin phase)
+
2348 size_t set_begin(bool has_value);
+
2349 // Set the optional value (end phase)
+
2350 void set_end(size_t fbe_begin);
+
2351
+
2352 // Set the optional value
+
2353 void set(const std::optional<T>& opt);
+
2354
+
2355private:
+
2356 FBEBuffer& _buffer;
+
2357 size_t _offset;
+
2358
+
2359public:
+
2360 // Base field model value
+
2361 FieldModel<T> value;
+
2362};
+
2363)CODE";
+
2364
+
2365 // Prepare code template
+
2366 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2367
+
2368 Write(code);
+
2369}
+
2370
+
2371void GeneratorCpp::GenerateFBEFieldModelOptional_Inline()
+
2372{
+
2373 std::string code = R"CODE(
+
2374template <typename T>
+
2375inline size_t FieldModel<std::optional<T>>::fbe_extra() const noexcept
+
2376{
+
2377 if (!has_value())
+
2378 return 0;
+
2379
+
2380 uint32_t fbe_optional_offset = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset() + 1));
+
2381 if ((fbe_optional_offset == 0) || ((_buffer.offset() + fbe_optional_offset + 4) > _buffer.size()))
+
2382 return 0;
+
2383
+
2384 _buffer.shift(fbe_optional_offset);
+
2385 size_t fbe_result = value.fbe_size() + value.fbe_extra();
+
2386 _buffer.unshift(fbe_optional_offset);
+
2387 return fbe_result;
+
2388}
+
2389
+
2390template <typename T>
+
2391inline bool FieldModel<std::optional<T>>::has_value() const noexcept
+
2392{
+
2393 if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size())
+
2394 return false;
+
2395
+
2396 uint8_t fbe_has_value = *((const uint8_t*)(_buffer.data() + _buffer.offset() + fbe_offset()));
+
2397 return (fbe_has_value != 0);
+
2398}
+
2399
+
2400template <typename T>
+
2401inline bool FieldModel<std::optional<T>>::verify() const noexcept
+
2402{
+
2403 if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size())
+
2404 return true;
+
2405
+
2406 uint8_t fbe_has_value = *((const uint8_t*)(_buffer.data() + _buffer.offset() + fbe_offset()));
+
2407 if (fbe_has_value == 0)
+
2408 return true;
+
2409
+
2410 uint32_t fbe_optional_offset = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset() + 1));
+
2411 if (fbe_optional_offset == 0)
+
2412 return false;
+
2413
+
2414 _buffer.shift(fbe_optional_offset);
+
2415 bool fbe_result = value.verify();
+
2416 _buffer.unshift(fbe_optional_offset);
+
2417 return fbe_result;
+
2418}
+
2419
+
2420template <typename T>
+
2421inline size_t FieldModel<std::optional<T>>::get_begin() const noexcept
+
2422{
+
2423 if (!has_value())
+
2424 return 0;
+
2425
+
2426 uint32_t fbe_optional_offset = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset() + 1));
+
2427 assert((fbe_optional_offset > 0) && "Model is broken!");
+
2428 if (fbe_optional_offset == 0)
+
2429 return 0;
+
2430
+
2431 _buffer.shift(fbe_optional_offset);
+
2432 return fbe_optional_offset;
+
2433}
+
2434
+
2435template <typename T>
+
2436inline void FieldModel<std::optional<T>>::get_end(size_t fbe_begin) const noexcept
+
2437{
+
2438 _buffer.unshift(fbe_begin);
+
2439}
+
2440
+
2441template <typename T>
+
2442inline void FieldModel<std::optional<T>>::get(std::optional<T>& opt, const std::optional<T>& defaults) const noexcept
+
2443{
+
2444 opt = defaults;
+
2445
+
2446 size_t fbe_begin = get_begin();
+
2447 if (fbe_begin == 0)
+
2448 return;
+
2449
+
2450 T temp = T();
+
2451 value.get(temp);
+
2452 opt.emplace(temp);
+
2453
+
2454 get_end(fbe_begin);
+
2455}
+
2456
+
2457template <typename T>
+
2458inline size_t FieldModel<std::optional<T>>::set_begin(bool has_value)
+
2459{
+
2460 assert(((_buffer.offset() + fbe_offset() + fbe_size()) <= _buffer.size()) && "Model is broken!");
+
2461 if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size())
+
2462 return 0;
+
2463
+
2464 uint8_t fbe_has_value = has_value ? 1 : 0;
+
2465 *((uint8_t*)(_buffer.data() + _buffer.offset() + fbe_offset())) = fbe_has_value;
+
2466 if (fbe_has_value == 0)
+
2467 return 0;
+
2468
+
2469 uint32_t fbe_optional_size = (uint32_t)value.fbe_size();
+
2470 uint32_t fbe_optional_offset = (uint32_t)(_buffer.allocate(fbe_optional_size) - _buffer.offset());
+
2471 assert(((fbe_optional_offset > 0) && ((_buffer.offset() + fbe_optional_offset + fbe_optional_size) <= _buffer.size())) && "Model is broken!");
+
2472 if ((fbe_optional_offset == 0) || ((_buffer.offset() + fbe_optional_offset + fbe_optional_size) > _buffer.size()))
+
2473 return 0;
+
2474
+
2475 *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset() + 1)) = fbe_optional_offset;
+
2476
+
2477 _buffer.shift(fbe_optional_offset);
+
2478 return fbe_optional_offset;
+
2479}
+
2480
+
2481template <typename T>
+
2482inline void FieldModel<std::optional<T>>::set_end(size_t fbe_begin)
+
2483{
+
2484 _buffer.unshift(fbe_begin);
+
2485}
+
2486
+
2487template <typename T>
+
2488inline void FieldModel<std::optional<T>>::set(const std::optional<T>& opt)
+
2489{
+
2490 size_t fbe_begin = set_begin(opt.has_value());
+
2491 if (fbe_begin == 0)
+
2492 return;
+
2493
+
2494 if (opt)
+
2495 value.set(opt.value());
+
2496
+
2497 set_end(fbe_begin);
+
2498}
+
2499)CODE";
+
2500
+
2501 // Prepare code template
+
2502 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2503
+
2504 Write(code);
+
2505}
+
2506
+
2507void GeneratorCpp::GenerateFBEFieldModelArray_Header()
+
2508{
+
2509 std::string code = R"CODE(
+
2510// Fast Binary Encoding field model array
+
2511template <typename T, size_t N>
+
2512class FieldModelArray
+
2513{
+
2514public:
+
2515 FieldModelArray(FBEBuffer& buffer, size_t offset) noexcept : _buffer(buffer), _offset(offset), _model(buffer, offset) {}
+
2516
+
2517 // Get the field offset
+
2518 size_t fbe_offset() const noexcept { return _offset; }
+
2519 // Get the field size
+
2520 size_t fbe_size() const noexcept { return N * _model.fbe_size(); }
+
2521 // Get the field extra size
+
2522 size_t fbe_extra() const noexcept { return 0; }
+
2523
+
2524 // Shift the current field offset
+
2525 void fbe_shift(size_t size) noexcept { _offset += size; }
+
2526 // Unshift the current field offset
+
2527 void fbe_unshift(size_t size) noexcept { _offset -= size; }
+
2528
+
2529 // Get the array
+
2530 const uint8_t* data() const noexcept;
+
2531 // Get the array
+
2532 uint8_t* data() noexcept;
+
2533 // Get the array offset
+
2534 size_t offset() const noexcept { return 0; }
+
2535 // Get the array size
+
2536 size_t size() const noexcept { return N; }
+
2537
+
2538 // Array index operator
+
2539 FieldModel<T> operator[](size_t index) const noexcept;
+
2540
+
2541 // Check if the array is valid
+
2542 bool verify() const noexcept;
+
2543
+
2544 // Get the array as C-array
+
2545 template <size_t S>
+
2546 void get(T (&values)[S]) const noexcept;
+
2547 // Get the array as std::array
+
2548 template <size_t S>
+
2549 void get(std::array<T, S>& values) const noexcept;
+
2550 // Get the array as std::vector
+
2551 void get(std::vector<T>& values) const noexcept;
+
2552
+
2553 // Set the array as C-array
+
2554 template <size_t S>
+
2555 void set(const T (&values)[S]) noexcept;
+
2556 // Set the array as std::array
+
2557 template <size_t S>
+
2558 void set(const std::array<T, S>& values) noexcept;
+
2559 // Set the array as std::vector
+
2560 void set(const std::vector<T>& values) noexcept;
+
2561
+
2562private:
+
2563 FBEBuffer& _buffer;
+
2564 size_t _offset;
+
2565 FieldModel<T> _model;
+
2566};
+
2567)CODE";
+
2568
+
2569 // Prepare code template
+
2570 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2571
+
2572 Write(code);
+
2573}
+
2574
+
2575void GeneratorCpp::GenerateFBEFieldModelArray_Inline()
+
2576{
+
2577 std::string code = R"CODE(
+
2578template <typename T, size_t N>
+
2579inline const uint8_t* FieldModelArray<T, N>::data() const noexcept
+
2580{
+
2581 assert(((_buffer.offset() + fbe_offset() + fbe_size()) <= _buffer.size()) && "Model is broken!");
+
2582 return _buffer.data() + _buffer.offset() + fbe_offset();
+
2583}
+
2584
+
2585template <typename T, size_t N>
+
2586inline uint8_t* FieldModelArray<T, N>::data() noexcept
+
2587{
+
2588 assert(((_buffer.offset() + fbe_offset() + fbe_size()) <= _buffer.size()) && "Model is broken!");
+
2589 return _buffer.data() + _buffer.offset() + fbe_offset();
+
2590}
+
2591
+
2592template <typename T, size_t N>
+
2593inline FieldModel<T> FieldModelArray<T, N>::operator[](size_t index) const noexcept
+
2594{
+
2595 assert(((_buffer.offset() + fbe_offset() + fbe_size()) <= _buffer.size()) && "Model is broken!");
+
2596 assert((index < N) && "Index is out of bounds!");
+
2597
+
2598 FieldModel<T> fbe_model(_buffer, fbe_offset());
+
2599 fbe_model.fbe_shift(index * fbe_model.fbe_size());
+
2600 return fbe_model;
+
2601}
+
2602
+
2603template <typename T, size_t N>
+
2604inline bool FieldModelArray<T, N>::verify() const noexcept
+
2605{
+
2606 if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size())
+
2607 return false;
+
2608
+
2609 FieldModel<T> fbe_model(_buffer, fbe_offset());
+
2610 for (size_t i = N; i-- > 0;)
+
2611 {
+
2612 if (!fbe_model.verify())
+
2613 return false;
+
2614 fbe_model.fbe_shift(fbe_model.fbe_size());
+
2615 }
+
2616
+
2617 return true;
+
2618}
+
2619
+
2620template <typename T, size_t N>
+
2621template <size_t S>
+
2622inline void FieldModelArray<T, N>::get(T (&values)[S]) const noexcept
+
2623{
+
2624 auto fbe_model = (*this)[0];
+
2625 for (size_t i = 0; (i < S) && (i < N); ++i)
+
2626 {
+
2627 fbe_model.get(values[i]);
+
2628 fbe_model.fbe_shift(fbe_model.fbe_size());
+
2629 }
+
2630}
+
2631
+
2632template <typename T, size_t N>
+
2633template <size_t S>
+
2634inline void FieldModelArray<T, N>::get(std::array<T, S>& values) const noexcept
+
2635{
+
2636 auto fbe_model = (*this)[0];
+
2637 for (size_t i = 0; (i < S) && (i < N); ++i)
+
2638 {
+
2639 fbe_model.get(values[i]);
+
2640 fbe_model.fbe_shift(fbe_model.fbe_size());
+
2641 }
+
2642}
+
2643
+
2644template <typename T, size_t N>
+
2645inline void FieldModelArray<T, N>::get(std::vector<T>& values) const noexcept
+
2646{
+
2647 values.clear();
+
2648 values.reserve(N);
+
2649
+
2650 auto fbe_model = (*this)[0];
+
2651 for (size_t i = N; i-- > 0;)
+
2652 {
+
2653 T value = T();
+
2654 fbe_model.get(value);
+
2655 values.emplace_back(value);
+
2656 fbe_model.fbe_shift(fbe_model.fbe_size());
+
2657 }
+
2658}
+
2659
+
2660template <typename T, size_t N>
+
2661template <size_t S>
+
2662inline void FieldModelArray<T, N>::set(const T (&values)[S]) noexcept
+
2663{
+
2664 assert(((_buffer.offset() + fbe_offset() + fbe_size()) <= _buffer.size()) && "Model is broken!");
+
2665 if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size())
+
2666 return;
+
2667
+
2668 auto fbe_model = (*this)[0];
+
2669 for (size_t i = 0; (i < S) && (i < N); ++i)
+
2670 {
+
2671 fbe_model.set(values[i]);
+
2672 fbe_model.fbe_shift(fbe_model.fbe_size());
+
2673 }
+
2674}
+
2675
+
2676template <typename T, size_t N>
+
2677template <size_t S>
+
2678inline void FieldModelArray<T, N>::set(const std::array<T, S>& values) noexcept
+
2679{
+
2680 assert(((_buffer.offset() + fbe_offset() + fbe_size()) <= _buffer.size()) && "Model is broken!");
+
2681 if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size())
+
2682 return;
+
2683
+
2684 auto fbe_model = (*this)[0];
+
2685 for (size_t i = 0; (i < S) && (i < N); ++i)
+
2686 {
+
2687 fbe_model.set(values[i]);
+
2688 fbe_model.fbe_shift(fbe_model.fbe_size());
+
2689 }
+
2690}
+
2691
+
2692template <typename T, size_t N>
+
2693inline void FieldModelArray<T, N>::set(const std::vector<T>& values) noexcept
+
2694{
+
2695 assert(((_buffer.offset() + fbe_offset() + fbe_size()) <= _buffer.size()) && "Model is broken!");
+
2696 if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size())
+
2697 return;
+
2698
+
2699 auto fbe_model = (*this)[0];
+
2700 for (size_t i = 0; (i < values.size()) && (i < N); ++i)
+
2701 {
+
2702 fbe_model.set(values[i]);
+
2703 fbe_model.fbe_shift(fbe_model.fbe_size());
+
2704 }
+
2705}
+
2706)CODE";
+
2707
+
2708 // Prepare code template
+
2709 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2710
+
2711 Write(code);
+
2712}
+
2713
+
2714void GeneratorCpp::GenerateFBEFieldModelVector_Header()
+
2715{
+
2716 std::string code = R"CODE(
+
2717// Fast Binary Encoding field model vector
+
2718template <typename T>
+
2719class FieldModelVector
+
2720{
+
2721public:
+
2722 FieldModelVector(FBEBuffer& buffer, size_t offset) noexcept : _buffer(buffer), _offset(offset) {}
+
2723
+
2724 // Get the field offset
+
2725 size_t fbe_offset() const noexcept { return _offset; }
+
2726 // Get the field size
+
2727 size_t fbe_size() const noexcept { return 4; }
+
2728 // Get the field extra size
+
2729 size_t fbe_extra() const noexcept;
+
2730
+
2731 // Shift the current field offset
+
2732 void fbe_shift(size_t size) noexcept { _offset += size; }
+
2733 // Unshift the current field offset
+
2734 void fbe_unshift(size_t size) noexcept { _offset -= size; }
+
2735
+
2736 // Get the vector offset
+
2737 size_t offset() const noexcept;
+
2738 // Get the vector size
+
2739 size_t size() const noexcept;
+
2740
+
2741 // Vector index operator
+
2742 FieldModel<T> operator[](size_t index) const noexcept;
+
2743
+
2744 // Resize the vector and get its first model
+
2745 FieldModel<T> resize(size_t size);
+
2746
+
2747 // Check if the vector is valid
+
2748 bool verify() const noexcept;
+
2749
+
2750 // Get the vector as std::vector
+
2751 void get(std::vector<T>& values) const noexcept;
+
2752 // Get the vector as std::list
+
2753 void get(std::list<T>& values) const noexcept;
+
2754 // Get the vector as std::set
+
2755 void get(std::set<T>& values) const noexcept;
+
2756
+
2757 // Set the vector as std::vector
+
2758 void set(const std::vector<T>& values) noexcept;
+
2759 // Set the vector as std::list
+
2760 void set(const std::list<T>& values) noexcept;
+
2761 // Set the vector as std::set
+
2762 void set(const std::set<T>& values) noexcept;
+
2763
+
2764private:
+
2765 FBEBuffer& _buffer;
+
2766 size_t _offset;
+
2767};
+
2768)CODE";
+
2769
+
2770 // Prepare code template
+
2771 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2772
+
2773 Write(code);
+
2774}
+
2775
+
2776void GeneratorCpp::GenerateFBEFieldModelVector_Inline()
+
2777{
+
2778 std::string code = R"CODE(
+
2779template <typename T>
+
2780inline size_t FieldModelVector<T>::fbe_extra() const noexcept
+
2781{
+
2782 if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size())
+
2783 return 0;
+
2784
+
2785 uint32_t fbe_vector_offset = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset()));
+
2786 if ((fbe_vector_offset == 0) || ((_buffer.offset() + fbe_vector_offset + 4) > _buffer.size()))
+
2787 return 0;
+
2788
+
2789 uint32_t fbe_vector_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_vector_offset));
+
2790
+
2791 size_t fbe_result = 4;
+
2792 FieldModel<T> fbe_model(_buffer, fbe_vector_offset + 4);
+
2793 for (size_t i = fbe_vector_size; i-- > 0;)
+
2794 {
+
2795 fbe_result += fbe_model.fbe_size() + fbe_model.fbe_extra();
+
2796 fbe_model.fbe_shift(fbe_model.fbe_size());
+
2797 }
+
2798 return fbe_result;
+
2799}
+
2800
+
2801template <typename T>
+
2802inline size_t FieldModelVector<T>::offset() const noexcept
+
2803{
+
2804 if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size())
+
2805 return 0;
+
2806
+
2807 uint32_t fbe_vector_offset = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset()));
+
2808 return fbe_vector_offset;
+
2809}
+
2810
+
2811template <typename T>
+
2812inline size_t FieldModelVector<T>::size() const noexcept
+
2813{
+
2814 if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size())
+
2815 return 0;
+
2816
+
2817 uint32_t fbe_vector_offset = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset()));
+
2818 if ((fbe_vector_offset == 0) || ((_buffer.offset() + fbe_vector_offset + 4) > _buffer.size()))
+
2819 return 0;
+
2820
+
2821 uint32_t fbe_vector_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_vector_offset));
+
2822 return fbe_vector_size;
+
2823}
+
2824
+
2825template <typename T>
+
2826inline FieldModel<T> FieldModelVector<T>::operator[](size_t index) const noexcept
+
2827{
+
2828 assert(((_buffer.offset() + fbe_offset() + fbe_size()) <= _buffer.size()) && "Model is broken!");
+
2829
+
2830 uint32_t fbe_vector_offset = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset()));
+
2831 assert(((fbe_vector_offset > 0) && ((_buffer.offset() + fbe_vector_offset + 4) <= _buffer.size())) && "Model is broken!");
+
2832
+
2833 [[maybe_unused]] uint32_t fbe_vector_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_vector_offset));
+
2834 assert((index < fbe_vector_size) && "Index is out of bounds!");
+
2835
+
2836 FieldModel<T> fbe_model(_buffer, fbe_vector_offset + 4);
+
2837 fbe_model.fbe_shift(index * fbe_model.fbe_size());
+
2838 return fbe_model;
+
2839}
+
2840
+
2841template <typename T>
+
2842inline FieldModel<T> FieldModelVector<T>::resize(size_t size)
+
2843{
+
2844 FieldModel<T> fbe_model(_buffer, fbe_offset());
+
2845
+
2846 uint32_t fbe_vector_size = (uint32_t)(size * fbe_model.fbe_size());
+
2847 uint32_t fbe_vector_offset = (uint32_t)(_buffer.allocate(4 + fbe_vector_size) - _buffer.offset());
+
2848 assert(((fbe_vector_offset > 0) && ((_buffer.offset() + fbe_vector_offset + 4) <= _buffer.size())) && "Model is broken!");
+
2849
+
2850 *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())) = fbe_vector_offset;
+
2851 *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_vector_offset)) = (uint32_t)size;
+
2852
+
2853 memset((char*)(_buffer.data() + _buffer.offset() + fbe_vector_offset + 4), 0, fbe_vector_size);
+
2854
+
2855 return FieldModel<T>(_buffer, fbe_vector_offset + 4);
+
2856}
+
2857
+
2858template <typename T>
+
2859inline bool FieldModelVector<T>::verify() const noexcept
+
2860{
+
2861 if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size())
+
2862 return true;
+
2863
+
2864 uint32_t fbe_vector_offset = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset()));
+
2865 if (fbe_vector_offset == 0)
+
2866 return true;
+
2867
+
2868 if ((_buffer.offset() + fbe_vector_offset + 4) > _buffer.size())
+
2869 return false;
+
2870
+
2871 uint32_t fbe_vector_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_vector_offset));
+
2872
+
2873 FieldModel<T> fbe_model(_buffer, fbe_vector_offset + 4);
+
2874 for (size_t i = fbe_vector_size; i-- > 0;)
+
2875 {
+
2876 if (!fbe_model.verify())
+
2877 return false;
+
2878 fbe_model.fbe_shift(fbe_model.fbe_size());
+
2879 }
+
2880
+
2881 return true;
+
2882}
+
2883
+
2884template <typename T>
+
2885inline void FieldModelVector<T>::get(std::vector<T>& values) const noexcept
+
2886{
+
2887 values.clear();
+
2888
+
2889 size_t fbe_vector_size = size();
+
2890 if (fbe_vector_size == 0)
+
2891 return;
+
2892
+
2893 values.reserve(fbe_vector_size);
+
2894
+
2895 auto fbe_model = (*this)[0];
+
2896 for (size_t i = fbe_vector_size; i-- > 0;)
+
2897 {
+
2898 T value = T();
+
2899 fbe_model.get(value);
+
2900 values.emplace_back(value);
+
2901 fbe_model.fbe_shift(fbe_model.fbe_size());
+
2902 }
+
2903}
+
2904
+
2905template <typename T>
+
2906inline void FieldModelVector<T>::get(std::list<T>& values) const noexcept
+
2907{
+
2908 values.clear();
+
2909
+
2910 size_t fbe_vector_size = size();
+
2911 if (fbe_vector_size == 0)
+
2912 return;
+
2913
+
2914 auto fbe_model = (*this)[0];
+
2915 for (size_t i = fbe_vector_size; i-- > 0;)
+
2916 {
+
2917 T value = T();
+
2918 fbe_model.get(value);
+
2919 values.emplace_back(value);
+
2920 fbe_model.fbe_shift(fbe_model.fbe_size());
+
2921 }
+
2922}
+
2923
+
2924template <typename T>
+
2925inline void FieldModelVector<T>::get(std::set<T>& values) const noexcept
+
2926{
+
2927 values.clear();
+
2928
+
2929 size_t fbe_vector_size = size();
+
2930 if (fbe_vector_size == 0)
+
2931 return;
+
2932
+
2933 auto fbe_model = (*this)[0];
+
2934 for (size_t i = fbe_vector_size; i-- > 0;)
+
2935 {
+
2936 T value = T();
+
2937 fbe_model.get(value);
+
2938 values.emplace(value);
+
2939 fbe_model.fbe_shift(fbe_model.fbe_size());
+
2940 }
+
2941}
+
2942
+
2943template <typename T>
+
2944inline void FieldModelVector<T>::set(const std::vector<T>& values) noexcept
+
2945{
+
2946 assert(((_buffer.offset() + fbe_offset() + fbe_size()) <= _buffer.size()) && "Model is broken!");
+
2947 if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size())
+
2948 return;
+
2949
+
2950 auto fbe_model = resize(values.size());
+
2951 for (const auto& value : values)
+
2952 {
+
2953 fbe_model.set(value);
+
2954 fbe_model.fbe_shift(fbe_model.fbe_size());
+
2955 }
+
2956}
+
2957
+
2958template <typename T>
+
2959inline void FieldModelVector<T>::set(const std::list<T>& values) noexcept
+
2960{
+
2961 assert(((_buffer.offset() + fbe_offset() + fbe_size()) <= _buffer.size()) && "Model is broken!");
+
2962 if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size())
+
2963 return;
+
2964
+
2965 auto fbe_model = resize(values.size());
+
2966 for (const auto& value : values)
+
2967 {
+
2968 fbe_model.set(value);
+
2969 fbe_model.fbe_shift(fbe_model.fbe_size());
+
2970 }
+
2971}
+
2972
+
2973template <typename T>
+
2974inline void FieldModelVector<T>::set(const std::set<T>& values) noexcept
+
2975{
+
2976 assert(((_buffer.offset() + fbe_offset() + fbe_size()) <= _buffer.size()) && "Model is broken!");
+
2977 if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size())
+
2978 return;
+
2979
+
2980 auto fbe_model = resize(values.size());
+
2981 for (const auto& value : values)
+
2982 {
+
2983 fbe_model.set(value);
+
2984 fbe_model.fbe_shift(fbe_model.fbe_size());
+
2985 }
+
2986}
+
2987)CODE";
+
2988
+
2989 // Prepare code template
+
2990 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2991
+
2992 Write(code);
+
2993}
+
2994
+
2995void GeneratorCpp::GenerateFBEFieldModelMap_Header()
+
2996{
+
2997 std::string code = R"CODE(
+
2998// Fast Binary Encoding field model map
+
2999template <typename TKey, typename TValue>
+
3000class FieldModelMap
+
3001{
+
3002public:
+
3003 FieldModelMap(FBEBuffer& buffer, size_t offset) noexcept : _buffer(buffer), _offset(offset) {}
+
3004
+
3005 // Get the field offset
+
3006 size_t fbe_offset() const noexcept { return _offset; }
+
3007 // Get the field size
+
3008 size_t fbe_size() const noexcept { return 4; }
+
3009 // Get the field extra size
+
3010 size_t fbe_extra() const noexcept;
+
3011
+
3012 // Shift the current field offset
+
3013 void fbe_shift(size_t size) noexcept { _offset += size; }
+
3014 // Unshift the current field offset
+
3015 void fbe_unshift(size_t size) noexcept { _offset -= size; }
+
3016
+
3017 // Get the map offset
+
3018 size_t offset() const noexcept;
+
3019 // Get the map size
+
3020 size_t size() const noexcept;
+
3021
+
3022 // Map index operator
+
3023 std::pair<FieldModel<TKey>, FieldModel<TValue>> operator[](size_t index) const noexcept;
+
3024
+
3025 // Resize the map and get its first model
+
3026 std::pair<FieldModel<TKey>, FieldModel<TValue>> resize(size_t size);
+
3027
+
3028 // Check if the map is valid
+
3029 bool verify() const noexcept;
+
3030
+
3031 // Get the map as std::map
+
3032 void get(std::map<TKey, TValue>& values) const noexcept;
+
3033 // Get the map as std::unordered_map
+
3034 void get(std::unordered_map<TKey, TValue>& values) const noexcept;
+
3035
+
3036 // Set the map as std::map
+
3037 void set(const std::map<TKey, TValue>& values) noexcept;
+
3038 // Set the map as std::unordered_map
+
3039 void set(const std::unordered_map<TKey, TValue>& values) noexcept;
+
3040
+
3041private:
+
3042 FBEBuffer& _buffer;
+
3043 size_t _offset;
+
3044};
+
3045)CODE";
+
3046
+
3047 // Prepare code template
+
3048 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
3049
+
3050 Write(code);
+
3051}
+
3052
+
3053void GeneratorCpp::GenerateFBEFieldModelMap_Inline()
+
3054{
+
3055 std::string code = R"CODE(
+
3056template <typename TKey, typename TValue>
+
3057inline size_t FieldModelMap<TKey, TValue>::fbe_extra() const noexcept
+
3058{
+
3059 if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size())
+
3060 return 0;
+
3061
+
3062 uint32_t fbe_map_offset = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset()));
+
3063 if ((fbe_map_offset == 0) || ((_buffer.offset() + fbe_map_offset + 4) > _buffer.size()))
+
3064 return 0;
+
3065
+
3066 uint32_t fbe_map_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_map_offset));
+
3067
+
3068 size_t fbe_result = 4;
+
3069 FieldModel<TKey> fbe_model_key(_buffer, fbe_map_offset + 4);
+
3070 FieldModel<TValue> fbe_model_value(_buffer, fbe_map_offset + 4 + fbe_model_key.fbe_size());
+
3071 for (size_t i = fbe_map_size; i-- > 0;)
+
3072 {
+
3073 fbe_result += fbe_model_key.fbe_size() + fbe_model_key.fbe_extra();
+
3074 fbe_model_key.fbe_shift(fbe_model_key.fbe_size() + fbe_model_value.fbe_size());
+
3075 fbe_result += fbe_model_value.fbe_size() + fbe_model_value.fbe_extra();
+
3076 fbe_model_value.fbe_shift(fbe_model_key.fbe_size() + fbe_model_value.fbe_size());
+
3077 }
+
3078 return fbe_result;
+
3079}
+
3080
+
3081template <typename TKey, typename TValue>
+
3082inline size_t FieldModelMap<TKey, TValue>::offset() const noexcept
+
3083{
+
3084 if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size())
+
3085 return 0;
+
3086
+
3087 uint32_t fbe_map_offset = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset()));
+
3088 return fbe_map_offset;
+
3089}
+
3090
+
3091template <typename TKey, typename TValue>
+
3092inline size_t FieldModelMap<TKey, TValue>::size() const noexcept
+
3093{
+
3094 if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size())
+
3095 return 0;
+
3096
+
3097 uint32_t fbe_map_offset = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset()));
+
3098 if ((fbe_map_offset == 0) || ((_buffer.offset() + fbe_map_offset + 4) > _buffer.size()))
+
3099 return 0;
+
3100
+
3101 uint32_t fbe_map_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_map_offset));
+
3102 return fbe_map_size;
+
3103}
+
3104
+
3105template <typename TKey, typename TValue>
+
3106inline std::pair<FieldModel<TKey>, FieldModel<TValue>> FieldModelMap<TKey, TValue>::operator[](size_t index) const noexcept
+
3107{
+
3108 assert(((_buffer.offset() + fbe_offset() + fbe_size()) <= _buffer.size()) && "Model is broken!");
+
3109
+
3110 uint32_t fbe_map_offset = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset()));
+
3111 assert(((fbe_map_offset > 0) && ((_buffer.offset() + fbe_map_offset + 4) <= _buffer.size())) && "Model is broken!");
+
3112
+
3113 [[maybe_unused]] uint32_t fbe_map_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_map_offset));
+
3114 assert((index < fbe_map_size) && "Index is out of bounds!");
+
3115
+
3116 FieldModel<TKey> fbe_model_key(_buffer, fbe_map_offset + 4);
+
3117 FieldModel<TValue> fbe_model_value(_buffer, fbe_map_offset + 4 + fbe_model_key.fbe_size());
+
3118 fbe_model_key.fbe_shift(index * (fbe_model_key.fbe_size() + fbe_model_value.fbe_size()));
+
3119 fbe_model_value.fbe_shift(index * (fbe_model_key.fbe_size() + fbe_model_value.fbe_size()));
+
3120 return std::make_pair(fbe_model_key, fbe_model_value);
+
3121}
+
3122
+
3123template <typename TKey, typename TValue>
+
3124inline std::pair<FieldModel<TKey>, FieldModel<TValue>> FieldModelMap<TKey, TValue>::resize(size_t size)
+
3125{
+
3126 FieldModel<TKey> fbe_model_key(_buffer, fbe_offset());
+
3127 FieldModel<TValue> fbe_model_value(_buffer, fbe_offset() + fbe_model_key.fbe_size());
+
3128
+
3129 uint32_t fbe_map_size = (uint32_t)(size * (fbe_model_key.fbe_size() + fbe_model_value.fbe_size()));
+
3130 uint32_t fbe_map_offset = (uint32_t)(_buffer.allocate(4 + fbe_map_size) - _buffer.offset());
+
3131 assert(((fbe_map_offset > 0) && ((_buffer.offset() + fbe_map_offset + 4 + fbe_map_size) <= _buffer.size())) && "Model is broken!");
+
3132
+
3133 *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())) = fbe_map_offset;
+
3134 *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_map_offset)) = (uint32_t)size;
+
3135
+
3136 memset((char*)(_buffer.data() + _buffer.offset() + fbe_map_offset + 4), 0, fbe_map_size);
+
3137
+
3138 return std::make_pair(FieldModel<TKey>(_buffer, fbe_map_offset + 4), FieldModel<TValue>(_buffer, fbe_map_offset + 4 + fbe_model_key.fbe_size()));
+
3139}
+
3140
+
3141template <typename TKey, typename TValue>
+
3142inline bool FieldModelMap<TKey, TValue>::verify() const noexcept
+
3143{
+
3144 if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size())
+
3145 return true;
+
3146
+
3147 uint32_t fbe_map_offset = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset()));
+
3148 if (fbe_map_offset == 0)
+
3149 return true;
+
3150
+
3151 if ((_buffer.offset() + fbe_map_offset + 4) > _buffer.size())
+
3152 return false;
+
3153
+
3154 uint32_t fbe_map_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_map_offset));
+
3155
+
3156 FieldModel<TKey> fbe_model_key(_buffer, fbe_map_offset + 4);
+
3157 FieldModel<TValue> fbe_model_value(_buffer, fbe_map_offset + 4 + fbe_model_key.fbe_size());
+
3158 for (size_t i = fbe_map_size; i-- > 0;)
+
3159 {
+
3160 if (!fbe_model_key.verify())
+
3161 return false;
+
3162 fbe_model_key.fbe_shift(fbe_model_key.fbe_size() + fbe_model_value.fbe_size());
+
3163 if (!fbe_model_value.verify())
+
3164 return false;
+
3165 fbe_model_value.fbe_shift(fbe_model_key.fbe_size() + fbe_model_value.fbe_size());
+
3166 }
+
3167
+
3168 return true;
+
3169}
+
3170
+
3171template <typename TKey, typename TValue>
+
3172inline void FieldModelMap<TKey, TValue>::get(std::map<TKey, TValue>& values) const noexcept
+
3173{
+
3174 values.clear();
+
3175
+
3176 size_t fbe_map_size = size();
+
3177 if (fbe_map_size == 0)
+
3178 return;
+
3179
+
3180 auto fbe_model = (*this)[0];
+
3181 for (size_t i = fbe_map_size; i-- > 0;)
+
3182 {
+
3183 TKey key = TKey();
+
3184 TValue value = TValue();
+
3185 fbe_model.first.get(key);
+
3186 fbe_model.second.get(value);
+
3187 values.emplace(key, value);
+
3188 fbe_model.first.fbe_shift(fbe_model.first.fbe_size() + fbe_model.second.fbe_size());
+
3189 fbe_model.second.fbe_shift(fbe_model.first.fbe_size() + fbe_model.second.fbe_size());
+
3190 }
+
3191}
+
3192
+
3193template <typename TKey, typename TValue>
+
3194inline void FieldModelMap<TKey, TValue>::get(std::unordered_map<TKey, TValue>& values) const noexcept
+
3195{
+
3196 values.clear();
+
3197
+
3198 size_t fbe_map_size = size();
+
3199 if (fbe_map_size == 0)
+
3200 return;
+
3201
+
3202 auto fbe_model = (*this)[0];
+
3203 for (size_t i = fbe_map_size; i-- > 0;)
+
3204 {
+
3205 TKey key = TKey();
+
3206 TValue value = TValue();
+
3207 fbe_model.first.get(key);
+
3208 fbe_model.second.get(value);
+
3209 values.emplace(key, value);
+
3210 fbe_model.first.fbe_shift(fbe_model.first.fbe_size() + fbe_model.second.fbe_size());
+
3211 fbe_model.second.fbe_shift(fbe_model.first.fbe_size() + fbe_model.second.fbe_size());
+
3212 }
+
3213}
+
3214
+
3215template <typename TKey, typename TValue>
+
3216inline void FieldModelMap<TKey, TValue>::set(const std::map<TKey, TValue>& values) noexcept
+
3217{
+
3218 assert(((_buffer.offset() + fbe_offset() + fbe_size()) <= _buffer.size()) && "Model is broken!");
+
3219 if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size())
+
3220 return;
+
3221
+
3222 auto fbe_model = resize(values.size());
+
3223 for (const auto& value : values)
+
3224 {
+
3225 fbe_model.first.set(value.first);
+
3226 fbe_model.first.fbe_shift(fbe_model.first.fbe_size() + fbe_model.second.fbe_size());
+
3227 fbe_model.second.set(value.second);
+
3228 fbe_model.second.fbe_shift(fbe_model.first.fbe_size() + fbe_model.second.fbe_size());
+
3229 }
+
3230}
+
3231
+
3232template <typename TKey, typename TValue>
+
3233inline void FieldModelMap<TKey, TValue>::set(const std::unordered_map<TKey, TValue>& values) noexcept
+
3234{
+
3235 assert(((_buffer.offset() + fbe_offset() + fbe_size()) <= _buffer.size()) && "Model is broken!");
+
3236 if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size())
+
3237 return;
+
3238
+
3239 auto fbe_model = resize(values.size());
+
3240 for (const auto& value : values)
+
3241 {
+
3242 fbe_model.first.set(value.first);
+
3243 fbe_model.first.fbe_shift(fbe_model.first.fbe_size() + fbe_model.second.fbe_size());
+
3244 fbe_model.second.set(value.second);
+
3245 fbe_model.second.fbe_shift(fbe_model.first.fbe_size() + fbe_model.second.fbe_size());
+
3246 }
+
3247}
+
3248)CODE";
+
3249
+
3250 // Prepare code template
+
3251 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
3252
+
3253 Write(code);
+
3254}
+
3255
+
3256void GeneratorCpp::GenerateFBEFinalModel_Header()
+
3257{
+
3258 std::string code = R"CODE(
+
3259// Fast Binary Encoding base final model
+
3260template <typename T, typename TBase = T>
+
3261class FinalModelBase
+
3262{
+
3263public:
+
3264 FinalModelBase(FBEBuffer& buffer, size_t offset) noexcept : _buffer(buffer), _offset(offset) {}
+
3265
+
3266 // Get the allocation size
+
3267 size_t fbe_allocation_size(T value) const noexcept { return fbe_size(); }
+
3268
+
3269 // Get the field offset
+
3270 size_t fbe_offset() const noexcept { return _offset; }
+
3271 // Set the field offset
+
3272 size_t fbe_offset(size_t offset) const noexcept { return _offset = offset; }
+
3273
+
3274 // Get the final size
+
3275 size_t fbe_size() const noexcept { return sizeof(TBase); }
+
3276
+
3277 // Shift the current field offset
+
3278 void fbe_shift(size_t size) noexcept { _offset += size; }
+
3279 // Unshift the current field offset
+
3280 void fbe_unshift(size_t size) noexcept { _offset -= size; }
+
3281
+
3282 // Check if the value is valid
+
3283 size_t verify() const noexcept;
+
3284
+
3285 // Get the field value
+
3286 size_t get(T& value) const noexcept;
+
3287 // Set the field value
+
3288 size_t set(T value) noexcept;
+
3289
+
3290private:
+
3291 FBEBuffer& _buffer;
+
3292 mutable size_t _offset;
+
3293};
+
3294
+
3295// Fast Binary Encoding final model
+
3296template <typename T>
+
3297class FinalModel : public FinalModelBase<T>
+
3298{
+
3299public:
+
3300 using FinalModelBase<T>::FinalModelBase;
+
3301};
+
3302
+
3303// Fast Binary Encoding final model bool specialization
+
3304template <>
+
3305class FinalModel<bool> : public FinalModelBase<bool, uint8_t>
+
3306{
+
3307public:
+
3308 using FinalModelBase<bool, uint8_t>::FinalModelBase;
+
3309};
+
3310
+
3311// Fast Binary Encoding final model char specialization
+
3312template <>
+
3313class FinalModel<char> : public FinalModelBase<char, uint8_t>
+
3314{
+
3315public:
+
3316 using FinalModelBase<char, uint8_t>::FinalModelBase;
+
3317};
+
3318
+
3319// Fast Binary Encoding final model wchar specialization
+
3320template <>
+
3321class FinalModel<wchar_t> : public FinalModelBase<wchar_t, uint32_t>
+
3322{
+
3323public:
+
3324 using FinalModelBase<wchar_t, uint32_t>::FinalModelBase;
+
3325};
+
3326)CODE";
+
3327
+
3328 // Prepare code template
+
3329 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
3330
+
3331 Write(code);
+
3332}
+
3333
+
3334void GeneratorCpp::GenerateFBEFinalModel_Inline()
+
3335{
+
3336 std::string code = R"CODE(
+
3337template <typename T, typename TBase>
+
3338inline size_t FinalModelBase<T, TBase>::verify() const noexcept
+
3339{
+
3340 if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size())
+
3341 return std::numeric_limits<std::size_t>::max();
+
3342
+
3343 return fbe_size();
+
3344}
+
3345
+
3346template <typename T, typename TBase>
+
3347inline size_t FinalModelBase<T, TBase>::get(T& value) const noexcept
+
3348{
+
3349 if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size())
+
3350 return 0;
+
3351
+
3352 value = (T)(*((const TBase*)(_buffer.data() + _buffer.offset() + fbe_offset())));
+
3353 return fbe_size();
+
3354}
+
3355
+
3356template <typename T, typename TBase>
+
3357inline size_t FinalModelBase<T, TBase>::set(T value) noexcept
+
3358{
+
3359 assert(((_buffer.offset() + fbe_offset() + fbe_size()) <= _buffer.size()) && "Model is broken!");
+
3360 if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size())
+
3361 return 0;
+
3362
+
3363 *((TBase*)(_buffer.data() + _buffer.offset() + fbe_offset())) = (TBase)value;
+
3364 return fbe_size();
+
3365}
+
3366)CODE";
+
3367
+
3368 // Prepare code template
+
3369 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
3370
+
3371 Write(code);
+
3372}
+
3373
+
3374void GeneratorCpp::GenerateFBEFinalModelDecimal_Header()
+
3375{
+
3376 std::string code = R"CODE(
+
3377// Fast Binary Encoding final model decimal specialization
+
3378template <>
+
3379class FinalModel<decimal_t>
+
3380{
+
3381public:
+
3382 FinalModel(FBEBuffer& buffer, size_t offset) noexcept : _buffer(buffer), _offset(offset) {}
+
3383
+
3384 // Get the allocation size
+
3385 size_t fbe_allocation_size(decimal_t value) const noexcept { return fbe_size(); }
+
3386
+
3387 // Get the field offset
+
3388 size_t fbe_offset() const noexcept { return _offset; }
+
3389 // Set the field offset
+
3390 size_t fbe_offset(size_t offset) const noexcept { return _offset = offset; }
+
3391
+
3392 // Get the final size
+
3393 size_t fbe_size() const noexcept { return 16; }
+
3394
+
3395 // Shift the current field offset
+
3396 void fbe_shift(size_t size) noexcept { _offset += size; }
+
3397 // Unshift the current field offset
+
3398 void fbe_unshift(size_t size) noexcept { _offset -= size; }
+
3399
+
3400 // Check if the decimal value is valid
+
3401 size_t verify() const noexcept;
+
3402
+
3403 // Get the decimal value
+
3404 size_t get(decimal_t& value) const noexcept;
+
3405 // Set the decimal value
+
3406 size_t set(decimal_t value) noexcept;
+
3407
+
3408private:
+
3409 FBEBuffer& _buffer;
+
3410 mutable size_t _offset;
+
3411
+
3412 static uint64_t extract(double a) noexcept;
+
3413 static uint64_t uint32x32(uint32_t a, uint32_t b) noexcept;
+
3414 static void uint64x64(uint64_t a, uint64_t b, uint64_t& low64, uint32_t& high32) noexcept;
+
3415};
+
3416)CODE";
+
3417
+
3418 // Prepare code template
+
3419 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
3420
+
3421 Write(code);
+
3422}
+
3423
+
3424void GeneratorCpp::GenerateFBEFinalModelDecimal_Source()
+
3425{
+
3426 std::string code = R"CODE(
+
3427uint64_t FinalModel<decimal_t>::extract(double a) noexcept
+
3428{
+
3429 uint64_t result;
+
3430 std::memcpy(&result, &a, sizeof(double));
+
3431 return result;
+
3432}
+
3433
+
3434uint64_t FinalModel<decimal_t>::uint32x32(uint32_t a, uint32_t b) noexcept
+
3435{
+
3436 return (uint64_t)a * (uint64_t)b;
+
3437}
+
3438
+
3439void FinalModel<decimal_t>::uint64x64(uint64_t a, uint64_t b, uint64_t& low64, uint32_t& high32) noexcept
+
3440{
+
3441 uint64_t low = uint32x32((uint32_t)a, (uint32_t)b);
+
3442 uint64_t mid = uint32x32((uint32_t)a, (uint32_t)(b >> 32));
+
3443 uint64_t high = uint32x32((uint32_t)(a >> 32), (uint32_t)(b >> 32));
+
3444 high += (mid >> 32);
+
3445 low += (mid <<= 32);
+
3446 // Test for carry
+
3447 if (low < mid)
+
3448 high++;
+
3449
+
3450 mid = uint32x32((uint32_t)(a >> 32), (uint32_t)b);
+
3451 high += (mid >> 32);
+
3452 low += (mid <<= 32);
+
3453 // Test for carry
+
3454 if (low < mid)
+
3455 high++;
+
3456
+
3457 if (high > 0xFFFFFFFFu)
+
3458 {
+
3459 low64 = 0;
+
3460 high32 = 0;
+
3461 }
+
3462 low64 = low;
+
3463 high32 = (uint32_t)high;
+
3464}
+
3465
+
3466size_t FinalModel<decimal_t>::verify() const noexcept
+
3467{
+
3468 if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size())
+
3469 return std::numeric_limits<std::size_t>::max();
+
3470
+
3471 return fbe_size();
+
3472}
+
3473
+
3474size_t FinalModel<decimal_t>::get(decimal_t& value) const noexcept
+
3475{
+
3476 if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size())
+
3477 return 0;
+
3478
+
3479 // Value taken via reverse engineering the double that corresponds to 2^64
+
3480 const double ds2to64 = 1.8446744073709552e+019;
+
3481
+
3482 // Read decimal parts
+
3483 uint64_t low = *((const uint64_t*)(_buffer.data() + _buffer.offset() + fbe_offset()));
+
3484 uint32_t high = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset() + 8));
+
3485 uint32_t flags = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset() + 12));
+
3486
+
3487 // Calculate decimal value
+
3488 double dValue = ((double)low + (double)high * ds2to64) / pow(10.0, (uint8_t)(flags >> 16));
+
3489 if (flags & 0x80000000)
+
3490 dValue = -dValue;
+
3491
+
3492 value = dValue;
+
3493 return fbe_size();
+
3494}
+
3495
+
3496size_t FinalModel<decimal_t>::set(decimal_t value) noexcept
+
3497{
+
3498 assert(((_buffer.offset() + fbe_offset() + fbe_size()) <= _buffer.size()) && "Model is broken!");
+
3499 if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size())
+
3500 return 0;
+
3501
+
3502 // The most we can scale by is 10^28, which is just slightly more
+
3503 // than 2^93. So a float with an exponent of -94 could just
+
3504 // barely reach 0.5, but smaller exponents will always round to zero.
+
3505 const uint32_t DBLBIAS = 1022;
+
3506
+
3507 // Get exponent value
+
3508 double dValue = (double)value;
+
3509 int32_t iExp = (int32_t)(((uint32_t)(extract(dValue) >> 52) & 0x7FFu) - DBLBIAS);
+
3510 if ((iExp < -94) || (iExp > 96))
+
3511 {
+
3512 // Value too big for .NET Decimal (exponent is limited to [-94, 96])
+
3513 memset((uint8_t*)(_buffer.data() + _buffer.offset() + fbe_offset()), 0, 16);
+
3514 return fbe_size();
+
3515 }
+
3516
+
3517 uint32_t flags = 0;
+
3518 if (dValue < 0)
+
3519 {
+
3520 dValue = -dValue;
+
3521 flags = 0x80000000;
+
3522 }
+
3523
+
3524 // Round the input to a 15-digit integer. The R8 format has
+
3525 // only 15 digits of precision, and we want to keep garbage digits
+
3526 // out of the Decimal were making.
+
3527
+
3528 // Calculate max power of 10 input value could have by multiplying
+
3529 // the exponent by log10(2). Using scaled integer multiplcation,
+
3530 // log10(2) * 2 ^ 16 = .30103 * 65536 = 19728.3.
+
3531 int32_t iPower = 14 - ((iExp * 19728) >> 16);
+
3532
+
3533 // iPower is between -14 and 43
+
3534 if (iPower >= 0)
+
3535 {
+
3536 // We have less than 15 digits, scale input up.
+
3537 if (iPower > 28)
+
3538 iPower = 28;
+
3539
+
3540 dValue *= pow(10.0, iPower);
+
3541 }
+
3542 else
+
3543 {
+
3544 if ((iPower != -1) || (dValue >= 1E15))
+
3545 dValue /= pow(10.0, -iPower);
+
3546 else
+
3547 iPower = 0; // didn't scale it
+
3548 }
+
3549
+
3550 assert(dValue < 1E15);
+
3551 if ((dValue < 1E14) && (iPower < 28))
+
3552 {
+
3553 dValue *= 10;
+
3554 iPower++;
+
3555 assert(dValue >= 1E14);
+
3556 }
+
3557
+
3558 // Round to int64
+
3559 uint64_t ulMant;
+
3560 ulMant = (uint64_t)(int64_t)dValue;
+
3561 dValue -= (int64_t)ulMant; // difference between input & integer
+
3562 if ((dValue > 0.5) || ((dValue == 0.5) && ((ulMant & 1) != 0)))
+
3563 ulMant++;
+
3564
+
3565 if (ulMant == 0)
+
3566 {
+
3567 // Mantissa is 0
+
3568 memset((uint8_t*)(_buffer.data() + _buffer.offset() + fbe_offset()), 0, 16);
+
3569 return fbe_size();
+
3570 }
+
3571
+
3572 if (iPower < 0)
+
3573 {
+
3574 // Add -iPower factors of 10, -iPower <= (29 - 15) = 14
+
3575 iPower = -iPower;
+
3576 if (iPower < 10)
+
3577 {
+
3578 double pow10 = (double)powl(10.0, iPower);
+
3579 uint64_t low64 = uint32x32((uint32_t)ulMant, (uint32_t)pow10);
+
3580 uint64_t high64 = uint32x32((uint32_t)(ulMant >> 32), (uint32_t)pow10);
+
3581 *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())) = (uint32_t)low64;
+
3582 high64 += low64 >> 32;
+
3583 *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset() + 4)) = (uint32_t)high64;
+
3584 high64 >>= 32;
+
3585 *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset() + 8)) = (uint32_t)high64;
+
3586 }
+
3587 else
+
3588 {
+
3589 // Have a big power of 10.
+
3590 assert(iPower <= 14);
+
3591 uint64_t low64;
+
3592 uint32_t high32;
+
3593 uint64x64(ulMant, (uint64_t)pow(10.0, iPower), low64, high32);
+
3594 *((uint64_t*)(_buffer.data() + _buffer.offset() + fbe_offset())) = low64;
+
3595 *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset() + 8)) = high32;
+
3596 }
+
3597 }
+
3598 else
+
3599 {
+
3600 // Factor out powers of 10 to reduce the scale, if possible.
+
3601 // The maximum number we could factor out would be 14. This
+
3602 // comes from the fact we have a 15-digit number, and the
+
3603 // MSD must be non-zero -- but the lower 14 digits could be
+
3604 // zero. Note also the scale factor is never negative, so
+
3605 // we can't scale by any more than the power we used to
+
3606 // get the integer.
+
3607 int lmax = iPower;
+
3608 if (lmax > 14)
+
3609 lmax = 14;
+
3610
+
3611 if ((((uint8_t)ulMant) == 0) && (lmax >= 8))
+
3612 {
+
3613 const uint32_t den = 100000000;
+
3614 uint64_t div = ulMant / den;
+
3615 if ((uint32_t)ulMant == (uint32_t)(div * den))
+
3616 {
+
3617 ulMant = div;
+
3618 iPower -= 8;
+
3619 lmax -= 8;
+
3620 }
+
3621 }
+
3622
+
3623 if ((((uint32_t)ulMant & 0xF) == 0) && (lmax >= 4))
+
3624 {
+
3625 const uint32_t den = 10000;
+
3626 uint64_t div = ulMant / den;
+
3627 if ((uint32_t)ulMant == (uint32_t)(div * den))
+
3628 {
+
3629 ulMant = div;
+
3630 iPower -= 4;
+
3631 lmax -= 4;
+
3632 }
+
3633 }
+
3634
+
3635 if ((((uint32_t)ulMant & 3) == 0) && (lmax >= 2))
+
3636 {
+
3637 const uint32_t den = 100;
+
3638 uint64_t div = ulMant / den;
+
3639 if ((uint32_t)ulMant == (uint32_t)(div * den))
+
3640 {
+
3641 ulMant = div;
+
3642 iPower -= 2;
+
3643 lmax -= 2;
+
3644 }
+
3645 }
+
3646
+
3647 if ((((uint32_t)ulMant & 1) == 0) && (lmax >= 1))
+
3648 {
+
3649 const uint32_t den = 10;
+
3650 uint64_t div = ulMant / den;
+
3651 if ((uint32_t)ulMant == (uint32_t)(div * den))
+
3652 {
+
3653 ulMant = div;
+
3654 iPower--;
+
3655 }
+
3656 }
+
3657
+
3658 flags |= (uint32_t)iPower << 16;
+
3659
+
3660 *((uint64_t*)(_buffer.data() + _buffer.offset() + fbe_offset())) = ulMant;
+
3661 *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset() + 8)) = 0;
+
3662 }
+
3663
+
3664 *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset() + 12)) = flags;
+
3665 return fbe_size();
+
3666}
+
3667)CODE";
+
3668
+
3669 // Prepare code template
+
3670 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
3671
+
3672 Write(code);
+
3673}
+
3674
+
3675void GeneratorCpp::GenerateFBEFinalModelUUID_Header()
+
3676{
+
3677 std::string code = R"CODE(
+
3678// Fast Binary Encoding final model UUID specialization
+
3679template <>
+
3680class FinalModel<uuid_t>
+
3681{
+
3682public:
+
3683 FinalModel(FBEBuffer& buffer, size_t offset) noexcept : _buffer(buffer), _offset(offset) {}
+
3684
+
3685 // Get the allocation size
+
3686 size_t fbe_allocation_size(uuid_t value) const noexcept { return fbe_size(); }
+
3687
+
3688 // Get the field offset
+
3689 size_t fbe_offset() const noexcept { return _offset; }
+
3690 // Set the field offset
+
3691 size_t fbe_offset(size_t offset) const noexcept { return _offset = offset; }
+
3692
+
3693 // Get the final size
+
3694 size_t fbe_size() const noexcept { return 16; }
+
3695
+
3696 // Shift the current field offset
+
3697 void fbe_shift(size_t size) noexcept { _offset += size; }
+
3698 // Unshift the current field offset
+
3699 void fbe_unshift(size_t size) noexcept { _offset -= size; }
+
3700
+
3701 // Check if the UUID value is valid
+
3702 size_t verify() const noexcept;
+
3703
+
3704 // Get the UUID value
+
3705 size_t get(uuid_t& value) const noexcept;
+
3706 // Set the UUID value
+
3707 size_t set(uuid_t value) noexcept;
+
3708
+
3709private:
+
3710 FBEBuffer& _buffer;
+
3711 mutable size_t _offset;
+
3712};
+
3713)CODE";
+
3714
+
3715 // Prepare code template
+
3716 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
3717
+
3718 Write(code);
+
3719}
+
3720
+
3721void GeneratorCpp::GenerateFBEFinalModelUUID_Source()
+
3722{
+
3723 std::string code = R"CODE(
+
3724size_t FinalModel<uuid_t>::verify() const noexcept
+
3725{
+
3726 if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size())
+
3727 return std::numeric_limits<std::size_t>::max();
+
3728
+
3729 return fbe_size();
+
3730}
+
3731
+
3732size_t FinalModel<uuid_t>::get(uuid_t& value) const noexcept
+
3733{
+
3734 if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size())
+
3735 return 0;
+
3736
+
3737 std::memcpy(value.data().data(), (const uint8_t*)(_buffer.data() + _buffer.offset() + fbe_offset()), fbe_size());
+
3738 return fbe_size();
+
3739}
+
3740
+
3741size_t FinalModel<uuid_t>::set(uuid_t value) noexcept
+
3742{
+
3743 assert(((_buffer.offset() + fbe_offset() + fbe_size()) <= _buffer.size()) && "Model is broken!");
+
3744 if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size())
+
3745 return 0;
+
3746
+
3747 std::memcpy((uint8_t*)(_buffer.data() + _buffer.offset() + fbe_offset()), value.data().data(), fbe_size());
+
3748 return fbe_size();
+
3749}
+
3750)CODE";
+
3751
+
3752 // Prepare code template
+
3753 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
3754
+
3755 Write(code);
+
3756}
+
3757
+
3758void GeneratorCpp::GenerateFBEFinalModelBytes_Header()
+
3759{
+
3760 std::string code = R"CODE(
+
3761// Fast Binary Encoding final model bytes specialization
+
3762template <>
+
3763class FinalModel<buffer_t>
+
3764{
+
3765public:
+
3766 FinalModel(FBEBuffer& buffer, size_t offset) noexcept : _buffer(buffer), _offset(offset) {}
+
3767
+
3768 // Get the allocation size
+
3769 size_t fbe_allocation_size(const void* data, size_t size) const noexcept { return 4 + size; }
+
3770 template <size_t N>
+
3771 size_t fbe_allocation_size(const uint8_t (&data)[N]) const noexcept { return 4 + N; }
+
3772 template <size_t N>
+
3773 size_t fbe_allocation_size(const std::array<uint8_t, N>& data) const noexcept { return 4 + N; }
+
3774 size_t fbe_allocation_size(const std::vector<uint8_t>& value) const noexcept { return 4 + value.size(); }
+
3775 size_t fbe_allocation_size(const buffer_t& value) const noexcept { return 4 + value.size(); }
+
3776
+
3777 // Get the field offset
+
3778 size_t fbe_offset() const noexcept { return _offset; }
+
3779 // Set the field offset
+
3780 size_t fbe_offset(size_t offset) const noexcept { return _offset = offset; }
+
3781
+
3782 // Shift the current field offset
+
3783 void fbe_shift(size_t size) noexcept { _offset += size; }
+
3784 // Unshift the current field offset
+
3785 void fbe_unshift(size_t size) noexcept { _offset -= size; }
+
3786
+
3787 // Check if the bytes value is valid
+
3788 size_t verify() const noexcept;
+
3789
+
3790 // Get the bytes value
+
3791 size_t get(void* data, size_t size) const noexcept;
+
3792 // Get the bytes value
+
3793 template <size_t N>
+
3794 size_t get(uint8_t (&data)[N]) const noexcept { return get(data, N); }
+
3795 // Get the bytes value
+
3796 template <size_t N>
+
3797 size_t get(std::array<uint8_t, N>& data) const noexcept { return get(data.data(), data.size()); }
+
3798 // Get the bytes value
+
3799 size_t get(std::vector<uint8_t>& value) const noexcept;
+
3800 // Get the bytes value
+
3801 size_t get(buffer_t& value) const noexcept { return get(value.buffer()); }
+
3802
+
3803 // Set the bytes value
+
3804 size_t set(const void* data, size_t size);
+
3805 // Set the bytes value
+
3806 template <size_t N>
+
3807 size_t set(const uint8_t (&data)[N]) { return set(data, N); }
+
3808 // Set the bytes value
+
3809 template <size_t N>
+
3810 size_t set(const std::array<uint8_t, N>& data) { return set(data.data(), data.size()); }
+
3811 // Set the bytes value
+
3812 size_t set(const std::vector<uint8_t>& value) { return set(value.data(), value.size()); }
+
3813 // Set the bytes value
+
3814 size_t set(const buffer_t& value) { return set(value.buffer()); }
+
3815
+
3816private:
+
3817 FBEBuffer& _buffer;
+
3818 mutable size_t _offset;
+
3819};
+
3820)CODE";
+
3821
+
3822 // Prepare code template
+
3823 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
3824
+
3825 Write(code);
+
3826}
+
3827
+
3828void GeneratorCpp::GenerateFBEFinalModelBytes_Source()
+
3829{
+
3830 std::string code = R"CODE(
+
3831size_t FinalModel<buffer_t>::verify() const noexcept
+
3832{
+
3833 if ((_buffer.offset() + fbe_offset() + 4) > _buffer.size())
+
3834 return std::numeric_limits<std::size_t>::max();
+
3835
+
3836 uint32_t fbe_bytes_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset()));
+
3837 if ((_buffer.offset() + fbe_offset() + 4 + fbe_bytes_size) > _buffer.size())
+
3838 return std::numeric_limits<std::size_t>::max();
+
3839
+
3840 return 4 + fbe_bytes_size;
+
3841}
+
3842
+
3843size_t FinalModel<buffer_t>::get(void* data, size_t size) const noexcept
+
3844{
+
3845 assert(((size == 0) || (data != nullptr)) && "Invalid buffer!");
+
3846 if ((size > 0) && (data == nullptr))
+
3847 return 0;
+
3848
+
3849 assert(((_buffer.offset() + fbe_offset() + 4) <= _buffer.size()) && "Model is broken!");
+
3850 if ((_buffer.offset() + fbe_offset() + 4) > _buffer.size())
+
3851 return 0;
+
3852
+
3853 uint32_t fbe_bytes_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset()));
+
3854 assert(((_buffer.offset() + fbe_offset() + 4 + fbe_bytes_size) <= _buffer.size()) && "Model is broken!");
+
3855 if ((_buffer.offset() + fbe_offset() + 4 + fbe_bytes_size) > _buffer.size())
+
3856 return 4;
+
3857
+
3858 size_t result = std::min(size, (size_t)fbe_bytes_size);
+
3859 memcpy(data, (const char*)(_buffer.data() + _buffer.offset() + fbe_offset() + 4), result);
+
3860 return 4 + fbe_bytes_size;
+
3861}
+
3862
+
3863size_t FinalModel<buffer_t>::get(std::vector<uint8_t>& value) const noexcept
+
3864{
+
3865 value.clear();
+
3866
+
3867 assert(((_buffer.offset() + fbe_offset() + 4) <= _buffer.size()) && "Model is broken!");
+
3868 if ((_buffer.offset() + fbe_offset() + 4) > _buffer.size())
+
3869 return 0;
+
3870
+
3871 uint32_t fbe_bytes_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset()));
+
3872 assert(((_buffer.offset() + fbe_offset() + 4 + fbe_bytes_size) <= _buffer.size()) && "Model is broken!");
+
3873 if ((_buffer.offset() + fbe_offset() + 4 + fbe_bytes_size) > _buffer.size())
+
3874 return 4;
+
3875
+
3876 const char* fbe_bytes = (const char*)(_buffer.data() + _buffer.offset() + fbe_offset() + 4);
+
3877 value.assign(fbe_bytes, fbe_bytes + fbe_bytes_size);
+
3878 return 4 + fbe_bytes_size;
+
3879}
+
3880
+
3881size_t FinalModel<buffer_t>::set(const void* data, size_t size)
+
3882{
+
3883 assert(((size == 0) || (data != nullptr)) && "Invalid buffer!");
+
3884 if ((size > 0) && (data == nullptr))
+
3885 return 0;
+
3886
+
3887 assert(((_buffer.offset() + fbe_offset() + 4) <= _buffer.size()) && "Model is broken!");
+
3888 if ((_buffer.offset() + fbe_offset() + 4) > _buffer.size())
+
3889 return 0;
+
3890
+
3891 uint32_t fbe_bytes_size = (uint32_t)size;
+
3892 assert(((_buffer.offset() + fbe_offset() + 4 + fbe_bytes_size) <= _buffer.size()) && "Model is broken!");
+
3893 if ((_buffer.offset() + fbe_offset() + 4 + fbe_bytes_size) > _buffer.size())
+
3894 return 4;
+
3895
+
3896 *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())) = fbe_bytes_size;
+
3897
+
3898 memcpy((char*)(_buffer.data() + _buffer.offset() + fbe_offset() + 4), data, fbe_bytes_size);
+
3899 return 4 + fbe_bytes_size;
+
3900}
+
3901)CODE";
+
3902
+
3903 // Prepare code template
+
3904 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
3905
+
3906 Write(code);
+
3907}
+
3908
+
3909void GeneratorCpp::GenerateFBEFinalModelString_Header()
+
3910{
+
3911 std::string code = R"CODE(
+
3912// Fast Binary Encoding final model string specialization
+
3913template <>
+
3914class FinalModel<std::string>
+
3915{
+
3916public:
+
3917 FinalModel(FBEBuffer& buffer, size_t offset) noexcept : _buffer(buffer), _offset(offset) {}
+
3918
+
3919 // Get the allocation size
+
3920 size_t fbe_allocation_size(const char* data, size_t size) const noexcept { return 4 + size; }
+
3921 template <size_t N>
+
3922 size_t fbe_allocation_size(const char (&data)[N]) const noexcept { return 4 + N; }
+
3923 template <size_t N>
+
3924 size_t fbe_allocation_size(const std::array<char, N>& data) const noexcept { return 4 + N; }
+
3925 size_t fbe_allocation_size(const std::string& value) const noexcept { return 4 + value.size(); }
+
3926
+
3927 // Get the field offset
+
3928 size_t fbe_offset() const noexcept { return _offset; }
+
3929 // Set the field offset
+
3930 size_t fbe_offset(size_t offset) const noexcept { return _offset = offset; }
+
3931
+
3932 // Shift the current field offset
+
3933 void fbe_shift(size_t size) noexcept { _offset += size; }
+
3934 // Unshift the current field offset
+
3935 void fbe_unshift(size_t size) noexcept { _offset -= size; }
+
3936
+
3937 // Check if the string value is valid
+
3938 size_t verify() const noexcept;
+
3939
+
3940 // Get the string value
+
3941 size_t get(char* data, size_t size) const noexcept;
+
3942 // Get the string value
+
3943 template <size_t N>
+
3944 size_t get(char (&data)[N]) const noexcept { return get(data, N); }
+
3945 // Get the string value
+
3946 template <size_t N>
+
3947 size_t get(std::array<char, N>& data) const noexcept { return get(data.data(), data.size()); }
+
3948 // Get the string value
+
3949 size_t get(std::string& value) const noexcept;
+
3950
+
3951 // Set the string value
+
3952 size_t set(const char* data, size_t size);
+
3953 // Set the string value
+
3954 template <size_t N>
+
3955 size_t set(const char (&data)[N]) { return set(data, N); }
+
3956 // Set the string value
+
3957 template <size_t N>
+
3958 size_t set(const std::array<char, N>& data) { return set(data.data(), data.size()); }
+
3959 // Set the string value
+
3960 size_t set(const std::string& value);
+
3961
+
3962private:
+
3963 FBEBuffer& _buffer;
+
3964 mutable size_t _offset;
+
3965};
+
3966)CODE";
+
3967
+
3968 // Prepare code template
+
3969 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
3970
+
3971 Write(code);
+
3972}
+
3973
+
3974void GeneratorCpp::GenerateFBEFinalModelString_Source()
+
3975{
+
3976 std::string code = R"CODE(
+
3977size_t FinalModel<std::string>::verify() const noexcept
+
3978{
+
3979 if ((_buffer.offset() + fbe_offset() + 4) > _buffer.size())
+
3980 return std::numeric_limits<std::size_t>::max();
+
3981
+
3982 uint32_t fbe_string_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset()));
+
3983 if ((_buffer.offset() + fbe_offset() + 4 + fbe_string_size) > _buffer.size())
+
3984 return std::numeric_limits<std::size_t>::max();
+
3985
+
3986 return 4 + fbe_string_size;
+
3987}
+
3988
+
3989size_t FinalModel<std::string>::get(char* data, size_t size) const noexcept
+
3990{
+
3991 assert(((size == 0) || (data != nullptr)) && "Invalid buffer!");
+
3992 if ((size > 0) && (data == nullptr))
+
3993 return 0;
+
3994
+
3995 assert(((_buffer.offset() + fbe_offset() + 4) <= _buffer.size()) && "Model is broken!");
+
3996 if ((_buffer.offset() + fbe_offset() + 4) > _buffer.size())
+
3997 return 0;
+
3998
+
3999 uint32_t fbe_string_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset()));
+
4000 assert(((_buffer.offset() + fbe_offset() + 4 + fbe_string_size) <= _buffer.size()) && "Model is broken!");
+
4001 if ((_buffer.offset() + fbe_offset() + 4 + fbe_string_size) > _buffer.size())
+
4002 return 4;
+
4003
+
4004 size_t result = std::min(size, (size_t)fbe_string_size);
+
4005 memcpy(data, (const char*)(_buffer.data() + _buffer.offset() + fbe_offset() + 4), result);
+
4006 return 4 + fbe_string_size;
+
4007}
+
4008
+
4009size_t FinalModel<std::string>::get(std::string& value) const noexcept
+
4010{
+
4011 value.clear();
+
4012
+
4013 assert(((_buffer.offset() + fbe_offset() + 4) <= _buffer.size()) && "Model is broken!");
+
4014 if ((_buffer.offset() + fbe_offset() + 4) > _buffer.size())
+
4015 return 0;
+
4016
+
4017 uint32_t fbe_string_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset()));
+
4018 assert(((_buffer.offset() + fbe_offset() + 4 + fbe_string_size) <= _buffer.size()) && "Model is broken!");
+
4019 if ((_buffer.offset() + fbe_offset() + 4 + fbe_string_size) > _buffer.size())
+
4020 return 4;
+
4021
+
4022 value.assign((const char*)(_buffer.data() + _buffer.offset() + fbe_offset() + 4), fbe_string_size);
+
4023 return 4 + fbe_string_size;
+
4024}
+
4025
+
4026size_t FinalModel<std::string>::set(const char* data, size_t size)
+
4027{
+
4028 assert(((size == 0) || (data != nullptr)) && "Invalid buffer!");
+
4029 if ((size > 0) && (data == nullptr))
+
4030 return 0;
+
4031
+
4032 assert(((_buffer.offset() + fbe_offset() + 4) <= _buffer.size()) && "Model is broken!");
+
4033 if ((_buffer.offset() + fbe_offset() + 4) > _buffer.size())
+
4034 return 0;
+
4035
+
4036 uint32_t fbe_string_size = (uint32_t)size;
+
4037 assert(((_buffer.offset() + fbe_offset() + 4 + fbe_string_size) <= _buffer.size()) && "Model is broken!");
+
4038 if ((_buffer.offset() + fbe_offset() + 4 + fbe_string_size) > _buffer.size())
+
4039 return 4;
+
4040
+
4041 *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())) = fbe_string_size;
+
4042
+
4043 memcpy((char*)(_buffer.data() + _buffer.offset() + fbe_offset() + 4), data, fbe_string_size);
+
4044 return 4 + fbe_string_size;
+
4045}
+
4046
+
4047size_t FinalModel<std::string>::set(const std::string& value)
+
4048{
+
4049 assert(((_buffer.offset() + fbe_offset() + 4) <= _buffer.size()) && "Model is broken!");
+
4050 if ((_buffer.offset() + fbe_offset() + 4) > _buffer.size())
+
4051 return 0;
+
4052
+
4053 uint32_t fbe_string_size = (uint32_t)value.size();
+
4054 assert(((_buffer.offset() + fbe_offset() + 4 + fbe_string_size) <= _buffer.size()) && "Model is broken!");
+
4055 if ((_buffer.offset() + fbe_offset() + 4 + fbe_string_size) > _buffer.size())
+
4056 return 4;
+
4057
+
4058 *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())) = fbe_string_size;
+
4059
+
4060 memcpy((char*)(_buffer.data() + _buffer.offset() + fbe_offset() + 4), value.data(), fbe_string_size);
+
4061 return 4 + fbe_string_size;
+
4062}
+
4063)CODE";
+
4064
+
4065 // Prepare code template
+
4066 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
4067
+
4068 Write(code);
+
4069}
+
4070
+
4071void GeneratorCpp::GenerateFBEFinalModelOptional_Header()
+
4072{
+
4073 std::string code = R"CODE(
+
4074// Fast Binary Encoding final model optional specialization
+
4075template <typename T>
+
4076class FinalModel<std::optional<T>>
+
4077{
+
4078public:
+
4079 FinalModel(FBEBuffer& buffer, size_t offset) noexcept : _buffer(buffer), _offset(offset), value(buffer, 0) {}
+
4080
+
4081 // Get the allocation size
+
4082 size_t fbe_allocation_size(const std::optional<T>& opt) const noexcept { return 1 + (opt ? value.fbe_allocation_size(opt.value()) : 0); }
+
4083
+
4084 // Get the field offset
+
4085 size_t fbe_offset() const noexcept { return _offset; }
+
4086 // Set the field offset
+
4087 size_t fbe_offset(size_t offset) const noexcept { return _offset = offset; }
+
4088
+
4089 // Shift the current field offset
+
4090 void fbe_shift(size_t size) noexcept { _offset += size; }
+
4091 // Unshift the current field offset
+
4092 void fbe_unshift(size_t size) noexcept { _offset -= size; }
+
4093
+
4095 explicit operator bool() const noexcept { return has_value(); }
+
4096
+
4097 // Checks if the object contains a value
+
4098 bool has_value() const noexcept;
+
4099
+
4100 // Check if the optional value is valid
+
4101 size_t verify() const noexcept;
+
4102
+
4103 // Get the optional value
+
4104 size_t get(std::optional<T>& opt) const noexcept;
+
4105 // Set the optional value
+
4106 size_t set(const std::optional<T>& opt);
+
4107
+
4108private:
+
4109 FBEBuffer& _buffer;
+
4110 mutable size_t _offset;
+
4111
+
4112public:
+
4113 // Base final model value
+
4114 FinalModel<T> value;
+
4115};
+
4116)CODE";
+
4117
+
4118 // Prepare code template
+
4119 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
4120
+
4121 Write(code);
+
4122}
+
4123
+
4124void GeneratorCpp::GenerateFBEFinalModelOptional_Inline()
+
4125{
+
4126 std::string code = R"CODE(
+
4127template <typename T>
+
4128inline bool FinalModel<std::optional<T>>::has_value() const noexcept
+
4129{
+
4130 if ((_buffer.offset() + fbe_offset() + 1) > _buffer.size())
+
4131 return false;
+
4132
+
4133 uint8_t fbe_has_value = *((const uint8_t*)(_buffer.data() + _buffer.offset() + fbe_offset()));
+
4134 return (fbe_has_value != 0);
+
4135}
+
4136
+
4137template <typename T>
+
4138inline size_t FinalModel<std::optional<T>>::verify() const noexcept
+
4139{
+
4140 if ((_buffer.offset() + fbe_offset() + 1) > _buffer.size())
+
4141 return std::numeric_limits<std::size_t>::max();
+
4142
+
4143 uint8_t fbe_has_value = *((const uint8_t*)(_buffer.data() + _buffer.offset() + fbe_offset()));
+
4144 if (fbe_has_value == 0)
+
4145 return 1;
+
4146
+
4147 _buffer.shift(fbe_offset() + 1);
+
4148 size_t fbe_result = value.verify();
+
4149 _buffer.unshift(fbe_offset() + 1);
+
4150 return 1 + fbe_result;
+
4151}
+
4152
+
4153template <typename T>
+
4154inline size_t FinalModel<std::optional<T>>::get(std::optional<T>& opt) const noexcept
+
4155{
+
4156 opt = std::nullopt;
+
4157
+
4158 assert(((_buffer.offset() + fbe_offset() + 1) <= _buffer.size()) && "Model is broken!");
+
4159 if ((_buffer.offset() + fbe_offset() + 1) > _buffer.size())
+
4160 return 0;
+
4161
+
4162 if (!has_value())
+
4163 return 1;
+
4164
+
4165 _buffer.shift(fbe_offset() + 1);
+
4166 T temp = T();
+
4167 size_t size = value.get(temp);
+
4168 opt.emplace(temp);
+
4169 _buffer.unshift(fbe_offset() + 1);
+
4170 return 1 + size;
+
4171}
+
4172
+
4173template <typename T>
+
4174inline size_t FinalModel<std::optional<T>>::set(const std::optional<T>& opt)
+
4175{
+
4176 assert(((_buffer.offset() + fbe_offset() + 1) <= _buffer.size()) && "Model is broken!");
+
4177 if ((_buffer.offset() + fbe_offset() + 1) > _buffer.size())
+
4178 return 0;
+
4179
+
4180 uint8_t fbe_has_value = opt ? 1 : 0;
+
4181 *((uint8_t*)(_buffer.data() + _buffer.offset() + fbe_offset())) = fbe_has_value;
+
4182 if (fbe_has_value == 0)
+
4183 return 1;
+
4184
+
4185 _buffer.shift(fbe_offset() + 1);
+
4186 size_t size = 0;
+
4187 if (opt)
+
4188 size = value.set(opt.value());
+
4189 _buffer.unshift(fbe_offset() + 1);
+
4190 return 1 + size;
+
4191}
+
4192)CODE";
+
4193
+
4194 // Prepare code template
+
4195 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
4196
+
4197 Write(code);
+
4198}
+
4199
+
4200void GeneratorCpp::GenerateFBEFinalModelArray_Header()
+
4201{
+
4202 std::string code = R"CODE(
+
4203// Fast Binary Encoding final model array
+
4204template <typename T, size_t N>
+
4205class FinalModelArray
+
4206{
+
4207public:
+
4208 FinalModelArray(FBEBuffer& buffer, size_t offset) noexcept : _buffer(buffer), _offset(offset) {}
+
4209
+
4210 // Get the allocation size
+
4211 template <size_t S>
+
4212 size_t fbe_allocation_size(const T (&values)[S]) const noexcept;
+
4213 template <size_t S>
+
4214 size_t fbe_allocation_size(const std::array<T, S>& values) const noexcept;
+
4215 size_t fbe_allocation_size(const std::vector<T>& values) const noexcept;
+
4216
+
4217 // Get the field offset
+
4218 size_t fbe_offset() const noexcept { return _offset; }
+
4219 // Set the field offset
+
4220 size_t fbe_offset(size_t offset) const noexcept { return _offset = offset; }
+
4221
+
4222 // Shift the current field offset
+
4223 void fbe_shift(size_t size) noexcept { _offset += size; }
+
4224 // Unshift the current field offset
+
4225 void fbe_unshift(size_t size) noexcept { _offset -= size; }
+
4226
+
4227 // Check if the array is valid
+
4228 size_t verify() const noexcept;
+
4229
+
4230 // Get the array as C-array
+
4231 template <size_t S>
+
4232 size_t get(T (&values)[S]) const noexcept;
+
4233 // Get the array as std::array
+
4234 template <size_t S>
+
4235 size_t get(std::array<T, S>& values) const noexcept;
+
4236 // Get the array as std::vector
+
4237 size_t get(std::vector<T>& values) const noexcept;
+
4238
+
4239 // Set the array as C-array
+
4240 template <size_t S>
+
4241 size_t set(const T (&values)[S]) noexcept;
+
4242 // Set the array as std::array
+
4243 template <size_t S>
+
4244 size_t set(const std::array<T, S>& values) noexcept;
+
4245 // Set the array as std::vector
+
4246 size_t set(const std::vector<T>& values) noexcept;
+
4247
+
4248private:
+
4249 FBEBuffer& _buffer;
+
4250 mutable size_t _offset;
+
4251};
+
4252)CODE";
+
4253
+
4254 // Prepare code template
+
4255 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
4256
+
4257 Write(code);
+
4258}
+
4259
+
4260void GeneratorCpp::GenerateFBEFinalModelArray_Inline()
+
4261{
+
4262 std::string code = R"CODE(
+
4263template <typename T, size_t N>
+
4264template <size_t S>
+
4265inline size_t FinalModelArray<T, N>::fbe_allocation_size(const T (&values)[S]) const noexcept
+
4266{
+
4267 size_t size = 0;
+
4268 FinalModel<T> fbe_model(_buffer, fbe_offset());
+
4269 for (size_t i = 0; (i < S) && (i < N); ++i)
+
4270 size += fbe_model.fbe_allocation_size(values[i]);
+
4271 return size;
+
4272}
+
4273
+
4274template <typename T, size_t N>
+
4275template <size_t S>
+
4276inline size_t FinalModelArray<T, N>::fbe_allocation_size(const std::array<T, S>& values) const noexcept
+
4277{
+
4278 size_t size = 0;
+
4279 FinalModel<T> fbe_model(_buffer, fbe_offset());
+
4280 for (size_t i = 0; (i < S) && (i < N); ++i)
+
4281 size += fbe_model.fbe_allocation_size(values[i]);
+
4282 return size;
+
4283}
+
4284
+
4285template <typename T, size_t N>
+
4286inline size_t FinalModelArray<T, N>::fbe_allocation_size(const std::vector<T>& values) const noexcept
+
4287{
+
4288 size_t size = 0;
+
4289 FinalModel<T> fbe_model(_buffer, fbe_offset());
+
4290 for (size_t i = 0; (i < values.size()) && (i < N); ++i)
+
4291 size += fbe_model.fbe_allocation_size(values[i]);
+
4292 return size;
+
4293}
+
4294
+
4295template <typename T, size_t N>
+
4296inline size_t FinalModelArray<T, N>::verify() const noexcept
+
4297{
+
4298 if ((_buffer.offset() + fbe_offset()) > _buffer.size())
+
4299 return std::numeric_limits<std::size_t>::max();
+
4300
+
4301 size_t size = 0;
+
4302 FinalModel<T> fbe_model(_buffer, fbe_offset());
+
4303 for (size_t i = N; i-- > 0;)
+
4304 {
+
4305 size_t offset = fbe_model.verify();
+
4306 if (offset == std::numeric_limits<std::size_t>::max())
+
4307 return std::numeric_limits<std::size_t>::max();
+
4308 fbe_model.fbe_shift(offset);
+
4309 size += offset;
+
4310 }
+
4311 return size;
+
4312}
+
4313
+
4314template <typename T, size_t N>
+
4315template <size_t S>
+
4316inline size_t FinalModelArray<T, N>::get(T (&values)[S]) const noexcept
+
4317{
+
4318 assert(((_buffer.offset() + fbe_offset()) <= _buffer.size()) && "Model is broken!");
+
4319 if ((_buffer.offset() + fbe_offset()) > _buffer.size())
+
4320 return 0;
+
4321
+
4322 size_t size = 0;
+
4323 FinalModel<T> fbe_model(_buffer, fbe_offset());
+
4324 for (size_t i = 0; (i < S) && (i < N); ++i)
+
4325 {
+
4326 size_t offset = fbe_model.get(values[i]);
+
4327 fbe_model.fbe_shift(offset);
+
4328 size += offset;
+
4329 }
+
4330 return size;
+
4331}
+
4332
+
4333template <typename T, size_t N>
+
4334template <size_t S>
+
4335inline size_t FinalModelArray<T, N>::get(std::array<T, S>& values) const noexcept
+
4336{
+
4337 assert(((_buffer.offset() + fbe_offset()) <= _buffer.size()) && "Model is broken!");
+
4338 if ((_buffer.offset() + fbe_offset()) > _buffer.size())
+
4339 return 0;
+
4340
+
4341 size_t size = 0;
+
4342 FinalModel<T> fbe_model(_buffer, fbe_offset());
+
4343 for (size_t i = 0; (i < S) && (i < N); ++i)
+
4344 {
+
4345 size_t offset = fbe_model.get(values[i]);
+
4346 fbe_model.fbe_shift(offset);
+
4347 size += offset;
+
4348 }
+
4349 return size;
+
4350}
+
4351
+
4352template <typename T, size_t N>
+
4353inline size_t FinalModelArray<T, N>::get(std::vector<T>& values) const noexcept
+
4354{
+
4355 values.clear();
+
4356
+
4357 assert(((_buffer.offset() + fbe_offset()) <= _buffer.size()) && "Model is broken!");
+
4358 if ((_buffer.offset() + fbe_offset()) > _buffer.size())
+
4359 return 0;
+
4360
+
4361 values.reserve(N);
+
4362
+
4363 size_t size = 0;
+
4364 FinalModel<T> fbe_model(_buffer, fbe_offset());
+
4365 for (size_t i = N; i-- > 0;)
+
4366 {
+
4367 T value = T();
+
4368 size_t offset = fbe_model.get(value);
+
4369 values.emplace_back(value);
+
4370 fbe_model.fbe_shift(offset);
+
4371 size += offset;
+
4372 }
+
4373 return size;
+
4374}
+
4375
+
4376template <typename T, size_t N>
+
4377template <size_t S>
+
4378inline size_t FinalModelArray<T, N>::set(const T (&values)[S]) noexcept
+
4379{
+
4380 assert(((_buffer.offset() + fbe_offset()) <= _buffer.size()) && "Model is broken!");
+
4381 if ((_buffer.offset() + fbe_offset()) > _buffer.size())
+
4382 return 0;
+
4383
+
4384 size_t size = 0;
+
4385 FinalModel<T> fbe_model(_buffer, fbe_offset());
+
4386 for (size_t i = 0; (i < S) && (i < N); ++i)
+
4387 {
+
4388 size_t offset = fbe_model.set(values[i]);
+
4389 fbe_model.fbe_shift(offset);
+
4390 size += offset;
+
4391 }
+
4392 return size;
+
4393}
+
4394
+
4395template <typename T, size_t N>
+
4396template <size_t S>
+
4397inline size_t FinalModelArray<T, N>::set(const std::array<T, S>& values) noexcept
+
4398{
+
4399 assert(((_buffer.offset() + fbe_offset()) <= _buffer.size()) && "Model is broken!");
+
4400 if ((_buffer.offset() + fbe_offset()) > _buffer.size())
+
4401 return 0;
+
4402
+
4403 size_t size = 0;
+
4404 FinalModel<T> fbe_model(_buffer, fbe_offset());
+
4405 for (size_t i = 0; (i < S) && (i < N); ++i)
+
4406 {
+
4407 size_t offset = fbe_model.set(values[i]);
+
4408 fbe_model.fbe_shift(offset);
+
4409 size += offset;
+
4410 }
+
4411 return size;
+
4412}
+
4413
+
4414template <typename T, size_t N>
+
4415inline size_t FinalModelArray<T, N>::set(const std::vector<T>& values) noexcept
+
4416{
+
4417 assert(((_buffer.offset() + fbe_offset()) <= _buffer.size()) && "Model is broken!");
+
4418 if ((_buffer.offset() + fbe_offset()) > _buffer.size())
+
4419 return 0;
+
4420
+
4421 size_t size = 0;
+
4422 FinalModel<T> fbe_model(_buffer, fbe_offset());
+
4423 for (size_t i = 0; (i < values.size()) && (i < N); ++i)
+
4424 {
+
4425 size_t offset = fbe_model.set(values[i]);
+
4426 fbe_model.fbe_shift(offset);
+
4427 size += offset;
+
4428 }
+
4429 return size;
+
4430}
+
4431)CODE";
+
4432
+
4433 // Prepare code template
+
4434 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
4435
+
4436 Write(code);
+
4437}
+
4438
+
4439void GeneratorCpp::GenerateFBEFinalModelVector_Header()
+
4440{
+
4441 std::string code = R"CODE(
+
4442// Fast Binary Encoding final model vector
+
4443template <typename T>
+
4444class FinalModelVector
+
4445{
+
4446public:
+
4447 FinalModelVector(FBEBuffer& buffer, size_t offset) noexcept : _buffer(buffer), _offset(offset) {}
+
4448
+
4449 // Get the allocation size
+
4450 size_t fbe_allocation_size(const std::vector<T>& values) const noexcept;
+
4451 size_t fbe_allocation_size(const std::list<T>& values) const noexcept;
+
4452 size_t fbe_allocation_size(const std::set<T>& values) const noexcept;
+
4453
+
4454 // Get the field offset
+
4455 size_t fbe_offset() const noexcept { return _offset; }
+
4456 // Set the field offset
+
4457 size_t fbe_offset(size_t offset) const noexcept { return _offset = offset; }
+
4458
+
4459 // Shift the current field offset
+
4460 void fbe_shift(size_t size) noexcept { _offset += size; }
+
4461 // Unshift the current field offset
+
4462 void fbe_unshift(size_t size) noexcept { _offset -= size; }
+
4463
+
4464 // Check if the vector is valid
+
4465 size_t verify() const noexcept;
+
4466
+
4467 // Get the vector as std::vector
+
4468 size_t get(std::vector<T>& values) const noexcept;
+
4469 // Get the vector as std::list
+
4470 size_t get(std::list<T>& values) const noexcept;
+
4471 // Get the vector as std::set
+
4472 size_t get(std::set<T>& values) const noexcept;
+
4473
+
4474 // Set the vector as std::vector
+
4475 size_t set(const std::vector<T>& values) noexcept;
+
4476 // Set the vector as std::list
+
4477 size_t set(const std::list<T>& values) noexcept;
+
4478 // Set the vector as std::set
+
4479 size_t set(const std::set<T>& values) noexcept;
+
4480
+
4481private:
+
4482 FBEBuffer& _buffer;
+
4483 mutable size_t _offset;
+
4484};
+
4485)CODE";
+
4486
+
4487 // Prepare code template
+
4488 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
4489
+
4490 Write(code);
+
4491}
+
4492
+
4493void GeneratorCpp::GenerateFBEFinalModelVector_Inline()
+
4494{
+
4495 std::string code = R"CODE(
+
4496template <typename T>
+
4497inline size_t FinalModelVector<T>::fbe_allocation_size(const std::vector<T>& values) const noexcept
+
4498{
+
4499 size_t size = 4;
+
4500 FinalModel<T> fbe_model(_buffer, fbe_offset() + 4);
+
4501 for (const auto& value : values)
+
4502 size += fbe_model.fbe_allocation_size(value);
+
4503 return size;
+
4504}
+
4505
+
4506template <typename T>
+
4507inline size_t FinalModelVector<T>::fbe_allocation_size(const std::list<T>& values) const noexcept
+
4508{
+
4509 size_t size = 4;
+
4510 FinalModel<T> fbe_model(_buffer, fbe_offset() + 4);
+
4511 for (const auto& value : values)
+
4512 size += fbe_model.fbe_allocation_size(value);
+
4513 return size;
+
4514}
+
4515
+
4516template <typename T>
+
4517inline size_t FinalModelVector<T>::fbe_allocation_size(const std::set<T>& values) const noexcept
+
4518{
+
4519 size_t size = 4;
+
4520 FinalModel<T> fbe_model(_buffer, fbe_offset() + 4);
+
4521 for (const auto& value : values)
+
4522 size += fbe_model.fbe_allocation_size(value);
+
4523 return size;
+
4524}
+
4525
+
4526template <typename T>
+
4527inline size_t FinalModelVector<T>::verify() const noexcept
+
4528{
+
4529 if ((_buffer.offset() + fbe_offset() + 4) > _buffer.size())
+
4530 return std::numeric_limits<std::size_t>::max();
+
4531
+
4532 uint32_t fbe_vector_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset()));
+
4533
+
4534 size_t size = 4;
+
4535 FinalModel<T> fbe_model(_buffer, fbe_offset() + 4);
+
4536 for (size_t i = fbe_vector_size; i-- > 0;)
+
4537 {
+
4538 size_t offset = fbe_model.verify();
+
4539 if (offset == std::numeric_limits<std::size_t>::max())
+
4540 return std::numeric_limits<std::size_t>::max();
+
4541 fbe_model.fbe_shift(offset);
+
4542 size += offset;
+
4543 }
+
4544 return size;
+
4545}
+
4546
+
4547template <typename T>
+
4548inline size_t FinalModelVector<T>::get(std::vector<T>& values) const noexcept
+
4549{
+
4550 values.clear();
+
4551
+
4552 assert(((_buffer.offset() + fbe_offset() + 4) <= _buffer.size()) && "Model is broken!");
+
4553 if ((_buffer.offset() + fbe_offset() + 4) > _buffer.size())
+
4554 return 0;
+
4555
+
4556 size_t fbe_vector_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset()));
+
4557 if (fbe_vector_size == 0)
+
4558 return 4;
+
4559
+
4560 values.reserve(fbe_vector_size);
+
4561
+
4562 size_t size = 4;
+
4563 FinalModel<T> fbe_model(_buffer, fbe_offset() + 4);
+
4564 for (size_t i = fbe_vector_size; i-- > 0;)
+
4565 {
+
4566 T value = T();
+
4567 size_t offset = fbe_model.get(value);
+
4568 values.emplace_back(value);
+
4569 fbe_model.fbe_shift(offset);
+
4570 size += offset;
+
4571 }
+
4572 return size;
+
4573}
+
4574
+
4575template <typename T>
+
4576inline size_t FinalModelVector<T>::get(std::list<T>& values) const noexcept
+
4577{
+
4578 values.clear();
+
4579
+
4580 assert(((_buffer.offset() + fbe_offset() + 4) <= _buffer.size()) && "Model is broken!");
+
4581 if ((_buffer.offset() + fbe_offset() + 4) > _buffer.size())
+
4582 return 0;
+
4583
+
4584 size_t fbe_vector_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset()));
+
4585 if (fbe_vector_size == 0)
+
4586 return 4;
+
4587
+
4588 size_t size = 4;
+
4589 FinalModel<T> fbe_model(_buffer, fbe_offset() + 4);
+
4590 for (size_t i = fbe_vector_size; i-- > 0;)
+
4591 {
+
4592 T value = T();
+
4593 size_t offset = fbe_model.get(value);
+
4594 values.emplace_back(value);
+
4595 fbe_model.fbe_shift(offset);
+
4596 size += offset;
+
4597 }
+
4598 return size;
+
4599}
+
4600
+
4601template <typename T>
+
4602inline size_t FinalModelVector<T>::get(std::set<T>& values) const noexcept
+
4603{
+
4604 values.clear();
+
4605
+
4606 assert(((_buffer.offset() + fbe_offset() + 4) <= _buffer.size()) && "Model is broken!");
+
4607 if ((_buffer.offset() + fbe_offset() + 4) > _buffer.size())
+
4608 return 0;
+
4609
+
4610 size_t fbe_vector_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset()));
+
4611 if (fbe_vector_size == 0)
+
4612 return 4;
+
4613
+
4614 size_t size = 4;
+
4615 FinalModel<T> fbe_model(_buffer, fbe_offset() + 4);
+
4616 for (size_t i = fbe_vector_size; i-- > 0;)
+
4617 {
+
4618 T value = T();
+
4619 size_t offset = fbe_model.get(value);
+
4620 values.emplace(value);
+
4621 fbe_model.fbe_shift(offset);
+
4622 size += offset;
+
4623 }
+
4624 return size;
+
4625}
+
4626
+
4627template <typename T>
+
4628inline size_t FinalModelVector<T>::set(const std::vector<T>& values) noexcept
+
4629{
+
4630 assert(((_buffer.offset() + fbe_offset() + 4) <= _buffer.size()) && "Model is broken!");
+
4631 if ((_buffer.offset() + fbe_offset() + 4) > _buffer.size())
+
4632 return 0;
+
4633
+
4634 *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())) = (uint32_t)values.size();
+
4635
+
4636 size_t size = 4;
+
4637 FinalModel<T> fbe_model(_buffer, fbe_offset() + 4);
+
4638 for (const auto& value : values)
+
4639 {
+
4640 size_t offset = fbe_model.set(value);
+
4641 fbe_model.fbe_shift(offset);
+
4642 size += offset;
+
4643 }
+
4644 return size;
+
4645}
+
4646
+
4647template <typename T>
+
4648inline size_t FinalModelVector<T>::set(const std::list<T>& values) noexcept
+
4649{
+
4650 assert(((_buffer.offset() + fbe_offset() + 4) <= _buffer.size()) && "Model is broken!");
+
4651 if ((_buffer.offset() + fbe_offset() + 4) > _buffer.size())
+
4652 return 0;
+
4653
+
4654 *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())) = (uint32_t)values.size();
+
4655
+
4656 size_t size = 4;
+
4657 FinalModel<T> fbe_model(_buffer, fbe_offset() + 4);
+
4658 for (const auto& value : values)
+
4659 {
+
4660 size_t offset = fbe_model.set(value);
+
4661 fbe_model.fbe_shift(offset);
+
4662 size += offset;
+
4663 }
+
4664 return size;
+
4665}
+
4666
+
4667template <typename T>
+
4668inline size_t FinalModelVector<T>::set(const std::set<T>& values) noexcept
+
4669{
+
4670 assert(((_buffer.offset() + fbe_offset() + 4) <= _buffer.size()) && "Model is broken!");
+
4671 if ((_buffer.offset() + fbe_offset() + 4) > _buffer.size())
+
4672 return 0;
+
4673
+
4674 *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())) = (uint32_t)values.size();
+
4675
+
4676 size_t size = 4;
+
4677 FinalModel<T> fbe_model(_buffer, fbe_offset() + 4);
+
4678 for (const auto& value : values)
+
4679 {
+
4680 size_t offset = fbe_model.set(value);
+
4681 fbe_model.fbe_shift(offset);
+
4682 size += offset;
+
4683 }
+
4684 return size;
+
4685}
+
4686)CODE";
+
4687
+
4688 // Prepare code template
+
4689 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
4690
+
4691 Write(code);
+
4692}
+
4693
+
4694void GeneratorCpp::GenerateFBEFinalModelMap_Header()
+
4695{
+
4696 std::string code = R"CODE(
+
4697// Fast Binary Encoding final model map
+
4698template <typename TKey, typename TValue>
+
4699class FinalModelMap
+
4700{
+
4701public:
+
4702 FinalModelMap(FBEBuffer& buffer, size_t offset) noexcept : _buffer(buffer), _offset(offset) {}
+
4703
+
4704 // Get the allocation size
+
4705 size_t fbe_allocation_size(const std::map<TKey, TValue>& values) const noexcept;
+
4706 size_t fbe_allocation_size(const std::unordered_map<TKey, TValue>& values) const noexcept;
+
4707
+
4708 // Get the field offset
+
4709 size_t fbe_offset() const noexcept { return _offset; }
+
4710 // Set the field offset
+
4711 size_t fbe_offset(size_t offset) const noexcept { return _offset = offset; }
+
4712
+
4713 // Shift the current field offset
+
4714 void fbe_shift(size_t size) noexcept { _offset += size; }
+
4715 // Unshift the current field offset
+
4716 void fbe_unshift(size_t size) noexcept { _offset -= size; }
+
4717
+
4718 // Check if the map is valid
+
4719 size_t verify() const noexcept;
+
4720
+
4721 // Get the map as std::map
+
4722 size_t get(std::map<TKey, TValue>& values) const noexcept;
+
4723 // Get the map as std::unordered_map
+
4724 size_t get(std::unordered_map<TKey, TValue>& values) const noexcept;
+
4725
+
4726 // Set the map as std::map
+
4727 size_t set(const std::map<TKey, TValue>& values) noexcept;
+
4728 // Set the map as std::unordered_map
+
4729 size_t set(const std::unordered_map<TKey, TValue>& values) noexcept;
+
4730
+
4731private:
+
4732 FBEBuffer& _buffer;
+
4733 mutable size_t _offset;
+
4734};
+
4735)CODE";
+
4736
+
4737 // Prepare code template
+
4738 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
4739
+
4740 Write(code);
+
4741}
+
4742
+
4743void GeneratorCpp::GenerateFBEFinalModelMap_Inline()
+
4744{
+
4745 std::string code = R"CODE(
+
4746template <typename TKey, typename TValue>
+
4747inline size_t FinalModelMap<TKey, TValue>::fbe_allocation_size(const std::map<TKey, TValue>& values) const noexcept
+
4748{
+
4749 size_t size = 4;
+
4750 FinalModel<TKey> fbe_model_key(_buffer, fbe_offset() + 4);
+
4751 FinalModel<TValue> fbe_model_value(_buffer, fbe_offset() + 4);
+
4752 for (const auto& value : values)
+
4753 {
+
4754 size += fbe_model_key.fbe_allocation_size(value.first);
+
4755 size += fbe_model_value.fbe_allocation_size(value.second);
+
4756 }
+
4757 return size;
+
4758}
+
4759
+
4760template <typename TKey, typename TValue>
+
4761inline size_t FinalModelMap<TKey, TValue>::fbe_allocation_size(const std::unordered_map<TKey, TValue>& values) const noexcept
+
4762{
+
4763 size_t size = 4;
+
4764 FinalModel<TKey> fbe_model_key(_buffer, fbe_offset() + 4);
+
4765 FinalModel<TValue> fbe_model_value(_buffer, fbe_offset() + 4);
+
4766 for (const auto& value : values)
+
4767 {
+
4768 size += fbe_model_key.fbe_allocation_size(value.first);
+
4769 size += fbe_model_value.fbe_allocation_size(value.second);
+
4770 }
+
4771 return size;
+
4772}
+
4773
+
4774template <typename TKey, typename TValue>
+
4775inline size_t FinalModelMap<TKey, TValue>::verify() const noexcept
+
4776{
+
4777 if ((_buffer.offset() + fbe_offset() + 4) > _buffer.size())
+
4778 return std::numeric_limits<std::size_t>::max();
+
4779
+
4780 uint32_t fbe_map_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset()));
+
4781
+
4782 size_t size = 4;
+
4783 FinalModel<TKey> fbe_model_key(_buffer, fbe_offset() + 4);
+
4784 FinalModel<TValue> fbe_model_value(_buffer, fbe_offset() + 4);
+
4785 for (size_t i = fbe_map_size; i-- > 0;)
+
4786 {
+
4787 size_t offset_key = fbe_model_key.verify();
+
4788 if (offset_key == std::numeric_limits<std::size_t>::max())
+
4789 return std::numeric_limits<std::size_t>::max();
+
4790 fbe_model_key.fbe_shift(offset_key);
+
4791 fbe_model_value.fbe_shift(offset_key);
+
4792 size += offset_key;
+
4793 size_t offset_value = fbe_model_value.verify();
+
4794 if (offset_value == std::numeric_limits<std::size_t>::max())
+
4795 return std::numeric_limits<std::size_t>::max();
+
4796 fbe_model_key.fbe_shift(offset_value);
+
4797 fbe_model_value.fbe_shift(offset_value);
+
4798 size += offset_value;
+
4799 }
+
4800 return size;
+
4801}
+
4802
+
4803template <typename TKey, typename TValue>
+
4804inline size_t FinalModelMap<TKey, TValue>::get(std::map<TKey, TValue>& values) const noexcept
+
4805{
+
4806 values.clear();
+
4807
+
4808 assert(((_buffer.offset() + fbe_offset() + 4) <= _buffer.size()) && "Model is broken!");
+
4809 if ((_buffer.offset() + fbe_offset() + 4) > _buffer.size())
+
4810 return 0;
+
4811
+
4812 size_t fbe_map_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset()));
+
4813 if (fbe_map_size == 0)
+
4814 return 4;
+
4815
+
4816 size_t size = 4;
+
4817 FinalModel<TKey> fbe_model_key(_buffer, fbe_offset() + 4);
+
4818 FinalModel<TValue> fbe_model_value(_buffer, fbe_offset() + 4);
+
4819 for (size_t i = fbe_map_size; i-- > 0;)
+
4820 {
+
4821 TKey key = TKey();
+
4822 TValue value = TValue();
+
4823 size_t offset_key = fbe_model_key.get(key);
+
4824 fbe_model_key.fbe_shift(offset_key);
+
4825 fbe_model_value.fbe_shift(offset_key);
+
4826 size_t offset_value = fbe_model_value.get(value);
+
4827 fbe_model_key.fbe_shift(offset_value);
+
4828 fbe_model_value.fbe_shift(offset_value);
+
4829 values.emplace(key, value);
+
4830 size += offset_key + offset_value;
+
4831 }
+
4832 return size;
+
4833}
+
4834
+
4835template <typename TKey, typename TValue>
+
4836inline size_t FinalModelMap<TKey, TValue>::get(std::unordered_map<TKey, TValue>& values) const noexcept
+
4837{
+
4838 values.clear();
+
4839
+
4840 assert(((_buffer.offset() + fbe_offset() + 4) <= _buffer.size()) && "Model is broken!");
+
4841 if ((_buffer.offset() + fbe_offset() + 4) > _buffer.size())
+
4842 return 0;
+
4843
+
4844 size_t fbe_map_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset()));
+
4845 if (fbe_map_size == 0)
+
4846 return 4;
+
4847
+
4848 size_t size = 4;
+
4849 FinalModel<TKey> fbe_model_key(_buffer, fbe_offset() + 4);
+
4850 FinalModel<TValue> fbe_model_value(_buffer, fbe_offset() + 4);
+
4851 for (size_t i = fbe_map_size; i-- > 0;)
+
4852 {
+
4853 TKey key = TKey();
+
4854 TValue value = TValue();
+
4855 size_t offset_key = fbe_model_key.get(key);
+
4856 fbe_model_key.fbe_shift(offset_key);
+
4857 fbe_model_value.fbe_shift(offset_key);
+
4858 size_t offset_value = fbe_model_value.get(value);
+
4859 fbe_model_key.fbe_shift(offset_value);
+
4860 fbe_model_value.fbe_shift(offset_value);
+
4861 values.emplace(key, value);
+
4862 size += offset_key + offset_value;
+
4863 }
+
4864 return size;
+
4865}
+
4866
+
4867template <typename TKey, typename TValue>
+
4868inline size_t FinalModelMap<TKey, TValue>::set(const std::map<TKey, TValue>& values) noexcept
+
4869{
+
4870 assert(((_buffer.offset() + fbe_offset() + 4) <= _buffer.size()) && "Model is broken!");
+
4871 if ((_buffer.offset() + fbe_offset() + 4) > _buffer.size())
+
4872 return 0;
+
4873
+
4874 *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())) = (uint32_t)values.size();
+
4875
+
4876 size_t size = 4;
+
4877 FinalModel<TKey> fbe_model_key(_buffer, fbe_offset() + 4);
+
4878 FinalModel<TValue> fbe_model_value(_buffer, fbe_offset() + 4);
+
4879 for (const auto& value : values)
+
4880 {
+
4881 size_t offset_key = fbe_model_key.set(value.first);
+
4882 fbe_model_key.fbe_shift(offset_key);
+
4883 fbe_model_value.fbe_shift(offset_key);
+
4884 size_t offset_value = fbe_model_value.set(value.second);
+
4885 fbe_model_key.fbe_shift(offset_value);
+
4886 fbe_model_value.fbe_shift(offset_value);
+
4887 size += offset_key + offset_value;
+
4888 }
+
4889 return size;
+
4890}
+
4891
+
4892template <typename TKey, typename TValue>
+
4893inline size_t FinalModelMap<TKey, TValue>::set(const std::unordered_map<TKey, TValue>& values) noexcept
+
4894{
+
4895 assert(((_buffer.offset() + fbe_offset() + 4) <= _buffer.size()) && "Model is broken!");
+
4896 if ((_buffer.offset() + fbe_offset() + 4) > _buffer.size())
+
4897 return 0;
+
4898
+
4899 *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())) = (uint32_t)values.size();
+
4900
+
4901 size_t size = 4;
+
4902 FinalModel<TKey> fbe_model_key(_buffer, fbe_offset() + 4);
+
4903 FinalModel<TValue> fbe_model_value(_buffer, fbe_offset() + 4);
+
4904 for (const auto& value : values)
+
4905 {
+
4906 size_t offset_key = fbe_model_key.set(value.first);
+
4907 fbe_model_key.fbe_shift(offset_key);
+
4908 fbe_model_value.fbe_shift(offset_key);
+
4909 size_t offset_value = fbe_model_value.set(value.second);
+
4910 fbe_model_key.fbe_shift(offset_value);
+
4911 fbe_model_value.fbe_shift(offset_value);
+
4912 size += offset_key + offset_value;
+
4913 }
+
4914 return size;
+
4915}
+
4916)CODE";
+
4917
+
4918 // Prepare code template
+
4919 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
4920
+
4921 Write(code);
+
4922}
+
4923
+
4924void GeneratorCpp::GenerateFBESender_Header()
+
4925{
+
4926 std::string code = R"CODE(
+
4927// Fast Binary Encoding base sender
+
4928class Sender
+
4929{
+
4930public:
+
4931 Sender(const Sender&) = delete;
+
4932 Sender(Sender&&) noexcept = delete;
+
4933 virtual ~Sender() = default;
+
4934
+
4935 Sender& operator=(const Sender&) = delete;
+
4936 Sender& operator=(Sender&&) noexcept = delete;
+
4937
+
4938 // Get the sender buffer
+
4939 FBEBuffer& buffer() noexcept { return *_buffer; }
+
4940 const FBEBuffer& buffer() const noexcept { return *_buffer; }
+
4941
+
4942 // Get the final protocol flag
+
4943 bool final() const noexcept { return _final; }
+
4944
+
4945 // Get the logging flag
+
4946 bool logging() const noexcept { return _logging; }
+
4947 // Enable/Disable logging
+
4948 void logging(bool enable) noexcept { _logging = enable; }
+
4949
+
4950 // Reset the sender buffer
+
4951 void reset() noexcept { _buffer->reset(); }
+
4952
+
4953 // Send serialized buffer.
+
4954 // Direct call of the method requires knowledge about internals of FBE models serialization.
+
4955 // Use it with care!
+
4956 size_t send_serialized(size_t serialized);
+
4957
+
4958protected:
+
4959 // Send message handler
+
4960 virtual size_t onSend(const void* data, size_t size) = 0;
+
4961 // Send log message handler
+
4962 virtual void onSendLog(const std::string& message) const {}
+
4963
+
4964protected:
+
4965 std::shared_ptr<FBEBuffer> _buffer;
+
4966 bool _logging;
+
4967 bool _final;
+
4968
+
4969 Sender() : Sender(nullptr) {}
+
4970 Sender(const std::shared_ptr<FBEBuffer>& buffer) : _logging(false), _final(false) { _buffer = buffer ? buffer : std::make_shared<FBEBuffer>(); }
+
4971
+
4972 // Enable/Disable final protocol
+
4973 void final(bool enable) noexcept { _final = enable; }
+
4974};
+
4975)CODE";
+
4976
+
4977 // Prepare code template
+
4978 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
4979
+
4980 Write(code);
+
4981}
+
4982
+
4983void GeneratorCpp::GenerateFBESender_Source()
+
4984{
+
4985 std::string code = R"CODE(
+
4986size_t Sender::send_serialized(size_t serialized)
+
4987{
+
4988 assert((serialized > 0) && "Invalid size of the serialized buffer!");
+
4989 if (serialized == 0)
+
4990 return 0;
+
4991
+
4992 // Shift the send buffer
+
4993 this->_buffer->shift(serialized);
+
4994
+
4995 // Send the value
+
4996 size_t sent = onSend(this->_buffer->data(), this->_buffer->size());
+
4997 this->_buffer->remove(0, sent);
+
4998 return sent;
+
4999}
+
5000)CODE";
+
5001
+
5002 // Prepare code template
+
5003 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
5004
+
5005 Write(code);
+
5006}
+
5007
+
5008void GeneratorCpp::GenerateFBEReceiver_Header()
+
5009{
+
5010 std::string code = R"CODE(
+
5011// Fast Binary Encoding base receiver
+
5012class Receiver
+
5013{
+
5014public:
+
5015 Receiver(const Receiver&) = delete;
+
5016 Receiver(Receiver&&) = delete;
+
5017 virtual ~Receiver() = default;
+
5018
+
5019 Receiver& operator=(const Receiver&) = delete;
+
5020 Receiver& operator=(Receiver&&) = delete;
+
5021
+
5022 // Get the receiver buffer
+
5023 FBEBuffer& buffer() noexcept { return *_buffer; }
+
5024 const FBEBuffer& buffer() const noexcept { return *_buffer; }
+
5025
+
5026 // Get the final protocol flag
+
5027 bool final() const noexcept { return _final; }
+
5028
+
5029 // Get the logging flag
+
5030 bool logging() const noexcept { return _logging; }
+
5031 // Enable/Disable logging
+
5032 void logging(bool enable) noexcept { _logging = enable; }
+
5033
+
5034 // Reset the receiver buffer
+
5035 void reset() noexcept { _buffer->reset(); }
+
5036
+
5037 // Receive data
+
5038 void receive(const void* data, size_t size);
+
5039
+
5040protected:
+
5041 // Receive message handler
+
5042 virtual bool onReceive(size_t type, const void* data, size_t size) = 0;
+
5043 // Receive log message handler
+
5044 virtual void onReceiveLog(const std::string& message) const {}
+
5045
+
5046protected:
+
5047 std::shared_ptr<FBEBuffer> _buffer;
+
5048 bool _logging;
+
5049 bool _final;
+
5050
+
5051 Receiver() : Receiver(nullptr) {}
+
5052 Receiver(const std::shared_ptr<FBEBuffer>& buffer) : _logging(false), _final(false) { _buffer = buffer ? buffer : std::make_shared<FBEBuffer>(); }
+
5053
+
5054 // Enable/Disable final protocol
+
5055 void final(bool enable) noexcept { _final = enable; }
+
5056};
+
5057)CODE";
+
5058
+
5059 // Prepare code template
+
5060 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
5061
+
5062 Write(code);
+
5063}
+
5064
+
5065void GeneratorCpp::GenerateFBEReceiver_Source()
+
5066{
+
5067 std::string code = R"CODE(
+
5068void Receiver::receive(const void* data, size_t size)
+
5069{
+
5070 if (size == 0)
+
5071 return;
+
5072
+
5073 assert((data != nullptr) && "Invalid buffer!");
+
5074 if (data == nullptr)
+
5075 return;
+
5076
+
5077 // Storage buffer
+
5078 uint8_t* buffer1 = _buffer->data();
+
5079 size_t offset0 = _buffer->offset();
+
5080 size_t offset1 = _buffer->size();
+
5081 size_t size1 = _buffer->size();
+
5082
+
5083 // Receive buffer
+
5084 const uint8_t* buffer2 = (const uint8_t*)data;
+
5085 size_t offset2 = 0;
+
5086 size_t size2 = size;
+
5087
+
5088 // While receive buffer is available to handle...
+
5089 while (offset2 < size2)
+
5090 {
+
5091 const uint8_t* message_buffer = nullptr;
+
5092 size_t message_size = 0;
+
5093
+
5094 // Try to receive message size
+
5095 bool message_size_copied = false;
+
5096 bool message_size_found = false;
+
5097 while (!message_size_found)
+
5098 {
+
5099 // Look into the storage buffer
+
5100 if (offset0 < size1)
+
5101 {
+
5102 size_t count = std::min(size1 - offset0, (size_t)4);
+
5103 if (count == 4)
+
5104 {
+
5105 message_size_copied = true;
+
5106 message_size_found = true;
+
5107 message_size = (size_t)(*((const uint32_t*)(buffer1 + offset0)));
+
5108 offset0 += 4;
+
5109 break;
+
5110 }
+
5111 else
+
5112 {
+
5113 // Fill remaining data from the receive buffer
+
5114 if (offset2 < size2)
+
5115 {
+
5116 count = std::min(size2 - offset2, 4 - count);
+
5117
+
5118 // Allocate and refresh the storage buffer
+
5119 _buffer->allocate(count);
+
5120 buffer1 = _buffer->data();
+
5121 size1 += count;
+
5122
+
5123 memcpy(buffer1 + offset1, buffer2 + offset2, count);
+
5124 offset1 += count;
+
5125 offset2 += count;
+
5126 continue;
+
5127 }
+
5128 else
+
5129 break;
+
5130 }
+
5131 }
+
5132
+
5133 // Look into the receive buffer
+
5134 if (offset2 < size2)
+
5135 {
+
5136 size_t count = std::min(size2 - offset2, (size_t)4);
+
5137 if (count == 4)
+
5138 {
+
5139 message_size_found = true;
+
5140 message_size = (size_t)(*((const uint32_t*)(buffer2 + offset2)));
+
5141 offset2 += 4;
+
5142 break;
+
5143 }
+
5144 else
+
5145 {
+
5146 // Allocate and refresh the storage buffer
+
5147 _buffer->allocate(count);
+
5148 buffer1 = _buffer->data();
+
5149 size1 += count;
+
5150
+
5151 memcpy(buffer1 + offset1, buffer2 + offset2, count);
+
5152 offset1 += count;
+
5153 offset2 += count;
+
5154 continue;
+
5155 }
+
5156 }
+
5157 else
+
5158 break;
+
5159 }
+
5160
+
5161 if (!message_size_found)
+
5162 return;
+
5163
+
5164 // Check the message full size
+
5165 size_t min_size = _final ? (4 + 4) : (4 + 4 + 4 + 4);
+
5166 assert((message_size >= min_size) && "Invalid receive data!");
+
5167 if (message_size < min_size)
+
5168 return;
+
5169
+
5170 // Try to receive message body
+
5171 bool message_found = false;
+
5172 while (!message_found)
+
5173 {
+
5174 // Look into the storage buffer
+
5175 if (offset0 < size1)
+
5176 {
+
5177 size_t count = std::min(size1 - offset0, message_size - 4);
+
5178 if (count == (message_size - 4))
+
5179 {
+
5180 message_found = true;
+
5181 message_buffer = buffer1 + offset0 - 4;
+
5182 offset0 += message_size - 4;
+
5183 break;
+
5184 }
+
5185 else
+
5186 {
+
5187 // Fill remaining data from the receive buffer
+
5188 if (offset2 < size2)
+
5189 {
+
5190 // Copy message size into the storage buffer
+
5191 if (!message_size_copied)
+
5192 {
+
5193 // Allocate and refresh the storage buffer
+
5194 _buffer->allocate(4);
+
5195 buffer1 = _buffer->data();
+
5196 size1 += 4;
+
5197
+
5198 *((uint32_t*)(buffer1 + offset0)) = (uint32_t)message_size;
+
5199 offset0 += 4;
+
5200 offset1 += 4;
+
5201
+
5202 message_size_copied = true;
+
5203 }
+
5204
+
5205 count = std::min(size2 - offset2, message_size - 4 - count);
+
5206
+
5207 // Allocate and refresh the storage buffer
+
5208 _buffer->allocate(count);
+
5209 buffer1 = _buffer->data();
+
5210 size1 += count;
+
5211
+
5212 memcpy(buffer1 + offset1, buffer2 + offset2, count);
+
5213 offset1 += count;
+
5214 offset2 += count;
+
5215 continue;
+
5216 }
+
5217 else
+
5218 break;
+
5219 }
+
5220 }
+
5221
+
5222 // Look into the receive buffer
+
5223 if (offset2 < size2)
+
5224 {
+
5225 size_t count = std::min(size2 - offset2, message_size - 4);
+
5226 if (!message_size_copied && (count == (message_size - 4)))
+
5227 {
+
5228 message_found = true;
+
5229 message_buffer = buffer2 + offset2 - 4;
+
5230 offset2 += message_size - 4;
+
5231 break;
+
5232 }
+
5233 else
+
5234 {
+
5235 // Copy message size into the storage buffer
+
5236 if (!message_size_copied)
+
5237 {
+
5238 // Allocate and refresh the storage buffer
+
5239 _buffer->allocate(4);
+
5240 buffer1 = _buffer->data();
+
5241 size1 += 4;
+
5242
+
5243 *((uint32_t*)(buffer1 + offset0)) = (uint32_t)message_size;
+
5244 offset0 += 4;
+
5245 offset1 += 4;
+
5246
+
5247 message_size_copied = true;
+
5248 }
+
5249
+
5250 // Allocate and refresh the storage buffer
+
5251 _buffer->allocate(count);
+
5252 buffer1 = _buffer->data();
+
5253 size1 += count;
+
5254
+
5255 memcpy(buffer1 + offset1, buffer2 + offset2, count);
+
5256 offset1 += count;
+
5257 offset2 += count;
+
5258 continue;
+
5259 }
+
5260 }
+
5261 else
+
5262 break;
+
5263 }
+
5264
+
5265 if (!message_found)
+
5266 {
+
5267 // Copy message size into the storage buffer
+
5268 if (!message_size_copied)
+
5269 {
+
5270 // Allocate and refresh the storage buffer
+
5271 _buffer->allocate(4);
+
5272 buffer1 = _buffer->data();
+
5273 size1 += 4;
+
5274
+
5275 *((uint32_t*)(buffer1 + offset0)) = (uint32_t)message_size;
+
5276 offset0 += 4;
+
5277 offset1 += 4;
+
5278
+
5279 message_size_copied = true;
+
5280 }
+
5281 return;
+
5282 }
+
5283
+
5284 [[maybe_unused]] uint32_t fbe_struct_size;
+
5285 uint32_t fbe_struct_type;
+
5286
+
5287 // Read the message parameters
+
5288 if (_final)
+
5289 {
+
5290 fbe_struct_size = *((const uint32_t*)(message_buffer));
+
5291 fbe_struct_type = *((const uint32_t*)(message_buffer + 4));
+
5292 }
+
5293 else
+
5294 {
+
5295 uint32_t fbe_struct_offset = *((const uint32_t*)(message_buffer + 4));
+
5296 fbe_struct_size = *((const uint32_t*)(message_buffer + fbe_struct_offset));
+
5297 fbe_struct_type = *((const uint32_t*)(message_buffer + fbe_struct_offset + 4));
+
5298 }
+
5299
+
5300 // Handle the message
+
5301 onReceive(fbe_struct_type, message_buffer, message_size);
+
5302
+
5303 // Reset the storage buffer
+
5304 _buffer->reset();
+
5305
+
5306 // Refresh the storage buffer
+
5307 buffer1 = _buffer->data();
+
5308 offset0 = _buffer->offset();
+
5309 offset1 = _buffer->size();
+
5310 size1 = _buffer->size();
+
5311 }
+
5312}
+
5313)CODE";
+
5314
+
5315 // Prepare code template
+
5316 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
5317
+
5318 Write(code);
+
5319}
+
5320
+
5321void GeneratorCpp::GenerateFBEJson()
+
5322{
+
5323 // Generate namespace begin
+
5324 WriteLine();
+
5325 WriteLineIndent("namespace JSON {");
+
5326
+
5327 std::string code = R"CODE(
+
5328template <class TWriter, typename T>
+
5329struct KeyWriter
+
5330{
+
5331 static bool to_json_key(TWriter& writer, const T& key)
+
5332 {
+
5333 return writer.Key(std::to_string(key));
+
5334 }
+
5335};
+
5336
+
5337template <class TWriter, typename T>
+
5338bool to_json_key(TWriter& writer, const T& key)
+
5339{
+
5340 return KeyWriter<TWriter, T>::to_json_key(writer, key);
+
5341}
+
5342
+
5343template <class TWriter>
+
5344struct KeyWriter<TWriter, FBE::decimal_t>
+
5345{
+
5346 static bool to_json_key(TWriter& writer, const FBE::decimal_t& key)
+
5347 {
+
5348 return writer.Key(key.string());
+
5349 }
+
5350};
+
5351
+
5352template <class TWriter>
+
5353struct KeyWriter<TWriter, FBE::uuid_t>
+
5354{
+
5355 static bool to_json_key(TWriter& writer, const FBE::uuid_t& key)
+
5356 {
+
5357 return writer.Key(key.string());
+
5358 }
+
5359};
+
5360
+
5361template <class TWriter>
+
5362struct KeyWriter<TWriter, std::string>
+
5363{
+
5364 static bool to_json_key(TWriter& writer, const std::string& key)
+
5365 {
+
5366 return writer.Key(key);
+
5367 }
+
5368};
+
5369
+
5370template <class TWriter, size_t N>
+
5371struct KeyWriter<TWriter, char[N]>
+
5372{
+
5373 static bool to_json_key(TWriter& writer, const char (&key)[N])
+
5374 {
+
5375 return writer.Key(key, N - 1);
+
5376 }
+
5377};
+
5378
+
5379template <class TWriter, typename T>
+
5380struct ValueWriter
+
5381{
+
5382 static bool to_json(TWriter& writer, const T& value, bool scope = true)
+
5383 {
+
5384 throw std::logic_error("Not implemented!");
+
5385 }
+
5386};
+
5387
+
5388template <class TWriter, typename T>
+
5389bool to_json(TWriter& writer, const T& value, bool scope = true)
+
5390{
+
5391 return ValueWriter<TWriter, T>::to_json(writer, value, scope);
+
5392}
+
5393
+
5394template <class TWriter>
+
5395struct ValueWriter<TWriter, bool>
+
5396{
+
5397 static bool to_json(TWriter& writer, const bool& value, bool scope = true)
+
5398 {
+
5399 return writer.Bool(value);
+
5400 }
+
5401};
+
5402
+
5403template <class TWriter>
+
5404struct ValueWriter<TWriter, char>
+
5405{
+
5406 static bool to_json(TWriter& writer, const char& value, bool scope = true)
+
5407 {
+
5408 return writer.Uint(value);
+
5409 }
+
5410};
+
5411
+
5412template <class TWriter>
+
5413struct ValueWriter<TWriter, wchar_t>
+
5414{
+
5415 static bool to_json(TWriter& writer, const wchar_t& value, bool scope = true)
+
5416 {
+
5417 return writer.Uint(value);
+
5418 }
+
5419};
+
5420
+
5421template <class TWriter>
+
5422struct ValueWriter<TWriter, int8_t>
+
5423{
+
5424 static bool to_json(TWriter& writer, const int8_t& value, bool scope = true)
+
5425 {
+
5426 return writer.Int(value);
+
5427 }
+
5428};
+
5429
+
5430template <class TWriter>
+
5431struct ValueWriter<TWriter, uint8_t>
+
5432{
+
5433 static bool to_json(TWriter& writer, const uint8_t& value, bool scope = true)
+
5434 {
+
5435 return writer.Uint(value);
+
5436 }
+
5437};
+
5438
+
5439template <class TWriter>
+
5440struct ValueWriter<TWriter, int16_t>
+
5441{
+
5442 static bool to_json(TWriter& writer, const int16_t& value, bool scope = true)
+
5443 {
+
5444 return writer.Int(value);
+
5445 }
+
5446};
+
5447
+
5448template <class TWriter>
+
5449struct ValueWriter<TWriter, uint16_t>
+
5450{
+
5451 static bool to_json(TWriter& writer, const uint16_t& value, bool scope = true)
+
5452 {
+
5453 return writer.Uint(value);
+
5454 }
+
5455};
+
5456
+
5457template <class TWriter>
+
5458struct ValueWriter<TWriter, int32_t>
+
5459{
+
5460 static bool to_json(TWriter& writer, const int32_t& value, bool scope = true)
+
5461 {
+
5462 return writer.Int(value);
+
5463 }
+
5464};
+
5465
+
5466template <class TWriter>
+
5467struct ValueWriter<TWriter, uint32_t>
+
5468{
+
5469 static bool to_json(TWriter& writer, const uint32_t& value, bool scope = true)
+
5470 {
+
5471 return writer.Uint(value);
+
5472 }
+
5473};
+
5474
+
5475template <class TWriter>
+
5476struct ValueWriter<TWriter, int64_t>
+
5477{
+
5478 static bool to_json(TWriter& writer, const int64_t& value, bool scope = true)
+
5479 {
+
5480 return writer.Int64(value);
+
5481 }
+
5482};
+
5483
+
5484template <class TWriter>
+
5485struct ValueWriter<TWriter, uint64_t>
+
5486{
+
5487 static bool to_json(TWriter& writer, const uint64_t& value, bool scope = true)
+
5488 {
+
5489 return writer.Uint64(value);
+
5490 }
+
5491};
+
5492
+
5493template <class TWriter>
+
5494struct ValueWriter<TWriter, float>
+
5495{
+
5496 static bool to_json(TWriter& writer, const float& value, bool scope = true)
+
5497 {
+
5498 return writer.Double(value);
+
5499 }
+
5500};
+
5501
+
5502template <class TWriter>
+
5503struct ValueWriter<TWriter, double>
+
5504{
+
5505 static bool to_json(TWriter& writer, const double& value, bool scope = true)
+
5506 {
+
5507 return writer.Double(value);
+
5508 }
+
5509};
+
5510
+
5511template <class TWriter>
+
5512struct ValueWriter<TWriter, FBE::decimal_t>
+
5513{
+
5514 static bool to_json(TWriter& writer, const FBE::decimal_t& value, bool scope = true)
+
5515 {
+
5516 return writer.String(value.string());
+
5517 }
+
5518};
+
5519
+
5520template <class TWriter>
+
5521struct ValueWriter<TWriter, FBE::uuid_t>
+
5522{
+
5523 static bool to_json(TWriter& writer, const FBE::uuid_t& value, bool scope = true)
+
5524 {
+
5525 return writer.String(value.string());
+
5526 }
+
5527};
+
5528
+
5529template <class TWriter>
+
5530struct ValueWriter<TWriter, std::string>
+
5531{
+
5532 static bool to_json(TWriter& writer, const std::string& value, bool scope = true)
+
5533 {
+
5534 return writer.String(value);
+
5535 }
+
5536};
+
5537
+
5538template <class TWriter, std::size_t N>
+
5539struct ValueWriter<TWriter, char[N]>
+
5540{
+
5541 static bool to_json(TWriter& writer, const char (&value)[N], bool scope = true)
+
5542 {
+
5543 return writer.String(value, N);
+
5544 }
+
5545};
+
5546
+
5547template <class TWriter, typename T>
+
5548struct ValueWriter<TWriter, std::optional<T>>
+
5549{
+
5550 static bool to_json(TWriter& writer, const std::optional<T>& value, bool scope = true)
+
5551 {
+
5552 if (value)
+
5553 return ValueWriter<TWriter, T>::to_json(writer, value.value(), true);
+
5554 else
+
5555 return writer.Null();
+
5556 }
+
5557};
+
5558
+
5559template <class TWriter>
+
5560struct ValueWriter<TWriter, buffer_t>
+
5561{
+
5562 static bool to_json(TWriter& writer, const buffer_t& values, bool scope = true)
+
5563 {
+
5564 return writer.String(values.base64encode());
+
5565 }
+
5566};
+
5567
+
5568template <class TWriter, typename T, size_t N>
+
5569struct ValueWriter<TWriter, std::array<T, N>>
+
5570{
+
5571 static bool to_json(TWriter& writer, const std::array<T, N>& values, bool scope = true)
+
5572 {
+
5573 writer.StartArray();
+
5574 for (const auto& value : values)
+
5575 if (!ValueWriter<TWriter, T>::to_json(writer, value, true))
+
5576 return false;
+
5577 writer.EndArray();
+
5578 return true;
+
5579 }
+
5580};
+
5581
+
5582template <class TWriter, typename T>
+
5583struct ValueWriter<TWriter, std::vector<T>>
+
5584{
+
5585 static bool to_json(TWriter& writer, const std::vector<T>& values, bool scope = true)
+
5586 {
+
5587 writer.StartArray();
+
5588 for (const auto& value : values)
+
5589 if (!FBE::JSON::to_json(writer, value, true))
+
5590 return false;
+
5591 writer.EndArray();
+
5592 return true;
+
5593 }
+
5594};
+
5595
+
5596template <class TWriter, typename T>
+
5597struct ValueWriter<TWriter, std::list<T>>
+
5598{
+
5599 static bool to_json(TWriter& writer, const std::list<T>& values, bool scope = true)
+
5600 {
+
5601 writer.StartArray();
+
5602 for (const auto& value : values)
+
5603 if (!FBE::JSON::to_json(writer, value, true))
+
5604 return false;
+
5605 writer.EndArray();
+
5606 return true;
+
5607 }
+
5608};
+
5609
+
5610template <class TWriter, typename T>
+
5611struct ValueWriter<TWriter, std::set<T>>
+
5612{
+
5613 static bool to_json(TWriter& writer, const std::set<T>& values, bool scope = true)
+
5614 {
+
5615 writer.StartArray();
+
5616 for (const auto& value : values)
+
5617 if (!FBE::JSON::to_json(writer, value, true))
+
5618 return false;
+
5619 writer.EndArray();
+
5620 return true;
+
5621 }
+
5622};
+
5623
+
5624template <class TWriter, typename TKey, typename TValue>
+
5625struct ValueWriter<TWriter, std::map<TKey, TValue>>
+
5626{
+
5627 static bool to_json(TWriter& writer, const std::map<TKey, TValue>& values, bool scope = true)
+
5628 {
+
5629 writer.StartObject();
+
5630 for (const auto& value : values)
+
5631 {
+
5632 if (!FBE::JSON::to_json_key(writer, value.first))
+
5633 return false;
+
5634 if (!FBE::JSON::to_json(writer, value.second, true))
+
5635 return false;
+
5636 }
+
5637 writer.EndObject();
+
5638 return true;
+
5639 }
+
5640};
+
5641
+
5642template <class TWriter, typename TKey, typename TValue>
+
5643struct ValueWriter<TWriter, std::unordered_map<TKey, TValue>>
+
5644{
+
5645 static bool to_json(TWriter& writer, const std::unordered_map<TKey, TValue>& values, bool scope = true)
+
5646 {
+
5647 writer.StartObject();
+
5648 for (const auto& value : values)
+
5649 {
+
5650 if (!FBE::JSON::to_json_key(writer, value.first))
+
5651 return false;
+
5652 if (!FBE::JSON::to_json(writer, value.second, true))
+
5653 return false;
+
5654 }
+
5655 writer.EndObject();
+
5656 return true;
+
5657 }
+
5658};
+
5659)CODE";
+
5660
+
5661 // Prepare code template
+
5662 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
5663
+
5664 Write(code);
+
5665
+
5666 code = R"CODE(
+
5667template <class TJson, typename T>
+
5668struct ValueReader
+
5669{
+
5670 static bool from_json(const TJson& json, T& value)
+
5671 {
+
5672 throw std::logic_error("Not implemented!");
+
5673 }
+
5674};
+
5675
+
5676template <class TJson, typename T>
+
5677bool from_json(const TJson& json, T& value)
+
5678{
+
5679 return ValueReader<TJson, T>::from_json(json, value);
+
5680}
+
5681
+
5682template <class TJson, typename T>
+
5683struct KeyReader
+
5684{
+
5685 static bool from_json_key(const TJson& json, T& key)
+
5686 {
+
5687 std::string str;
+
5688 if (!FBE::JSON::from_json(json, str))
+
5689 return false;
+
5690
+
5691 std::istringstream(str) >> key;
+
5692 return true;
+
5693 }
+
5694};
+
5695
+
5696template <class TJson, typename T>
+
5697bool from_json_key(const TJson& json, T& key)
+
5698{
+
5699 return KeyReader<TJson, T>::from_json_key(json, key);
+
5700}
+
5701
+
5702template <class TJson>
+
5703struct KeyReader<TJson, std::string>
+
5704{
+
5705 static bool from_json_key(const TJson& json, std::string& key)
+
5706 {
+
5707 return FBE::JSON::from_json(json, key);
+
5708 }
+
5709};
+
5710
+
5711template <class TJson>
+
5712struct KeyReader<TJson, FBE::decimal_t>
+
5713{
+
5714 static bool from_json_key(const TJson& json, FBE::decimal_t& key)
+
5715 {
+
5716 return FBE::JSON::from_json(json, key);
+
5717 }
+
5718};
+
5719
+
5720template <class TJson>
+
5721struct KeyReader<TJson, FBE::uuid_t>
+
5722{
+
5723 static bool from_json_key(const TJson& json, FBE::uuid_t& key)
+
5724 {
+
5725 return FBE::JSON::from_json(json, key);
+
5726 }
+
5727};
+
5728
+
5729template <class TJson, size_t N>
+
5730struct KeyReader<TJson, char[N]>
+
5731{
+
5732 static bool from_json_key(const TJson& json, char (&key)[N])
+
5733 {
+
5734 return FBE::JSON::from_json(json, key);
+
5735 }
+
5736};
+
5737
+
5738template <class TJson>
+
5739struct ValueReader<TJson, bool>
+
5740{
+
5741 static bool from_json(const TJson& json, bool& value)
+
5742 {
+
5743 value = false;
+
5744
+
5745 // Schema validation
+
5746 if (json.IsNull() || !json.IsBool())
+
5747 return false;
+
5748
+
5749 // Save the value
+
5750 value = json.GetBool();
+
5751 return true;
+
5752 }
+
5753};
+
5754
+
5755template <class TJson>
+
5756struct ValueReader<TJson, char>
+
5757{
+
5758 static bool from_json(const TJson& json, char& value)
+
5759 {
+
5760 value = '\0';
+
5761
+
5762 // Schema validation
+
5763 if (json.IsNull() || !json.IsUint())
+
5764 return false;
+
5765
+
5766 // Save the value
+
5767 value = (char)json.GetUint();
+
5768 return true;
+
5769 }
+
5770};
+
5771
+
5772template <class TJson>
+
5773struct ValueReader<TJson, wchar_t>
+
5774{
+
5775 static bool from_json(const TJson& json, wchar_t& value)
+
5776 {
+
5777 value = L'\0';
+
5778
+
5779 // Schema validation
+
5780 if (json.IsNull() || !json.IsUint())
+
5781 return false;
+
5782
+
5783 // Save the value
+
5784 value = (wchar_t)json.GetUint();
+
5785 return true;
+
5786 }
+
5787};
+
5788
+
5789template <class TJson>
+
5790struct ValueReader<TJson, int8_t>
+
5791{
+
5792 static bool from_json(const TJson& json, int8_t& value)
+
5793 {
+
5794 value = 0;
+
5795
+
5796 // Schema validation
+
5797 if (json.IsNull() || !json.IsInt())
+
5798 return false;
+
5799
+
5800 // Save the value
+
5801 value = (int8_t)json.GetInt();
+
5802 return true;
+
5803 }
+
5804};
+
5805
+
5806template <class TJson>
+
5807struct ValueReader<TJson, uint8_t>
+
5808{
+
5809 static bool from_json(const TJson& json, uint8_t& value)
+
5810 {
+
5811 value = 0;
+
5812
+
5813 // Schema validation
+
5814 if (json.IsNull() || !json.IsUint())
+
5815 return false;
+
5816
+
5817 // Save the value
+
5818 value = (uint8_t)json.GetUint();
+
5819 return true;
+
5820 }
+
5821};
+
5822
+
5823template <class TJson>
+
5824struct ValueReader<TJson, int16_t>
+
5825{
+
5826 static bool from_json(const TJson& json, int16_t& value)
+
5827 {
+
5828 value = 0;
+
5829
+
5830 // Schema validation
+
5831 if (json.IsNull() || !json.IsInt())
+
5832 return false;
+
5833
+
5834 // Save the value
+
5835 value = (int16_t)json.GetInt();
+
5836 return true;
+
5837 }
+
5838};
+
5839
+
5840template <class TJson>
+
5841struct ValueReader<TJson, uint16_t>
+
5842{
+
5843 static bool from_json(const TJson& json, uint16_t& value)
+
5844 {
+
5845 value = 0;
+
5846
+
5847 // Schema validation
+
5848 if (json.IsNull() || !json.IsUint())
+
5849 return false;
+
5850
+
5851 // Save the value
+
5852 value = (uint16_t)json.GetUint();
+
5853 return true;
+
5854 }
+
5855};
+
5856
+
5857template <class TJson>
+
5858struct ValueReader<TJson, int32_t>
+
5859{
+
5860 static bool from_json(const TJson& json, int32_t& value)
+
5861 {
+
5862 value = 0;
+
5863
+
5864 // Schema validation
+
5865 if (json.IsNull() || !json.IsInt())
+
5866 return false;
+
5867
+
5868 // Save the value
+
5869 value = (int32_t)json.GetInt();
+
5870 return true;
+
5871 }
+
5872};
+
5873
+
5874template <class TJson>
+
5875struct ValueReader<TJson, uint32_t>
+
5876{
+
5877 static bool from_json(const TJson& json, uint32_t& value)
+
5878 {
+
5879 value = 0;
+
5880
+
5881 // Schema validation
+
5882 if (json.IsNull() || !json.IsUint())
+
5883 return false;
+
5884
+
5885 // Save the value
+
5886 value = (uint32_t)json.GetUint();
+
5887 return true;
+
5888 }
+
5889};
+
5890
+
5891template <class TJson>
+
5892struct ValueReader<TJson, int64_t>
+
5893{
+
5894 static bool from_json(const TJson& json, int64_t& value)
+
5895 {
+
5896 value = 0;
+
5897
+
5898 // Schema validation
+
5899 if (json.IsNull() || !json.IsInt64())
+
5900 return false;
+
5901
+
5902 // Save the value
+
5903 value = (int64_t)json.GetInt64();
+
5904 return true;
+
5905 }
+
5906};
+
5907
+
5908template <class TJson>
+
5909struct ValueReader<TJson, uint64_t>
+
5910{
+
5911 static bool from_json(const TJson& json, uint64_t& value)
+
5912 {
+
5913 value = 0;
+
5914
+
5915 // Schema validation
+
5916 if (json.IsNull() || !json.IsUint64())
+
5917 return false;
+
5918
+
5919 // Save the value
+
5920 value = (uint64_t)json.GetUint64();
+
5921 return true;
+
5922 }
+
5923};
+
5924
+
5925template <class TJson>
+
5926struct ValueReader<TJson, float>
+
5927{
+
5928 static bool from_json(const TJson& json, float& value)
+
5929 {
+
5930 value = 0.0f;
+
5931
+
5932 // Schema validation
+
5933 if (json.IsNull() || !(json.IsInt() || json.IsFloat()))
+
5934 return false;
+
5935
+
5936 // Save the value
+
5937 value = json.GetFloat();
+
5938 return true;
+
5939 }
+
5940};
+
5941
+
5942template <class TJson>
+
5943struct ValueReader<TJson, double>
+
5944{
+
5945 static bool from_json(const TJson& json, double& value)
+
5946 {
+
5947 value = 0.0;
+
5948
+
5949 // Schema validation
+
5950 if (json.IsNull() || !(json.IsInt() || json.IsDouble()))
+
5951 return false;
+
5952
+
5953 // Save the value
+
5954 value = json.GetDouble();
+
5955 return true;
+
5956 }
+
5957};
+
5958
+
5959template <class TJson>
+
5960struct ValueReader<TJson, FBE::decimal_t>
+
5961{
+
5962 static bool from_json(const TJson& json, FBE::decimal_t& value)
+
5963 {
+
5964 value = 0.0;
+
5965
+
5966 // Schema validation
+
5967 if (json.IsNull() || !json.IsString())
+
5968 return false;
+
5969
+
5970 // Save the value
+
5971 try
+
5972 {
+
5973 std::string str(json.GetString(), (size_t)json.GetStringLength());
+
5974 value = std::stod(str);
+
5975 return true;
+
5976 }
+
5977 catch (...)
+
5978 {
+
5979 return false;
+
5980 }
+
5981 }
+
5982};
+
5983
+
5984template <class TJson>
+
5985struct ValueReader<TJson, FBE::uuid_t>
+
5986{
+
5987 static bool from_json(const TJson& json, FBE::uuid_t& value)
+
5988 {
+
5989 value = uuid_t::nil();
+
5990
+
5991 // Schema validation
+
5992 if (json.IsNull() || !json.IsString())
+
5993 return false;
+
5994
+
5995 // Save the value
+
5996 try
+
5997 {
+
5998 std::string str(json.GetString(), (size_t)json.GetStringLength());
+
5999 value = str;
+
6000 return true;
+
6001 }
+
6002 catch (...)
+
6003 {
+
6004 return false;
+
6005 }
+
6006 }
+
6007};
+
6008
+
6009template <class TJson>
+
6010struct ValueReader<TJson, std::string>
+
6011{
+
6012 static bool from_json(const TJson& json, std::string& value)
+
6013 {
+
6014 value = "";
+
6015
+
6016 // Schema validation
+
6017 if (json.IsNull() || !json.IsString())
+
6018 return false;
+
6019
+
6020 // Save the value
+
6021 value.assign(json.GetString(), (size_t)json.GetStringLength());
+
6022 return true;
+
6023 }
+
6024};
+
6025
+
6026template <class TJson, size_t N>
+
6027struct ValueReader<TJson, char[N]>
+
6028{
+
6029 static bool from_json(const TJson& json, char (&value)[N])
+
6030 {
+
6031 // Schema validation
+
6032 if (json.IsNull() || !json.IsString())
+
6033 return false;
+
6034
+
6035 // Save the value
+
6036 size_t length = std::min((size_t)json.GetStringLength(), N);
+
6037 std::memcpy(value, json.GetString(), length);
+
6038 // Write the end of string character if possible
+
6039 if (length < N)
+
6040 value[length] = '\0';
+
6041 return true;
+
6042 }
+
6043};
+
6044
+
6045template <class TJson, typename T>
+
6046struct ValueReader<TJson, std::optional<T>>
+
6047{
+
6048 static bool from_json(const TJson& json, std::optional<T>& value)
+
6049 {
+
6050 value = std::nullopt;
+
6051
+
6052 // Empty optional value
+
6053 if (json.IsNull())
+
6054 return true;
+
6055
+
6056 // Try to get the value
+
6057 T temp = T();
+
6058 if (!FBE::JSON::from_json(json, temp))
+
6059 return false;
+
6060
+
6061 // Save the value
+
6062 value.emplace(temp);
+
6063 return true;
+
6064 }
+
6065};
+
6066
+
6067template <class TJson>
+
6068struct ValueReader<TJson, buffer_t>
+
6069{
+
6070 static bool from_json(const TJson& json, buffer_t& value)
+
6071 {
+
6072 // Schema validation
+
6073 if (json.IsNull() || !json.IsString())
+
6074 return false;
+
6075
+
6076 std::string str(json.GetString(), (size_t)json.GetStringLength());
+
6077 value = buffer_t::base64decode(str);
+
6078 return true;
+
6079 }
+
6080};
+
6081
+
6082template <class TJson, typename T, size_t N>
+
6083struct ValueReader<TJson, std::array<T, N>>
+
6084{
+
6085 static bool from_json(const TJson& json, std::array<T, N>& values)
+
6086 {
+
6087 // Schema validation
+
6088 if (json.IsNull() || !json.IsArray())
+
6089 return false;
+
6090
+
6091 // Collect array items
+
6092 size_t length = json.GetArray().Size();
+
6093 for (size_t i = 0; (i < length) && (i < N); ++i)
+
6094 if (!FBE::JSON::from_json(json.GetArray()[(rapidjson::SizeType)i], values[i]))
+
6095 return false;
+
6096 return true;
+
6097 }
+
6098};
+
6099
+
6100template <class TJson, typename T>
+
6101struct ValueReader<TJson, std::vector<T>>
+
6102{
+
6103 static bool from_json(const TJson& json, std::vector<T>& values)
+
6104 {
+
6105 values.clear();
+
6106
+
6107 // Schema validation
+
6108 if (json.IsNull() || !json.IsArray())
+
6109 return false;
+
6110
+
6111 // Collect vector items
+
6112 values.reserve(json.GetArray().Size());
+
6113 for (const auto& item : json.GetArray())
+
6114 {
+
6115 T temp = T();
+
6116 if (!FBE::JSON::from_json(item, temp))
+
6117 return false;
+
6118 values.emplace_back(temp);
+
6119 }
+
6120 return true;
+
6121 }
+
6122};
+
6123
+
6124template <class TJson, typename T>
+
6125struct ValueReader<TJson, std::list<T>>
+
6126{
+
6127 static bool from_json(const TJson& json, std::list<T>& values)
+
6128 {
+
6129 values.clear();
+
6130
+
6131 // Schema validation
+
6132 if (json.IsNull() || !json.IsArray())
+
6133 return false;
+
6134
+
6135 // Collect list items
+
6136 for (const auto& item : json.GetArray())
+
6137 {
+
6138 T temp = T();
+
6139 if (!FBE::JSON::from_json(item, temp))
+
6140 return false;
+
6141 values.emplace_back(temp);
+
6142 }
+
6143 return true;
+
6144 }
+
6145};
+
6146
+
6147template <class TJson, typename T>
+
6148struct ValueReader<TJson, std::set<T>>
+
6149{
+
6150 static bool from_json(const TJson& json, std::set<T>& values)
+
6151 {
+
6152 values.clear();
+
6153
+
6154 // Schema validation
+
6155 if (json.IsNull() || !json.IsArray())
+
6156 return false;
+
6157
+
6158 // Collect set items
+
6159 for (const auto& item : json.GetArray())
+
6160 {
+
6161 T temp = T();
+
6162 if (!FBE::JSON::from_json(item, temp))
+
6163 return false;
+
6164 values.emplace(temp);
+
6165 }
+
6166 return true;
+
6167 }
+
6168};
+
6169
+
6170template <class TJson, typename TKey, typename TValue>
+
6171struct ValueReader<TJson, std::map<TKey, TValue>>
+
6172{
+
6173 static bool from_json(const TJson& json, std::map<TKey, TValue>& values)
+
6174 {
+
6175 values.clear();
+
6176
+
6177 // Schema validation
+
6178 if (json.IsNull() || !json.IsObject())
+
6179 return false;
+
6180
+
6181 // Collect map items
+
6182 for (auto it = json.MemberBegin(); it != json.MemberEnd(); ++it)
+
6183 {
+
6184 TKey key = TKey();
+
6185 TValue value = TValue();
+
6186 if (!FBE::JSON::from_json_key(it->name, key))
+
6187 return false;
+
6188 if (!FBE::JSON::from_json(it->value, value))
+
6189 return false;
+
6190 values.emplace(key, value);
+
6191 }
+
6192 return true;
+
6193 }
+
6194};
+
6195
+
6196template <class TJson, typename TKey, typename TValue>
+
6197struct ValueReader<TJson, std::unordered_map<TKey, TValue>>
+
6198{
+
6199 static bool from_json(const TJson& json, std::unordered_map<TKey, TValue>& values)
+
6200 {
+
6201 values.clear();
+
6202
+
6203 // Schema validation
+
6204 if (json.IsNull() || !json.IsObject())
+
6205 return false;
+
6206
+
6207 // Collect hash items
+
6208 for (auto it = json.MemberBegin(); it != json.MemberEnd(); ++it)
+
6209 {
+
6210 TKey key = TKey();
+
6211 TValue value = TValue();
+
6212 if (!FBE::JSON::from_json_key(it->name, key))
+
6213 return false;
+
6214 if (!FBE::JSON::from_json(it->value, value))
+
6215 return false;
+
6216 values.emplace(key, value);
+
6217 }
+
6218 return true;
+
6219 }
+
6220};
+
6221)CODE";
+
6222
+
6223 // Prepare code template
+
6224 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
6225
+
6226 Write(code);
+
6227
+
6228 code = R"CODE(
+
6229template <class TJson, typename T>
+
6230struct NodeReader
+
6231{
+
6232 static bool from_json(const TJson& json, T& value, const char* key)
+
6233 {
+
6234 if (key == nullptr)
+
6235 return false;
+
6236
+
6237 // Try to find a member with the given key
+
6238 rapidjson::Value::ConstMemberIterator member = json.FindMember(key);
+
6239 if (member == json.MemberEnd())
+
6240 return false;
+
6241
+
6242 return FBE::JSON::from_json(member->value, value);
+
6243 }
+
6244};
+
6245
+
6246template <class TJson, typename T>
+
6247bool from_json(const TJson& json, T& value, const char* key)
+
6248{
+
6249 return NodeReader<TJson, T>::from_json(json, value, key);
+
6250}
+
6251)CODE";
+
6252
+
6253 // Prepare code template
+
6254 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
6255
+
6256 Write(code);
+
6257
+
6258 code = R"CODE(
+
6259template <class TJson, typename T>
+
6260struct ChildNodeReader
+
6261{
+
6262 static bool from_json_child(const TJson& json, T& value, const char* key)
+
6263 {
+
6264 if (key == nullptr)
+
6265 return false;
+
6266
+
6267 // Try to find a member with the given key
+
6268 rapidjson::Value::ConstMemberIterator member = json.FindMember(key);
+
6269 if (member == json.MemberEnd())
+
6270 return false;
+
6271
+
6272 // Schema validation
+
6273 if (member->value.IsNull() || !member->value.IsObject())
+
6274 return false;
+
6275
+
6276 // Deserialize the child object
+
6277 return FBE::JSON::from_json(member->value.GetObj(), value);
+
6278 }
+
6279};
+
6280
+
6281template <class TJson, typename T>
+
6282bool from_json_child(const TJson& json, T& value, const char* key)
+
6283{
+
6284 return ChildNodeReader<TJson, T>::from_json_child(json, value, key);
+
6285}
+
6286)CODE";
+
6287
+
6288 // Prepare code template
+
6289 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
6290
+
6291 Write(code);
+
6292
+
6293 // Generate namespace end
+
6294 WriteLine();
+
6295 WriteLineIndent("} // namespace JSON");
+
6296}
+
6297
+
6298void GeneratorCpp::GenerateFBE_Header(const CppCommon::Path& path)
+
6299{
+
6300 // Create package path
+
6301 CppCommon::Directory::CreateTree(path);
+
6302
+
6303 // Generate the common file
+
6304 CppCommon::Path common = path / "fbe.h";
+
6305 WriteBegin();
+
6306
+
6307 // Generate common header
+
6308 GenerateHeader("FBE");
+
6309
+
6310 // Generate imports
+
6311 GenerateImports();
+
6312
+
6313 // Generate namespace begin
+
6314 WriteLine();
+
6315 WriteLineIndent("namespace FBE {");
+
6316
+
6317 // Generate common body
+
6318 GenerateBufferWrapper_Header();
+
6319 GenerateDecimalWrapper_Header();
+
6320 GenerateFlagsWrapper_Header();
+
6321 GenerateTimeWrapper_Header();
+
6322 GenerateUUIDWrapper_Header();
+
6323 GenerateFBEBuffer_Header();
+
6324 GenerateFBEBaseModel_Header();
+
6325
+
6326 // Generate namespace end
+
6327 WriteLine();
+
6328 WriteLineIndent("} // namespace FBE");
+
6329
+
6330 // Generate common footer
+
6331 GenerateFooter();
+
6332
+
6333 // Store the common file
+
6334 WriteEnd();
+
6335 Store(common);
+
6336}
+
6337
+
6338void GeneratorCpp::GenerateFBE_Source(const CppCommon::Path& path)
+
6339{
+
6340 // Create package path
+
6341 CppCommon::Directory::CreateTree(path);
+
6342
+
6343 // Generate the common file
+
6344 CppCommon::Path common = path / "fbe.cpp";
+
6345 WriteBegin();
+
6346
+
6347 // Generate common source
+
6348 GenerateSource("FBE");
+
6349
+
6350 // Generate imports
+
6351 GenerateImports("fbe.h");
+
6352
+
6353 // Generate imports source
+
6354 GenerateImportsSource();
+
6355
+
6356 // Generate namespace begin
+
6357 WriteLine();
+
6358 WriteLineIndent("namespace FBE {");
+
6359
+
6360 // Generate common body
+
6361 GenerateBufferWrapper_Source();
+
6362 GenerateTimeWrapper_Source();
+
6363 GenerateUUIDWrapper_Source();
+
6364 GenerateFBEBuffer_Source();
+
6365
+
6366 // Generate namespace end
+
6367 WriteLine();
+
6368 WriteLineIndent("} // namespace FBE");
+
6369
+
6370 // Generate common footer
+
6371 GenerateFooter();
+
6372
+
6373 // Store the common file
+
6374 WriteEnd();
+
6375 Store(common);
+
6376}
+
6377
+
6378void GeneratorCpp::GenerateFBEModels_Header(const CppCommon::Path& path)
+
6379{
+
6380 // Create package path
+
6381 CppCommon::Directory::CreateTree(path);
+
6382
+
6383 // Generate the field models file
+
6384 CppCommon::Path common = path / "fbe_models.h";
+
6385 WriteBegin();
+
6386
+
6387 // Generate field models header
+
6388 GenerateHeader("FBE");
+
6389
+
6390 // Generate imports
+
6391 GenerateImports("fbe.h");
+
6392
+
6393 // Generate namespace begin
+
6394 WriteLine();
+
6395 WriteLineIndent("namespace FBE {");
+
6396
+
6397 // Generate field models
+
6398 GenerateFBEFieldModel_Header();
+
6399 GenerateFBEFieldModelDecimal_Header();
+
6400 GenerateFBEFieldModelUUID_Header();
+
6401 GenerateFBEFieldModelBytes_Header();
+
6402 GenerateFBEFieldModelString_Header();
+
6403 GenerateFBEFieldModelOptional_Header();
+
6404 GenerateFBEFieldModelArray_Header();
+
6405 GenerateFBEFieldModelVector_Header();
+
6406 GenerateFBEFieldModelMap_Header();
+
6407
+
6408 // Generate namespace end
+
6409 WriteLine();
+
6410 WriteLineIndent("} // namespace FBE");
+
6411
+
6412 // Generate inline import
+
6413 GenerateImports("fbe_models.inl");
+
6414
+
6415 // Generate field models footer
+
6416 GenerateFooter();
+
6417
+
6418 // Store the field models file
+
6419 WriteEnd();
+
6420 Store(common);
+
6421}
+
6422
+
6423void GeneratorCpp::GenerateFBEModels_Inline(const CppCommon::Path& path)
+
6424{
+
6425 // Create package path
+
6426 CppCommon::Directory::CreateTree(path);
+
6427
+
6428 // Generate the field models file
+
6429 CppCommon::Path common = path / "fbe_models.inl";
+
6430 WriteBegin();
+
6431
+
6432 // Generate field models inline
+
6433 GenerateInline("FBE");
+
6434
+
6435 // Generate namespace begin
+
6436 WriteLine();
+
6437 WriteLineIndent("namespace FBE {");
+
6438
+
6439 // Generate field models
+
6440 GenerateFBEFieldModel_Inline();
+
6441 GenerateFBEFieldModelOptional_Inline();
+
6442 GenerateFBEFieldModelArray_Inline();
+
6443 GenerateFBEFieldModelVector_Inline();
+
6444 GenerateFBEFieldModelMap_Inline();
+
6445
+
6446 // Generate namespace end
+
6447 WriteLine();
+
6448 WriteLineIndent("} // namespace FBE");
+
6449
+
6450 // Generate field models footer
+
6451 GenerateFooter();
+
6452
+
6453 // Store the field models file
+
6454 WriteEnd();
+
6455 Store(common);
+
6456}
+
6457
+
6458void GeneratorCpp::GenerateFBEModels_Source(const CppCommon::Path& path)
+
6459{
+
6460 // Create package path
+
6461 CppCommon::Directory::CreateTree(path);
+
6462
+
6463 // Generate the field models file
+
6464 CppCommon::Path common = path / "fbe_models.cpp";
+
6465 WriteBegin();
+
6466
+
6467 // Generate field models source
+
6468 GenerateSource("FBE");
+
6469
+
6470 // Generate imports
+
6471 GenerateImports("fbe_models.h");
+
6472
+
6473 // Generate namespace begin
+
6474 WriteLine();
+
6475 WriteLineIndent("namespace FBE {");
+
6476
+
6477 // Generate field models
+
6478 GenerateFBEFieldModelDecimal_Source();
+
6479 GenerateFBEFieldModelUUID_Source();
+
6480 GenerateFBEFieldModelBytes_Source();
+
6481 GenerateFBEFieldModelString_Source();
+
6482
+
6483 // Generate namespace end
+
6484 WriteLine();
+
6485 WriteLineIndent("} // namespace FBE");
+
6486
+
6487 // Generate field models footer
+
6488 GenerateFooter();
+
6489
+
6490 // Store the field models file
+
6491 WriteEnd();
+
6492 Store(common);
+
6493}
+
6494
+
6495void GeneratorCpp::GenerateFBEFinalModels_Header(const CppCommon::Path& path)
+
6496{
+
6497 // Create package path
+
6498 CppCommon::Directory::CreateTree(path);
+
6499
+
6500 // Generate the final models file
+
6501 CppCommon::Path common = path / "fbe_final_models.h";
+
6502 WriteBegin();
+
6503
+
6504 // Generate final models header
+
6505 GenerateHeader("FBE");
+
6506
+
6507 // Generate imports
+
6508 GenerateImports("fbe.h");
+
6509
+
6510 // Generate namespace begin
+
6511 WriteLine();
+
6512 WriteLineIndent("namespace FBE {");
+
6513
+
6514 // Generate final models
+
6515 GenerateFBEFinalModel_Header();
+
6516 GenerateFBEFinalModelDecimal_Header();
+
6517 GenerateFBEFinalModelUUID_Header();
+
6518 GenerateFBEFinalModelBytes_Header();
+
6519 GenerateFBEFinalModelString_Header();
+
6520 GenerateFBEFinalModelOptional_Header();
+
6521 GenerateFBEFinalModelArray_Header();
+
6522 GenerateFBEFinalModelVector_Header();
+
6523 GenerateFBEFinalModelMap_Header();
+
6524
+
6525 // Generate namespace end
+
6526 WriteLine();
+
6527 WriteLineIndent("} // namespace FBE");
+
6528
+
6529 // Generate inline import
+
6530 GenerateImports("fbe_final_models.inl");
+
6531
+
6532 // Generate final models footer
+
6533 GenerateFooter();
+
6534
+
6535 // Store the final models file
+
6536 WriteEnd();
+
6537 Store(common);
+
6538}
+
6539
+
6540void GeneratorCpp::GenerateFBEFinalModels_Inline(const CppCommon::Path& path)
+
6541{
+
6542 // Create package path
+
6543 CppCommon::Directory::CreateTree(path);
+
6544
+
6545 // Generate the final models file
+
6546 CppCommon::Path common = path / "fbe_final_models.inl";
+
6547 WriteBegin();
+
6548
+
6549 // Generate final models inline
+
6550 GenerateInline("FBE");
+
6551
+
6552 // Generate namespace begin
+
6553 WriteLine();
+
6554 WriteLineIndent("namespace FBE {");
+
6555
+
6556 // Generate final models
+
6557 GenerateFBEFinalModel_Inline();
+
6558 GenerateFBEFinalModelOptional_Inline();
+
6559 GenerateFBEFinalModelArray_Inline();
+
6560 GenerateFBEFinalModelVector_Inline();
+
6561 GenerateFBEFinalModelMap_Inline();
+
6562
+
6563 // Generate namespace end
+
6564 WriteLine();
+
6565 WriteLineIndent("} // namespace FBE");
+
6566
+
6567 // Generate final models footer
+
6568 GenerateFooter();
+
6569
+
6570 // Store the final models file
+
6571 WriteEnd();
+
6572 Store(common);
+
6573}
+
6574
+
6575void GeneratorCpp::GenerateFBEFinalModels_Source(const CppCommon::Path& path)
+
6576{
+
6577 // Create package path
+
6578 CppCommon::Directory::CreateTree(path);
+
6579
+
6580 // Generate the final models file
+
6581 CppCommon::Path common = path / "fbe_final_models.cpp";
+
6582 WriteBegin();
+
6583
+
6584 // Generate final models source
+
6585 GenerateSource("FBE");
+
6586
+
6587 // Generate imports
+
6588 GenerateImports("fbe_final_models.h");
+
6589
+
6590 // Generate namespace begin
+
6591 WriteLine();
+
6592 WriteLineIndent("namespace FBE {");
+
6593
+
6594 // Generate final models
+
6595 GenerateFBEFinalModelDecimal_Source();
+
6596 GenerateFBEFinalModelUUID_Source();
+
6597 GenerateFBEFinalModelBytes_Source();
+
6598 GenerateFBEFinalModelString_Source();
+
6599
+
6600 // Generate namespace end
+
6601 WriteLine();
+
6602 WriteLineIndent("} // namespace FBE");
+
6603
+
6604 // Generate final models footer
+
6605 GenerateFooter();
+
6606
+
6607 // Store the final models file
+
6608 WriteEnd();
+
6609 Store(common);
+
6610}
+
6611
+
6612void GeneratorCpp::GenerateFBEProtocol_Header(const CppCommon::Path& path)
+
6613{
+
6614 // Create package path
+
6615 CppCommon::Directory::CreateTree(path);
+
6616
+
6617 // Generate the protocol file
+
6618 CppCommon::Path common = path / "fbe_protocol.h";
+
6619 WriteBegin();
+
6620
+
6621 // Generate protocol header
+
6622 GenerateHeader("FBE");
+
6623
+
6624 // Generate imports
+
6625 GenerateImports("fbe.h");
+
6626
+
6627 // Generate namespace begin
+
6628 WriteLine();
+
6629 WriteLineIndent("namespace FBE {");
+
6630
+
6631 // Generate protocol
+
6632 GenerateFBESender_Header();
+
6633 GenerateFBEReceiver_Header();
+
6634
+
6635 // Generate namespace end
+
6636 WriteLine();
+
6637 WriteLineIndent("} // namespace FBE");
+
6638
+
6639 // Generate protocol footer
+
6640 GenerateFooter();
+
6641
+
6642 // Store the protocol file
+
6643 WriteEnd();
+
6644 Store(common);
+
6645}
+
6646
+
6647void GeneratorCpp::GenerateFBEProtocol_Source(const CppCommon::Path& path)
+
6648{
+
6649 // Create package path
+
6650 CppCommon::Directory::CreateTree(path);
+
6651
+
6652 // Generate the protocol file
+
6653 CppCommon::Path common = path / "fbe_protocol.cpp";
+
6654 WriteBegin();
+
6655
+
6656 // Generate protocol source
+
6657 GenerateSource("FBE");
+
6658
+
6659 // Generate imports
+
6660 GenerateImports("fbe_protocol.h");
+
6661
+
6662 // Generate namespace begin
+
6663 WriteLine();
+
6664 WriteLineIndent("namespace FBE {");
+
6665
+
6666 // Generate protocol
+
6667 GenerateFBESender_Source();
+
6668 GenerateFBEReceiver_Source();
+
6669
+
6670 // Generate namespace end
+
6671 WriteLine();
+
6672 WriteLineIndent("} // namespace FBE");
+
6673
+
6674 // Generate protocol footer
+
6675 GenerateFooter();
+
6676
+
6677 // Store the protocol file
+
6678 WriteEnd();
+
6679 Store(common);
+
6680}
+
6681
+
6682void GeneratorCpp::GenerateFBEJson_Header(const CppCommon::Path& path)
+
6683{
+
6684 // Create package path
+
6685 CppCommon::Directory::CreateTree(path);
+
6686
+
6687 // Generate the JSON file
+
6688 CppCommon::Path common = path / "fbe_json.h";
+
6689 WriteBegin();
+
6690
+
6691 // Generate JSON header
+
6692 GenerateHeader("FBE");
+
6693
+
6694 // Generate imports
+
6695 GenerateImports("fbe.h");
+
6696 GenerateImportsJson();
+
6697
+
6698 // Generate namespace begin
+
6699 WriteLine();
+
6700 WriteLineIndent("namespace FBE {");
+
6701
+
6702 // Generate JSON
+
6703 GenerateFBEJson();
+
6704
+
6705 // Generate namespace end
+
6706 WriteLine();
+
6707 WriteLineIndent("} // namespace FBE");
+
6708
+
6709 // Generate JSON footer
+
6710 GenerateFooter();
+
6711
+
6712 // Store the JSON file
+
6713 WriteEnd();
+
6714 Store(common);
+
6715}
+
6716
+
6717void GeneratorCpp::GeneratePackage_Header(const std::shared_ptr<Package>& p)
+
6718{
+
6719 CppCommon::Path output = _output;
+
6720
+
6721 // Create package path
+
6722 CppCommon::Directory::CreateTree(output);
+
6723
+
6724 // Generate the output file
+
6725 output /= *p->name + ".h";
+
6726 WriteBegin();
+
6727
+
6728 // Generate package header
+
6729 GenerateHeader(CppCommon::Path(_input).filename().string());
+
6730
+
6731 // Generate imports
+
6732 GenerateImports(p);
+
6733
+
6734 // Generate namespace begin
+
6735 WriteLine();
+
6736 WriteLineIndent("namespace " + *p->name + " {");
+
6737
+
6738 // Generate namespace body
+
6739 if (p->body)
+
6740 {
+
6741 // Generate child enums
+
6742 for (const auto& e : p->body->enums)
+
6743 GenerateEnum(p, e);
+
6744
+
6745 // Generate child flags
+
6746 for (const auto& f : p->body->flags)
+
6747 GenerateFlags(p, f);
+
6748
+
6749 // Generate child structs
+
6750 for (const auto& s : p->body->structs)
+
6751 GenerateStruct_Header(p, s);
+
6752 }
+
6753
+
6754 // Generate namespace end
+
6755 WriteLine();
+
6756 WriteLineIndent("} // namespace " + *p->name);
+
6757
+
6758 // Generate package footer
+
6759 GenerateFooter();
+
6760
+
6761 // Store the output file
+
6762 WriteEnd();
+
6763 Store(output);
+
6764}
+
6765
+
6766void GeneratorCpp::GeneratePackage_Source(const std::shared_ptr<Package>& p)
+
6767{
+
6768 CppCommon::Path output = _output;
+
6769
+
6770 // Create package path
+
6771 CppCommon::Directory::CreateTree(output);
+
6772
+
6773 // Generate the output file
+
6774 output /= *p->name + ".cpp";
+
6775 WriteBegin();
+
6776
+
6777 // Generate package source
+
6778 GenerateSource(CppCommon::Path(_input).filename().string());
+
6779
+
6780 // Generate imports
+
6781 GenerateImports(*p->name + ".h");
+
6782
+
6783 // Generate namespace begin
+
6784 WriteLine();
+
6785 WriteLineIndent("namespace " + *p->name + " {");
+
6786
+
6787 // Generate namespace body
+
6788 if (p->body)
+
6789 {
+
6790 // Generate child enums
+
6791 for (const auto& e : p->body->enums)
+
6792 {
+
6793 // Generate enum output stream
+
6794 GenerateEnumOutputStream(e);
+
6795
+
6796 // Generate enum logging stream
+
6797 if (Logging())
+
6798 GenerateEnumLoggingStream(e);
+
6799 }
+
6800
+
6801 // Generate child flags
+
6802 for (const auto& f : p->body->flags)
+
6803 {
+
6804 // Generate flags output stream
+
6805 GenerateFlagsOutputStream(f);
+
6806
+
6807 // Generate flags logging stream
+
6808 if (Logging())
+
6809 GenerateFlagsLoggingStream(f);
+
6810 }
+
6811
+
6812 // Generate child structs
+
6813 for (const auto& s : p->body->structs)
+
6814 {
+
6815 GenerateStruct_Source(p, s);
+
6816
+
6817 // Generate struct output stream
+
6818 GenerateStructOutputStream(p, s);
+
6819
+
6820 // Generate struct logging stream
+
6821 if (Logging())
+
6822 GenerateStructLoggingStream(p, s);
+
6823 }
+
6824 }
+
6825
+
6826 // Generate namespace end
+
6827 WriteLine();
+
6828 WriteLineIndent("} // namespace " + *p->name);
+
6829
+
6830 // Generate package footer
+
6831 GenerateFooter();
+
6832
+
6833 // Store the output file
+
6834 WriteEnd();
+
6835 Store(output);
+
6836}
+
6837
+
6838void GeneratorCpp::GeneratePackage_Json(const std::shared_ptr<Package>& p)
+
6839{
+
6840 CppCommon::Path output = _output;
+
6841
+
6842 // Create package path
+
6843 CppCommon::Directory::CreateTree(output);
+
6844
+
6845 // Generate the output file
+
6846 output /= *p->name + "_json.h";
+
6847 WriteBegin();
+
6848
+
6849 // Generate package header
+
6850 GenerateHeader(CppCommon::Path(_input).filename().string());
+
6851
+
6852 // Generate imports
+
6853 GenerateImportsJson(p);
+
6854
+
6855 // Generate namespace begin
+
6856 WriteLine();
+
6857 WriteLineIndent("namespace FBE {");
+
6858 WriteLine();
+
6859 WriteLineIndent("namespace JSON {");
+
6860
+
6861 // Generate namespace body
+
6862 if (p->body)
+
6863 {
+
6864 // Generate child enums
+
6865 for (const auto& e : p->body->enums)
+
6866 GenerateEnumJson(p, e);
+
6867
+
6868 // Generate child flags
+
6869 for (const auto& f : p->body->flags)
+
6870 GenerateFlagsJson(p, f);
+
6871
+
6872 // Generate child structs
+
6873 for (const auto& s : p->body->structs)
+
6874 GenerateStructJson(p, s);
+
6875 }
+
6876
+
6877 // Generate namespace end
+
6878 WriteLine();
+
6879 WriteLineIndent("} // namespace JSON");
+
6880 WriteLine();
+
6881 WriteLineIndent("} // namespace FBE");
+
6882
+
6883 // Generate package footer
+
6884 GenerateFooter();
+
6885
+
6886 // Store the output file
+
6887 WriteEnd();
+
6888 Store(output);
+
6889}
+
6890
+
6891void GeneratorCpp::GeneratePackageModels_Header(const std::shared_ptr<Package>& p)
+
6892{
+
6893 CppCommon::Path output = _output;
+
6894
+
6895 // Create package path
+
6896 CppCommon::Directory::CreateTree(output);
+
6897
+
6898 // Generate the output file
+
6899 output /= *p->name + "_models.h";
+
6900 WriteBegin();
+
6901
+
6902 // Generate package models header
+
6903 GenerateHeader(CppCommon::Path(_input).filename().string());
+
6904
+
6905 // Generate imports
+
6906 GenerateImports("fbe_models.h");
+
6907 GenerateImportsModels(p, false);
+
6908
+
6909 // Generate namespace begin
+
6910 WriteLine();
+
6911 WriteLineIndent("namespace FBE {");
+
6912
+
6913 // Generate namespace body
+
6914 if (p->body)
+
6915 {
+
6916 // Generate child enums
+
6917 for (const auto& e : p->body->enums)
+
6918 {
+
6919 // Generate enum field model
+
6920 GenerateEnumFieldModel(p, e);
+
6921 }
+
6922
+
6923 // Generate child flags
+
6924 for (const auto& f : p->body->flags)
+
6925 {
+
6926 // Generate flags field model
+
6927 GenerateFlagsFieldModel(p, f);
+
6928 }
+
6929
+
6930 // Generate child structs
+
6931 for (const auto& s : p->body->structs)
+
6932 {
+
6933 // Generate struct field models
+
6934 GenerateStructFieldModel_Header(p, s);
+
6935 GenerateStructModel_Header(p, s);
+
6936 }
+
6937 }
+
6938
+
6939 // Generate namespace end
+
6940 WriteLine();
+
6941 WriteLineIndent("} // namespace FBE");
+
6942
+
6943 // Generate package footer
+
6944 GenerateFooter();
+
6945
+
6946 // Store the output file
+
6947 WriteEnd();
+
6948 Store(output);
+
6949}
+
6950
+
6951void GeneratorCpp::GeneratePackageModels_Source(const std::shared_ptr<Package>& p)
+
6952{
+
6953 CppCommon::Path output = _output;
+
6954
+
6955 // Create package path
+
6956 CppCommon::Directory::CreateTree(output);
+
6957
+
6958 // Generate the output file
+
6959 output /= *p->name + "_models.cpp";
+
6960 WriteBegin();
+
6961
+
6962 // Generate package models source
+
6963 GenerateSource(CppCommon::Path(_input).filename().string());
+
6964
+
6965 // Generate imports
+
6966 GenerateImports(*p->name + "_models.h");
+
6967
+
6968 // Generate namespace begin
+
6969 WriteLine();
+
6970 WriteLineIndent("namespace FBE {");
+
6971
+
6972 // Generate namespace body
+
6973 if (p->body)
+
6974 {
+
6975 // Generate child structs
+
6976 for (const auto& s : p->body->structs)
+
6977 {
+
6978 // Generate struct field models
+
6979 GenerateStructFieldModel_Source(p, s);
+
6980 GenerateStructModel_Source(p, s);
+
6981 }
+
6982 }
+
6983
+
6984 // Generate namespace end
+
6985 WriteLine();
+
6986 WriteLineIndent("} // namespace FBE");
+
6987
+
6988 // Generate package footer
+
6989 GenerateFooter();
+
6990
+
6991 // Store the output file
+
6992 WriteEnd();
+
6993 Store(output);
+
6994}
+
6995
+
6996void GeneratorCpp::GeneratePackageFinalModels_Header(const std::shared_ptr<Package>& p)
+
6997{
+
6998 CppCommon::Path output = _output;
+
6999
+
7000 // Create package path
+
7001 CppCommon::Directory::CreateTree(output);
+
7002
+
7003 // Generate the output file
+
7004 output /= *p->name + "_final_models.h";
+
7005 WriteBegin();
+
7006
+
7007 // Generate package final models header
+
7008 GenerateHeader(CppCommon::Path(_input).filename().string());
+
7009
+
7010 // Generate imports
+
7011 GenerateImports("fbe_final_models.h");
+
7012 GenerateImportsModels(p, true);
+
7013
+
7014 // Generate namespace begin
+
7015 WriteLine();
+
7016 WriteLineIndent("namespace FBE {");
+
7017
+
7018 // Generate namespace body
+
7019 if (p->body)
+
7020 {
+
7021 // Generate child enums
+
7022 for (const auto& e : p->body->enums)
+
7023 {
+
7024 // Generate enum final model
+
7025 GenerateEnumFinalModel(p, e);
+
7026 }
+
7027
+
7028 // Generate child flags
+
7029 for (const auto& f : p->body->flags)
+
7030 {
+
7031 // Generate flags final model
+
7032 GenerateFlagsFinalModel(p, f);
+
7033 }
+
7034
+
7035 // Generate child structs
+
7036 for (const auto& s : p->body->structs)
+
7037 {
+
7038 // Generate struct final models
+
7039 GenerateStructFinalModel_Header(p, s);
+
7040 GenerateStructModelFinal_Header(p, s);
+
7041 }
+
7042 }
+
7043
+
7044 // Generate namespace end
+
7045 WriteLine();
+
7046 WriteLineIndent("} // namespace FBE");
+
7047
+
7048 // Generate package footer
+
7049 GenerateFooter();
+
7050
+
7051 // Store the output file
+
7052 WriteEnd();
+
7053 Store(output);
+
7054}
+
7055
+
7056void GeneratorCpp::GeneratePackageFinalModels_Source(const std::shared_ptr<Package>& p)
+
7057{
+
7058 CppCommon::Path output = _output;
+
7059
+
7060 // Create package path
+
7061 CppCommon::Directory::CreateTree(output);
+
7062
+
7063 // Generate the output file
+
7064 output /= *p->name + "_final_models.cpp";
+
7065 WriteBegin();
+
7066
+
7067 // Generate package final models source
+
7068 GenerateSource(CppCommon::Path(_input).filename().string());
+
7069
+
7070 // Generate imports
+
7071 GenerateImports(*p->name + "_final_models.h");
+
7072
+
7073 // Generate namespace begin
+
7074 WriteLine();
+
7075 WriteLineIndent("namespace FBE {");
+
7076
+
7077 // Generate namespace body
+
7078 if (p->body)
+
7079 {
+
7080 // Generate child structs
+
7081 for (const auto& s : p->body->structs)
+
7082 {
+
7083 // Generate struct final models
+
7084 GenerateStructFinalModel_Source(p, s);
+
7085 GenerateStructModelFinal_Source(p, s);
+
7086 }
+
7087 }
+
7088
+
7089 // Generate namespace end
+
7090 WriteLine();
+
7091 WriteLineIndent("} // namespace FBE");
+
7092
+
7093 // Generate package footer
+
7094 GenerateFooter();
+
7095
+
7096 // Store the output file
+
7097 WriteEnd();
+
7098 Store(output);
+
7099}
+
7100
+
7101void GeneratorCpp::GeneratePackageProtocol_Header(const std::shared_ptr<Package>& p, bool final)
+
7102{
+
7103 CppCommon::Path output = _output;
+
7104
+
7105 // Create package path
+
7106 CppCommon::Directory::CreateTree(output);
+
7107
+
7108 // Generate the output file
+
7109 output /= *p->name + (final ? "_final" : "") + "_protocol.h";
+
7110 WriteBegin();
+
7111
+
7112 // Generate package protocol header
+
7113 GenerateHeader(CppCommon::Path(_input).filename().string());
+
7114
+
7115 // Generate imports
+
7116 GenerateImports("fbe_protocol.h");
+
7117 GenerateImportsProtocol(p, final);
+
7118
+
7119 // Generate namespace begin
+
7120 WriteLine();
+
7121 WriteLineIndent("namespace FBE {");
+
7122 WriteLine();
+
7123 WriteLineIndent("namespace " + *p->name + " {");
+
7124
+
7125 // Generate protocol version
+
7126 GenerateProtocolVersion(p);
+
7127
+
7128 // Generate sender & receiver
+
7129 GenerateSender_Header(p, final);
+
7130 GenerateReceiver_Header(p, final);
+
7131 if (!final)
+
7132 GenerateProxy_Header(p, final);
+
7133 GenerateClient_Header(p, final);
+
7134
+
7135 // Generate namespace end
+
7136 WriteLine();
+
7137 WriteLineIndent("} // namespace " + *p->name);
+
7138 WriteLine();
+
7139 WriteLineIndent("} // namespace FBE");
+
7140
+
7141 // Generate package footer
+
7142 GenerateFooter();
+
7143
+
7144 // Store the output file
+
7145 WriteEnd();
+
7146 Store(output);
+
7147}
+
7148
+
7149void GeneratorCpp::GeneratePackageProtocol_Source(const std::shared_ptr<Package>& p, bool final)
+
7150{
+
7151 CppCommon::Path output = _output;
+
7152
+
7153 // Create package path
+
7154 CppCommon::Directory::CreateTree(output);
+
7155
+
7156 // Generate the output file
+
7157 output /= *p->name + (final ? "_final" : "") + "_protocol.cpp";
+
7158 WriteBegin();
+
7159
+
7160 // Generate package protocol source
+
7161 GenerateSource(CppCommon::Path(_input).filename().string());
+
7162
+
7163 // Generate warnings header
+
7164 GenerateWarningsHeader();
+
7165
+
7166 // Generate imports
+
7167 GenerateImports(*p->name + (final ? "_final" : "") + "_protocol.h");
+
7168
+
7169 // Generate namespace begin
+
7170 WriteLine();
+
7171 WriteLineIndent("namespace FBE {");
+
7172 WriteLine();
+
7173 WriteLineIndent("namespace " + *p->name + " {");
+
7174
+
7175 // Generate sender & receiver
+
7176 GenerateSender_Source(p, final);
+
7177 GenerateReceiver_Source(p, final);
+
7178 if (!final)
+
7179 GenerateProxy_Source(p, final);
+
7180 GenerateClient_Source(p, final);
+
7181
+
7182 // Generate namespace end
+
7183 WriteLine();
+
7184 WriteLineIndent("} // namespace " + *p->name);
+
7185 WriteLine();
+
7186 WriteLineIndent("} // namespace FBE");
+
7187
+
7188 // Generate warnings footer
+
7189 GenerateWarningsFooter();
+
7190
+
7191 // Generate package footer
+
7192 GenerateFooter();
+
7193
+
7194 // Store the output file
+
7195 WriteEnd();
+
7196 Store(output);
+
7197}
+
7198
+
7199void GeneratorCpp::GenerateEnum(const std::shared_ptr<Package>& p, const std::shared_ptr<EnumType>& e)
+
7200{
+
7201 // Generate enum begin
+
7202 WriteLine();
+
7203 WriteIndent("enum class " + std::string(e->attributes->deprecated ? "[[deprecated]] " : "") + *e->name);
+
7204 if (e->base && !e->base->empty())
+
7205 Write(" : " + ConvertEnumType(*e->base));
+
7206 WriteLine();
+
7207 WriteLineIndent("{");
+
7208 Indent(1);
+
7209
+
7210 std::string enum_type = (e->base && !e->base->empty()) ? *e->base : "int32";
+
7211
+
7212 // Generate enum body
+
7213 if (e->body)
+
7214 {
+
7215 for (const auto& value : e->body->values)
+
7216 {
+
7217 WriteIndent(*value->name);
+
7218 if (value->attributes->deprecated)
+
7219 Write(" [[deprecated]]");
+
7220 if (value->value)
+
7221 {
+
7222 if (value->value->constant && !value->value->constant->empty())
+
7223 Write(" = " + ConvertConstant(enum_type, *value->value->constant, false));
+
7224 else if (value->value->reference && !value->value->reference->empty())
+
7225 Write(" = " + ConvertConstant("", *value->value->reference, false));
+
7226 }
+
7227 WriteLine(",");
+
7228 }
+
7229 }
+
7230
+
7231 // Generate enum end
+
7232 Indent(-1);
+
7233 WriteLineIndent("};");
+
7234
+
7235 // Generate enum output stream operator declaration
+
7236 WriteLine();
+
7237 WriteLineIndent("std::ostream& operator<<(std::ostream& stream, " + *e->name + " value);");
+
7238
+
7239 // Generate enum formatter declaration
+
7240 WriteLine();
+
7241 WriteLineIndent("#if defined(FMT_VERSION) && (FMT_VERSION >= 90000)");
+
7242 WriteLineIndent("} template <> struct fmt::formatter<" + *p->name + "::" + *e->name + "> : ostream_formatter {}; namespace " + *p->name + " {");
+
7243 WriteLineIndent("#endif");
+
7244
+
7245 // Generate enum logging stream operator declaration
+
7246 WriteLine();
+
7247 WriteLineIndent("#if defined(LOGGING_PROTOCOL)");
+
7248 WriteLineIndent("CppLogging::Record& operator<<(CppLogging::Record& record, " + *e->name + " value);");
+
7249 WriteLineIndent("#endif");
+
7250}
+
7251
+
7252void GeneratorCpp::GenerateEnumOutputStream(const std::shared_ptr<EnumType>& e)
+
7253{
+
7254 // Generate enum output stream operator begin
+
7255 WriteLine();
+
7256 WriteLineIndent("std::ostream& operator<<(std::ostream& stream, " + *e->name + " value)");
+
7257 WriteLineIndent("{");
+
7258 Indent(1);
+
7259
+
7260 // Generate enum output stream operator body
+
7261 if (e->body && !e->body->values.empty())
+
7262 {
+
7263 for (auto it = e->body->values.begin(); it != e->body->values.end(); ++it)
+
7264 WriteLineIndent("if (value == " + *e->name + "::" + *(*it)->name + ")" + " return stream << \"" + *(*it)->name + "\";");
+
7265 WriteLineIndent("return stream << \"<unknown>\";");
+
7266 }
+
7267 else
+
7268 WriteLineIndent("return stream << \"<empty>\";");
+
7269
+
7270 // Generate enum output stream operator end
+
7271 Indent(-1);
+
7272 WriteLineIndent("}");
+
7273}
+
7274
+
7275void GeneratorCpp::GenerateEnumLoggingStream(const std::shared_ptr<EnumType>& e)
+
7276{
+
7277 // Generate enum logging stream operator begin
+
7278 WriteLine();
+
7279 WriteLineIndent("#if defined(LOGGING_PROTOCOL)");
+
7280 WriteLineIndent("CppLogging::Record& operator<<(CppLogging::Record& record, " + *e->name + " value)");
+
7281 WriteLineIndent("{");
+
7282 Indent(1);
+
7283
+
7284 // Generate enum logging stream operator body
+
7285 if (e->body && !e->body->values.empty())
+
7286 {
+
7287 for (auto it = e->body->values.begin(); it != e->body->values.end(); ++it)
+
7288 WriteLineIndent("if (value == " + *e->name + "::" + *(*it)->name + ")" + " return record.StoreCustom(\"" + *(*it)->name + "\");");
+
7289 WriteLineIndent("return record.StoreCustom(\"<unknown>\");");
+
7290 }
+
7291 else
+
7292 WriteLineIndent("return record.StoreCustom(\"<empty>\");");
+
7293
+
7294 // Generate enum logging stream operator end
+
7295 Indent(-1);
+
7296 WriteLineIndent("}");
+
7297 WriteLineIndent("#endif");
+
7298}
+
7299
+
7300void GeneratorCpp::GenerateEnumJson(const std::shared_ptr<Package>& p, const std::shared_ptr<EnumType>& e)
+
7301{
+
7302 std::string enum_name = "::" + *p->name + "::" + *e->name;
+
7303 std::string enum_type = (e->base && !e->base->empty()) ? *e->base : "int32";
+
7304 std::string enum_base_type = ConvertEnumType(enum_type);
+
7305
+
7306 std::string json = R"CODE(
+
7307template <class TWriter>
+
7308struct ValueWriter<TWriter, _ENUM_NAME_>
+
7309{
+
7310 static bool to_json(TWriter& writer, const _ENUM_NAME_& value, bool scope = true)
+
7311 {
+
7312 return FBE::JSON::to_json(writer, (_ENUM_TYPE_)value);
+
7313 }
+
7314};
+
7315
+
7316template <class TJson>
+
7317struct ValueReader<TJson, _ENUM_NAME_>
+
7318{
+
7319 static bool from_json(const TJson& json, _ENUM_NAME_& value)
+
7320 {
+
7321 _ENUM_TYPE_ raw;
+
7322 if (!FBE::JSON::from_json(json, raw))
+
7323 return false;
+
7324
+
7325 value = (_ENUM_NAME_)raw;
+
7326 return true;
+
7327 }
+
7328};
+
7329)CODE";
+
7330
+
7331 // Prepare enum template
+
7332 json = std::regex_replace(json, std::regex("_ENUM_NAME_"), enum_name);
+
7333 json = std::regex_replace(json, std::regex("_ENUM_TYPE_"), enum_base_type);
+
7334 json = std::regex_replace(json, std::regex("\n"), EndLine());
+
7335
+
7336 // Generate enum JSON
+
7337 Write(json);
+
7338}
+
7339
+
7340void GeneratorCpp::GenerateEnumFieldModel(const std::shared_ptr<Package>& p, const std::shared_ptr<EnumType>& e)
+
7341{
+
7342 std::string enum_name = "::" + *p->name + "::" + *e->name;
+
7343 std::string enum_type = (e->base && !e->base->empty()) ? *e->base : "int32";
+
7344 std::string enum_base_type = ConvertEnumType(enum_type);
+
7345
+
7346 std::string code = R"CODE(
+
7347// Fast Binary Encoding _ENUM_NAME_ field model
+
7348template <>
+
7349class FieldModel<_ENUM_NAME_> : public FieldModelBase<_ENUM_NAME_, _ENUM_TYPE_>
+
7350{
+
7351public:
+
7352 using FieldModelBase<_ENUM_NAME_, _ENUM_TYPE_>::FieldModelBase;
+
7353};
+
7354)CODE";
+
7355
+
7356 // Prepare enum template
+
7357 code = std::regex_replace(code, std::regex("_ENUM_NAME_"), enum_name);
+
7358 code = std::regex_replace(code, std::regex("_ENUM_TYPE_"), enum_base_type);
+
7359 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
7360
+
7361 // Generate enum field model
+
7362 Write(code);
+
7363}
+
7364
+
7365void GeneratorCpp::GenerateEnumFinalModel(const std::shared_ptr<Package>& p, const std::shared_ptr<EnumType>& e)
+
7366{
+
7367 std::string enum_name = "::" + *p->name + "::" + *e->name;
+
7368 std::string enum_type = (e->base && !e->base->empty()) ? *e->base : "int32";
+
7369 std::string enum_base_type = ConvertEnumType(enum_type);
+
7370
+
7371 std::string code = R"CODE(
+
7372// Fast Binary Encoding _ENUM_NAME_ final model
+
7373template <>
+
7374class FinalModel<_ENUM_NAME_> : public FinalModelBase<_ENUM_NAME_, _ENUM_TYPE_>
+
7375{
+
7376public:
+
7377 using FinalModelBase<_ENUM_NAME_, _ENUM_TYPE_>::FinalModelBase;
+
7378};
+
7379)CODE";
+
7380
+
7381 // Prepare enum template
+
7382 code = std::regex_replace(code, std::regex("_ENUM_NAME_"), enum_name);
+
7383 code = std::regex_replace(code, std::regex("_ENUM_TYPE_"), enum_base_type);
+
7384 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
7385
+
7386 // Generate enum final model
+
7387 Write(code);
+
7388}
+
7389
+
7390void GeneratorCpp::GenerateFlags(const std::shared_ptr<Package>& p, const std::shared_ptr<FlagsType>& f)
+
7391{
+
7392 // Generate flags begin
+
7393 WriteLine();
+
7394 WriteIndent("enum class " + std::string(f->attributes->deprecated ? "[[deprecated]] " : "") + *f->name);
+
7395 if (f->base && !f->base->empty())
+
7396 Write(" : " + ConvertEnumType(*f->base));
+
7397 WriteLine();
+
7398 WriteLineIndent("{");
+
7399 Indent(1);
+
7400
+
7401 std::string flags_type = (f->base && !f->base->empty()) ? *f->base : "int32";
+
7402
+
7403 // Generate flags body
+
7404 if (f->body)
+
7405 {
+
7406 for (const auto& value : f->body->values)
+
7407 {
+
7408 WriteIndent(*value->name);
+
7409 if (value->attributes->deprecated)
+
7410 Write(" [[deprecated]]");
+
7411 if (value->value)
+
7412 {
+
7413 if (value->value->constant && !value->value->constant->empty())
+
7414 Write(" = " + ConvertConstant(flags_type, *value->value->constant, false));
+
7415 else if (value->value->reference && !value->value->reference->empty())
+
7416 Write(" = " + ConvertConstant("", *value->value->reference, false));
+
7417 }
+
7418 WriteLine(",");
+
7419 }
+
7420 }
+
7421
+
7422 // Generate flags end
+
7423 Indent(-1);
+
7424 WriteLineIndent("};");
+
7425 WriteLine();
+
7426 WriteLineIndent("FBE_ENUM_FLAGS(" + *f->name + ")");
+
7427
+
7428 // Generate flags output stream operator declaration
+
7429 WriteLine();
+
7430 WriteLineIndent("std::ostream& operator<<(std::ostream& stream, " + *f->name + " value);");
+
7431
+
7432 // Generate flags formatter declaration
+
7433 WriteLine();
+
7434 WriteLineIndent("#if defined(FMT_VERSION) && (FMT_VERSION >= 90000)");
+
7435 WriteLineIndent("} template <> struct fmt::formatter<" + *p->name + "::" + *f->name + "> : ostream_formatter {}; namespace " + *p->name + " {");
+
7436 WriteLineIndent("#endif");
+
7437
+
7438 // Generate flags logging stream operator declaration
+
7439 WriteLine();
+
7440 WriteLineIndent("#if defined(LOGGING_PROTOCOL)");
+
7441 WriteLineIndent("CppLogging::Record& operator<<(CppLogging::Record& record, " + *f->name + " value);");
+
7442 WriteLineIndent("#endif");
+
7443}
+
7444
+
7445void GeneratorCpp::GenerateFlagsOutputStream(const std::shared_ptr<FlagsType>& f)
+
7446{
+
7447 // Generate flags output stream operator begin
+
7448 WriteLine();
+
7449 WriteLineIndent("std::ostream& operator<<(std::ostream& stream, " + *f->name + " value)");
+
7450 WriteLineIndent("{");
+
7451 Indent(1);
+
7452
+
7453 // Generate flags output stream operator body
+
7454 if (f->body && !f->body->values.empty())
+
7455 {
+
7456 WriteLineIndent("bool first = true;");
+
7457 for (auto it = f->body->values.begin(); it != f->body->values.end(); ++it)
+
7458 {
+
7459 WriteLineIndent("if ((value & " + *f->name + "::" + *(*it)->name + ") && ((value & " + *f->name + "::" + *(*it)->name + ") == " + *f->name + "::" + *(*it)->name + "))");
+
7460 WriteLineIndent("{");
+
7461 Indent(1);
+
7462 WriteLineIndent("stream << (first ? \"\" : \"|\") << \"" + *(*it)->name + "\";");
+
7463 WriteLineIndent("first = false;");
+
7464 Indent(-1);
+
7465 WriteLineIndent("}");
+
7466 }
+
7467 }
+
7468 WriteLineIndent("return stream;");
+
7469
+
7470 // Generate flags output stream operator end
+
7471 Indent(-1);
+
7472 WriteLineIndent("}");
+
7473}
+
7474
+
7475void GeneratorCpp::GenerateFlagsLoggingStream(const std::shared_ptr<FlagsType>& f)
+
7476{
+
7477 // Generate flags logging stream operator begin
+
7478 WriteLine();
+
7479 WriteLineIndent("#if defined(LOGGING_PROTOCOL)");
+
7480 WriteLineIndent("CppLogging::Record& operator<<(CppLogging::Record& record, " + *f->name + " value)");
+
7481 WriteLineIndent("{");
+
7482 Indent(1);
+
7483
+
7484 // Generate flags output stream operator body
+
7485 WriteLineIndent("const size_t begin = record.StoreListBegin();");
+
7486 if (f->body && !f->body->values.empty())
+
7487 {
+
7488 WriteLineIndent("bool first = true;");
+
7489 for (auto it = f->body->values.begin(); it != f->body->values.end(); ++it)
+
7490 {
+
7491 WriteLineIndent("if ((value & " + *f->name + "::" + *(*it)->name + ") && ((value & " + *f->name + "::" + *(*it)->name + ") == " + *f->name + "::" + *(*it)->name + "))");
+
7492 WriteLineIndent("{");
+
7493 Indent(1);
+
7494 WriteLineIndent("record.StoreList((first ? \"\" : \"|\")).StoreList(\"" + *(*it)->name + "\");");
+
7495 WriteLineIndent("first = false;");
+
7496 Indent(-1);
+
7497 WriteLineIndent("}");
+
7498 }
+
7499 }
+
7500 WriteLineIndent("return record.StoreListEnd(begin);");
+
7501
+
7502 // Generate flags logging stream operator end
+
7503 Indent(-1);
+
7504 WriteLineIndent("}");
+
7505 WriteLineIndent("#endif");
+
7506}
+
7507
+
7508void GeneratorCpp::GenerateFlagsJson(const std::shared_ptr<Package>& p, const std::shared_ptr<FlagsType>& f)
+
7509{
+
7510 std::string flags_name = "::" + *p->name + "::" + *f->name;
+
7511 std::string flags_type = (f->base && !f->base->empty()) ? *f->base : "int32";
+
7512 std::string flags_base_type = ConvertEnumType(flags_type);
+
7513
+
7514 std::string json = R"CODE(
+
7515template <class TWriter>
+
7516struct ValueWriter<TWriter, _FLAGS_NAME_>
+
7517{
+
7518 static bool to_json(TWriter& writer, const _FLAGS_NAME_& value, bool scope = true)
+
7519 {
+
7520 return FBE::JSON::to_json(writer, (_FLAGS_TYPE_)value);
+
7521 }
+
7522};
+
7523
+
7524template <class TJson>
+
7525struct ValueReader<TJson, _FLAGS_NAME_>
+
7526{
+
7527 static bool from_json(const TJson& json, _FLAGS_NAME_& value)
+
7528 {
+
7529 _FLAGS_TYPE_ raw;
+
7530 if (!FBE::JSON::from_json(json, raw))
+
7531 return false;
+
7532
+
7533 value = (_FLAGS_NAME_)raw;
+
7534 return true;
+
7535 }
+
7536};
+
7537)CODE";
+
7538
+
7539 // Prepare flags template
+
7540 json = std::regex_replace(json, std::regex("_FLAGS_NAME_"), flags_name);
+
7541 json = std::regex_replace(json, std::regex("_FLAGS_TYPE_"), flags_base_type);
+
7542 json = std::regex_replace(json, std::regex("\n"), EndLine());
+
7543
+
7544 // Generate flags JSON
+
7545 Write(json);
+
7546}
+
7547
+
7548void GeneratorCpp::GenerateFlagsFieldModel(const std::shared_ptr<Package>& p, const std::shared_ptr<FlagsType>& f)
+
7549{
+
7550 std::string flags_name = "::" + *p->name + "::" + *f->name;
+
7551 std::string flags_type = (f->base && !f->base->empty()) ? *f->base : "int32";
+
7552 std::string flags_base_type = ConvertEnumType(flags_type);
+
7553
+
7554 std::string code = R"CODE(
+
7555// Fast Binary Encoding _FLAGS_NAME_ field model
+
7556template <>
+
7557class FieldModel<_FLAGS_NAME_> : public FieldModelBase<_FLAGS_NAME_, _FLAGS_TYPE_>
+
7558{
+
7559public:
+
7560 using FieldModelBase<_FLAGS_NAME_, _FLAGS_TYPE_>::FieldModelBase;
+
7561};
+
7562)CODE";
+
7563
+
7564 // Prepare flags template
+
7565 code = std::regex_replace(code, std::regex("_FLAGS_NAME_"), flags_name);
+
7566 code = std::regex_replace(code, std::regex("_FLAGS_TYPE_"), flags_base_type);
+
7567 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
7568
+
7569 // Generate flags field model
+
7570 Write(code);
+
7571}
+
7572
+
7573void GeneratorCpp::GenerateFlagsFinalModel(const std::shared_ptr<Package>& p, const std::shared_ptr<FlagsType>& f)
+
7574{
+
7575 std::string flags_name = "::" + *p->name + "::" + *f->name;
+
7576 std::string flags_type = (f->base && !f->base->empty()) ? *f->base : "int32";
+
7577 std::string flags_base_type = ConvertEnumType(flags_type);
+
7578
+
7579 std::string code = R"CODE(
+
7580// Fast Binary Encoding _FLAGS_NAME_ final model
+
7581template <>
+
7582class FinalModel<_FLAGS_NAME_> : public FinalModelBase<_FLAGS_NAME_, _FLAGS_TYPE_>
+
7583{
+
7584public:
+
7585 using FinalModelBase<_FLAGS_NAME_, _FLAGS_TYPE_>::FinalModelBase;
+
7586};
+
7587)CODE";
+
7588
+
7589 // Prepare flags template
+
7590 code = std::regex_replace(code, std::regex("_FLAGS_NAME_"), flags_name);
+
7591 code = std::regex_replace(code, std::regex("_FLAGS_TYPE_"), flags_base_type);
+
7592 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
7593
+
7594 // Generate flags final model
+
7595 Write(code);
+
7596}
+
7597
+
7598void GeneratorCpp::GenerateStruct_Header(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s)
+
7599{
+
7600 // Generate struct response forward declaration
+
7601 if (s->response)
+
7602 {
+
7603 std::string response = *s->response->response;
+
7604 bool imported = CppCommon::StringUtils::ReplaceAll(response, ".", "");
+
7605 if (!imported)
+
7606 {
+
7607 WriteLine();
+
7608 WriteLineIndent("struct " + response + ";");
+
7609 }
+
7610 }
+
7611
+
7612 // Generate struct begin
+
7613 WriteLine();
+
7614 WriteIndent("struct " + std::string(s->attributes->deprecated ? "[[deprecated]] " : "") + *s->name);
+
7615 if (s->base && !s->base->empty())
+
7616 Write(" : public " + ConvertTypeName(*p->name, *s->base, false));
+
7617 WriteLine();
+
7618 WriteLineIndent("{");
+
7619 Indent(1);
+
7620
+
7621 // Generate struct response type definition
+
7622 if (s->response)
+
7623 {
+
7624 std::string response = *s->response->response;
+
7625 CppCommon::StringUtils::ReplaceAll(response, ".", "::");
+
7626 WriteLineIndent("typedef " + response + " Response;");
+
7627 if (s->body && !s->body->fields.empty())
+
7628 WriteLine();
+
7629 }
+
7630
+
7631 // Generate struct body
+
7632 if (s->body)
+
7633 {
+
7634 for (const auto& field : s->body->fields)
+
7635 {
+
7636 WriteIndent();
+
7637 if (field->attributes && field->attributes->deprecated)
+
7638 Write("[[deprecated]] ");
+
7639 WriteLine(ConvertTypeName(*p->name, *field) + " " + *field->name + ";");
+
7640 }
+
7641 if (!s->body->fields.empty())
+
7642 WriteLine();
+
7643 }
+
7644
+
7645 // Generate struct FBE type property
+
7646 if (s->base && !s->base->empty() && (s->type == 0))
+
7647 WriteLineIndent("size_t fbe_type() const noexcept { return " + ConvertTypeName(*p->name, *s->base, false) + "::fbe_type(); }");
+
7648 else
+
7649 WriteLineIndent("size_t fbe_type() const noexcept { return " + std::to_string(s->type) + "; }");
+
7650
+
7651 // Generate struct default constructor
+
7652 bool first = true;
+
7653 WriteLine();
+
7654 WriteLineIndent(*s->name + "();");
+
7655
+
7656 // Generate struct initialization constructor
+
7657 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
7658 {
+
7659 first = true;
+
7660 size_t args = 0;
+
7661 if (s->base && !s->base->empty())
+
7662 ++args;
+
7663 if (s->body && !s->body->fields.empty())
+
7664 args += s->body->fields.size();
+
7665 WriteIndent(((args <= 1) ? "explicit " : "") + *s->name + "(");
+
7666 if (s->base && !s->base->empty())
+
7667 {
+
7668 Write("const " + ConvertTypeName(*p->name, *s->base, false) + "& base");
+
7669 first = false;
+
7670 }
+
7671 if (s->body)
+
7672 {
+
7673 for (const auto& field : s->body->fields)
+
7674 {
+
7675 Write(std::string(first ? "" : ", ") + ConvertTypeNameAsArgument(*p->name, *field) + " arg_" + *field->name);
+
7676 first = false;
+
7677 }
+
7678 }
+
7679 WriteLine(");");
+
7680 }
+
7681
+
7682 // Generate struct copy/mode constructor, destructor and assign operators
+
7683 WriteLineIndent(*s->name + "(const " + *s->name + "& other) = default;");
+
7684 WriteLineIndent(*s->name + "(" + *s->name + "&& other) = default;");
+
7685 WriteLineIndent("~" + *s->name + "() = default;");
+
7686 WriteLine();
+
7687 WriteLineIndent(*s->name + "& operator=(const " + *s->name + "& other) = default;");
+
7688 WriteLineIndent(*s->name + "& operator=(" + *s->name + "&& other) = default;");
+
7689
+
7690 // Generate struct compare operators
+
7691 WriteLine();
+
7692 WriteLineIndent("bool operator==(const " + *s->name + "& other) const noexcept;");
+
7693 WriteLineIndent("bool operator!=(const " + *s->name + "& other) const noexcept { return !operator==(other); }");
+
7694 WriteLineIndent("bool operator<(const " + *s->name + "& other) const noexcept;");
+
7695 WriteLineIndent("bool operator<=(const " + *s->name + "& other) const noexcept { return operator<(other) || operator==(other); }");
+
7696 WriteLineIndent("bool operator>(const " + *s->name + "& other) const noexcept { return !operator<=(other); }");
+
7697 WriteLineIndent("bool operator>=(const " + *s->name + "& other) const noexcept { return !operator<(other); }");
+
7698
+
7699 // Generate struct string convert
+
7700 WriteLine();
+
7701 WriteLineIndent("std::string string() const { std::stringstream ss; ss << *this; return ss.str(); }");
+
7702
+
7703 // Generate struct output stream operator
+
7704 WriteLine();
+
7705 WriteLineIndent("friend std::ostream& operator<<(std::ostream& stream, const " + *s->name + "& value);");
+
7706
+
7707 // Generate struct output stream operator
+
7708 if (Logging())
+
7709 {
+
7710 WriteLine();
+
7711 WriteLineIndent("#if defined(LOGGING_PROTOCOL)");
+
7712 WriteLineIndent("friend CppLogging::Record& operator<<(CppLogging::Record& record, const " + *s->name + "& value);");
+
7713 WriteLineIndent("#endif");
+
7714 }
+
7715
+
7716 // Generate struct swap methods
+
7717 WriteLine();
+
7718 WriteLineIndent("void swap(" + *s->name + "& other) noexcept;");
+
7719 WriteLineIndent("friend void swap(" + *s->name + "& value1, " + *s->name + "& value2) noexcept { value1.swap(value2); }");
+
7720
+
7721 // Generate struct end
+
7722 Indent(-1);
+
7723 WriteLineIndent("};");
+
7724
+
7725 // Generate namespace end
+
7726 WriteLine();
+
7727 WriteLineIndent("} // namespace " + *p->name);
+
7728
+
7729 // Generate struct formatter
+
7730 GenerateStructFormatter(p, s);
+
7731
+
7732 // Generate struct hash
+
7733 GenerateStructHash(p, s);
+
7734
+
7735 // Generate namespace begin
+
7736 WriteLine();
+
7737 WriteLineIndent("namespace " + *p->name + " {");
+
7738}
+
7739
+
7740void GeneratorCpp::GenerateStruct_Source(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s)
+
7741{
+
7742 WriteLine();
+
7743
+
7744 // Generate struct default constructor
+
7745 bool first = true;
+
7746 WriteLineIndent(*s->name + "::" + *s->name + "()");
+
7747 Indent(1);
+
7748 if (s->base && !s->base->empty())
+
7749 {
+
7750 WriteLineIndent(": " + ConvertTypeName(*p->name, *s->base, false) + "()");
+
7751 first = false;
+
7752 }
+
7753 if (s->body)
+
7754 {
+
7755 for (const auto& field : s->body->fields)
+
7756 {
+
7757 WriteLineIndent(std::string(first ? ": " : ", ") + *field->name + "(" + ((field->value || IsPrimitiveType(*field->type, field->optional)) ? ConvertDefault(*p->name, *field) : "") + ")");
+
7758 first = false;
+
7759 }
+
7760 }
+
7761 Indent(-1);
+
7762 WriteLineIndent("{}");
+
7763
+
7764 // Generate struct initialization constructor
+
7765 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
7766 {
+
7767 first = true;
+
7768 WriteLine();
+
7769 WriteIndent(*s->name + "::" + *s->name + "(");
+
7770 if (s->base && !s->base->empty())
+
7771 {
+
7772 Write("const " + ConvertTypeName(*p->name, *s->base, false) + "& base");
+
7773 first = false;
+
7774 }
+
7775 if (s->body)
+
7776 {
+
7777 for (const auto& field : s->body->fields)
+
7778 {
+
7779 Write(std::string(first ? "" : ", ") + ConvertTypeNameAsArgument(*p->name, *field) + " arg_" + *field->name);
+
7780 first = false;
+
7781 }
+
7782 }
+
7783 WriteLine(")");
+
7784 Indent(1);
+
7785 first = true;
+
7786 if (s->base && !s->base->empty())
+
7787 {
+
7788 WriteLineIndent(": " + ConvertTypeName(*p->name, *s->base, false) + "(base)");
+
7789 first = false;
+
7790 }
+
7791 if (s->body)
+
7792 {
+
7793 for (const auto& field : s->body->fields)
+
7794 {
+
7795 WriteLineIndent(std::string(first ? ": " : ", ") + *field->name + "(arg_" + *field->name + ")");
+
7796 first = false;
+
7797 }
+
7798 }
+
7799 Indent(-1);
+
7800 WriteLineIndent("{}");
+
7801 }
+
7802
+
7803 // Generate struct compare operators
+
7804 WriteLine();
+
7805 WriteLineIndent("bool " + *s->name + "::operator==(const " + *s->name + "& other) const noexcept");
+
7806 WriteLineIndent("{");
+
7807 Indent(1);
+
7808 WriteLineIndent("return (");
+
7809 Indent(1);
+
7810 first = true;
+
7811 if (s->base && !s->base->empty())
+
7812 {
+
7813 WriteLineIndent(ConvertTypeName(*p->name, *s->base, false) + "::operator==(other)");
+
7814 first = false;
+
7815 }
+
7816 if (s->body)
+
7817 {
+
7818 for (const auto& field : s->body->fields)
+
7819 {
+
7820 if (field->keys)
+
7821 {
+
7822 WriteLineIndent(std::string(first ? "(" : "&& (") + *field->name + " == other." + *field->name + ")");
+
7823 first = false;
+
7824 }
+
7825 }
+
7826 }
+
7827 if (!s->keys)
+
7828 {
+
7829 WriteLineIndent(std::string(first ? "true" : "&& true"));
+
7830 first = false;
+
7831 }
+
7832 WriteLineIndent(");");
+
7833 Indent(-1);
+
7834 Indent(-1);
+
7835 WriteLineIndent("}");
+
7836
+
7837 WriteLine();
+
7838 WriteLineIndent("bool " + *s->name + "::operator<(const " + *s->name + "& other) const noexcept");
+
7839 WriteLineIndent("{");
+
7840 Indent(1);
+
7841 if (s->base && !s->base->empty())
+
7842 {
+
7843 WriteLineIndent("if (" + ConvertTypeName(*p->name, *s->base, false) + "::operator<(other))");
+
7844 Indent(1);
+
7845 WriteLineIndent("return true;");
+
7846 Indent(-1);
+
7847 WriteLineIndent("if (other." + ConvertTypeName(*p->name, *s->base, false) + "::operator<(*this))");
+
7848 Indent(1);
+
7849 WriteLineIndent("return false;");
+
7850 Indent(-1);
+
7851 }
+
7852 if (s->body)
+
7853 {
+
7854 for (const auto& field : s->body->fields)
+
7855 {
+
7856 if (field->keys)
+
7857 {
+
7858 WriteLineIndent("if (" + *field->name + " < other." + *field->name + ")");
+
7859 Indent(1);
+
7860 WriteLineIndent("return true;");
+
7861 Indent(-1);
+
7862 WriteLineIndent("if (other." + *field->name + " < " + *field->name + ")");
+
7863 Indent(1);
+
7864 WriteLineIndent("return false;");
+
7865 Indent(-1);
+
7866 }
+
7867 }
+
7868 }
+
7869 WriteLineIndent("return false;");
+
7870 Indent(-1);
+
7871 WriteLineIndent("}");
+
7872
+
7873 // Generate struct swap method
+
7874 WriteLine();
+
7875 WriteLineIndent("void " + *s->name + "::swap(" + *s->name + "& other) noexcept");
+
7876 WriteLineIndent("{");
+
7877 Indent(1);
+
7878 WriteLineIndent("using std::swap;");
+
7879 if (s->base && !s->base->empty())
+
7880 WriteLineIndent(ConvertTypeName(*p->name, *s->base, false) + "::swap(other);");
+
7881 if (s->body)
+
7882 for (const auto& field : s->body->fields)
+
7883 WriteLineIndent("swap(" + *field->name + ", other." + *field->name + ");");
+
7884 Indent(-1);
+
7885 WriteLineIndent("}");
+
7886}
+
7887
+
7888void GeneratorCpp::GenerateStructOutputStream(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s)
+
7889{
+
7890 // Generate struct output stream operator begin
+
7891 WriteLine();
+
7892 WriteLineIndent("std::ostream& operator<<(std::ostream& stream, const " + *s->name + "& value)");
+
7893 WriteLineIndent("{");
+
7894 Indent(1);
+
7895
+
7896 // Generate struct output stream operator body
+
7897 WriteLineIndent("stream << \"" + *s->name + "(\";");
+
7898 bool first = true;
+
7899 if (s->base && !s->base->empty())
+
7900 {
+
7901 WriteLineIndent("stream << (const " + ConvertTypeName(*p->name, *s->base, false) + "&)value;");
+
7902 first = false;
+
7903 }
+
7904 if (s->body)
+
7905 {
+
7906 // Generate fields output stream operator calls
+
7907 for (const auto& field : s->body->fields)
+
7908 {
+
7909 if (field->attributes && field->attributes->hidden)
+
7910 WriteLineIndent("stream << \"" + std::string(first ? "" : ",") + *field->name + "=***\";");
+
7911 else if (field->array)
+
7912 {
+
7913 WriteLineIndent("{");
+
7914 Indent(1);
+
7915 WriteLineIndent("bool first = true;");
+
7916 WriteLineIndent("stream << \"" + std::string(first ? "" : ",") + *field->name + "=[" + std::to_string(field->N) + "][\"" + ";");
+
7917 WriteLineIndent("for (size_t i = 0; i < " + std::to_string(field->N) + "; ++i)");
+
7918 WriteLineIndent("{");
+
7919 Indent(1);
+
7920 WriteLineIndent(ConvertOutputStreamValue(*field->type, "value." + *field->name + "[i]", field->optional, true));
+
7921 WriteLineIndent("first = false;");
+
7922 Indent(-1);
+
7923 WriteLineIndent("}");
+
7924 WriteLineIndent("stream << \"]\";");
+
7925 Indent(-1);
+
7926 WriteLineIndent("}");
+
7927 }
+
7928 else if (field->vector)
+
7929 {
+
7930 WriteLineIndent("{");
+
7931 Indent(1);
+
7932 WriteLineIndent("bool first = true;");
+
7933 WriteLineIndent("stream << \"" + std::string(first ? "" : ",") + *field->name + "=[\" << " + "value." + *field->name + ".size()" + " << \"][\"" + ";");
+
7934 WriteLineIndent("for (const auto& it : value." + *field->name + ")");
+
7935 WriteLineIndent("{");
+
7936 Indent(1);
+
7937 WriteLineIndent(ConvertOutputStreamValue(*field->type, "it", field->optional, true));
+
7938 WriteLineIndent("first = false;");
+
7939 Indent(-1);
+
7940 WriteLineIndent("}");
+
7941 WriteLineIndent("stream << \"]\";");
+
7942 Indent(-1);
+
7943 WriteLineIndent("}");
+
7944 }
+
7945 else if (field->list)
+
7946 {
+
7947 WriteLineIndent("{");
+
7948 Indent(1);
+
7949 WriteLineIndent("bool first = true;");
+
7950 WriteLineIndent("stream << \"" + std::string(first ? "" : ",") + *field->name + "=[\" << " + "value." + *field->name + ".size()" + "<< \"]<\"" + ";");
+
7951 WriteLineIndent("for (const auto& it : value." + *field->name + ")");
+
7952 WriteLineIndent("{");
+
7953 Indent(1);
+
7954 WriteLineIndent(ConvertOutputStreamValue(*field->type, "it", field->optional, true));
+
7955 WriteLineIndent("first = false;");
+
7956 Indent(-1);
+
7957 WriteLineIndent("}");
+
7958 WriteLineIndent("stream << \">\";");
+
7959 Indent(-1);
+
7960 WriteLineIndent("}");
+
7961 }
+
7962 else if (field->set)
+
7963 {
+
7964 WriteLineIndent("{");
+
7965 Indent(1);
+
7966 WriteLineIndent("bool first = true;");
+
7967 WriteLineIndent("stream << \"" + std::string(first ? "" : ",") + *field->name + "=[\" << " + "value." + *field->name + ".size()" + "<< \"]{\"" + ";");
+
7968 WriteLineIndent("for (const auto& it : value." + *field->name + ")");
+
7969 WriteLineIndent("{");
+
7970 Indent(1);
+
7971 WriteLineIndent(ConvertOutputStreamValue(*field->type, "it", field->optional, true));
+
7972 WriteLineIndent("first = false;");
+
7973 Indent(-1);
+
7974 WriteLineIndent("}");
+
7975 WriteLineIndent("stream << \"}\";");
+
7976 Indent(-1);
+
7977 WriteLineIndent("}");
+
7978 }
+
7979 else if (field->map)
+
7980 {
+
7981 WriteLineIndent("{");
+
7982 Indent(1);
+
7983 WriteLineIndent("bool first = true;");
+
7984 WriteLineIndent("stream << \"" + std::string(first ? "" : ",") + *field->name + "=[\" << " + "value." + *field->name + ".size()" + "<< \"]<{\"" + ";");
+
7985 WriteLineIndent("for (const auto& it : value." + *field->name + ")");
+
7986 WriteLineIndent("{");
+
7987 Indent(1);
+
7988 WriteLineIndent(ConvertOutputStreamValue(*field->key, "it.first", false, true));
+
7989 WriteLineIndent("stream << \"->\";");
+
7990 WriteLineIndent(ConvertOutputStreamValue(*field->type, "it.second", field->optional, false));
+
7991 WriteLineIndent("first = false;");
+
7992 Indent(-1);
+
7993 WriteLineIndent("}");
+
7994 WriteLineIndent("stream << \"}>\";");
+
7995 Indent(-1);
+
7996 WriteLineIndent("}");
+
7997 }
+
7998 else if (field->hash)
+
7999 {
+
8000 WriteLineIndent("{");
+
8001 Indent(1);
+
8002 WriteLineIndent("bool first = true;");
+
8003 WriteLineIndent("stream << \"" + std::string(first ? "" : ",") + *field->name + "=[\" << " + "value." + *field->name + ".size()" + "<< \"][{\"" + ";");
+
8004 WriteLineIndent("for (const auto& it : value." + *field->name + ")");
+
8005 WriteLineIndent("{");
+
8006 Indent(1);
+
8007 WriteLineIndent(ConvertOutputStreamValue(*field->key, "it.first", false, true));
+
8008 WriteLineIndent("stream << \"->\";");
+
8009 WriteLineIndent(ConvertOutputStreamValue(*field->type, "it.second", field->optional, false));
+
8010 WriteLineIndent("first = false;");
+
8011 Indent(-1);
+
8012 WriteLineIndent("}");
+
8013 WriteLineIndent("stream << \"}]\";");
+
8014 Indent(-1);
+
8015 WriteLineIndent("}");
+
8016 }
+
8017 else
+
8018 WriteLineIndent("stream << \"" + std::string(first ? "" : ",") + *field->name + "=\"; " + ConvertOutputStreamValue(*field->type, "value." + *field->name, field->optional, false));
+
8019 first = false;
+
8020 }
+
8021 }
+
8022 WriteLineIndent("stream << \")\";");
+
8023 WriteLineIndent("return stream;");
+
8024
+
8025 // Generate struct output stream operator end
+
8026 Indent(-1);
+
8027 WriteLineIndent("}");
+
8028}
+
8029
+
8030void GeneratorCpp::GenerateStructLoggingStream(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s)
+
8031{
+
8032 // Generate struct logging stream operator begin
+
8033 WriteLine();
+
8034 WriteLineIndent("#if defined(LOGGING_PROTOCOL)");
+
8035 WriteLineIndent("CppLogging::Record& operator<<(CppLogging::Record& record, const " + *s->name + "& value)");
+
8036 WriteLineIndent("{");
+
8037 Indent(1);
+
8038
+
8039 // Generate struct output stream operator body
+
8040 WriteLineIndent("const size_t begin = record.StoreListBegin();");
+
8041 WriteLineIndent("record.StoreList(\"" + *s->name + "(\");");
+
8042 bool first = true;
+
8043 if (s->base && !s->base->empty())
+
8044 {
+
8045 WriteLineIndent("record.StoreList((const " + ConvertTypeName(*p->name, *s->base, false) + "&)value);");
+
8046 first = false;
+
8047 }
+
8048 if (s->body)
+
8049 {
+
8050 // Generate fields output stream operator calls
+
8051 for (const auto& field : s->body->fields)
+
8052 {
+
8053 if (field->attributes && field->attributes->hidden)
+
8054 WriteLineIndent("record.StoreList(\"" + std::string(first ? "" : ",") + *field->name + "=***\");");
+
8055 else if (field->array)
+
8056 {
+
8057 WriteLineIndent("{");
+
8058 Indent(1);
+
8059 WriteLineIndent("bool first = true;");
+
8060 WriteLineIndent("record.StoreList(\"" + std::string(first ? "" : ",") + *field->name + "=[" + std::to_string(field->N) + "][\");");
+
8061 WriteLineIndent("for (size_t i = 0; i < " + std::to_string(field->N) + "; ++i)");
+
8062 WriteLineIndent("{");
+
8063 Indent(1);
+
8064 WriteLineIndent(ConvertLoggingStreamValue(*field->type, "value." + *field->name + "[i]", field->optional, true));
+
8065 WriteLineIndent("first = false;");
+
8066 Indent(-1);
+
8067 WriteLineIndent("}");
+
8068 WriteLineIndent("record.StoreList(\"]\");");
+
8069 Indent(-1);
+
8070 WriteLineIndent("}");
+
8071 }
+
8072 else if (field->vector)
+
8073 {
+
8074 WriteLineIndent("{");
+
8075 Indent(1);
+
8076 WriteLineIndent("bool first = true;");
+
8077 WriteLineIndent("record.StoreList(\"" + std::string(first ? "" : ",") + *field->name + "=[\").StoreList(value." + *field->name + ".size()).StoreList(\"][\");");
+
8078 WriteLineIndent("for (const auto& it : value." + *field->name + ")");
+
8079 WriteLineIndent("{");
+
8080 Indent(1);
+
8081 WriteLineIndent(ConvertLoggingStreamValue(*field->type, "it", field->optional, true));
+
8082 WriteLineIndent("first = false;");
+
8083 Indent(-1);
+
8084 WriteLineIndent("}");
+
8085 WriteLineIndent("record.StoreList(\"]\");");
+
8086 Indent(-1);
+
8087 WriteLineIndent("}");
+
8088 }
+
8089 else if (field->list)
+
8090 {
+
8091 WriteLineIndent("{");
+
8092 Indent(1);
+
8093 WriteLineIndent("bool first = true;");
+
8094 WriteLineIndent("record.StoreList(\"" + std::string(first ? "" : ",") + *field->name + "=[\").StoreList(value." + *field->name + ".size()).StoreList(\"]<\");");
+
8095 WriteLineIndent("for (const auto& it : value." + *field->name + ")");
+
8096 WriteLineIndent("{");
+
8097 Indent(1);
+
8098 WriteLineIndent(ConvertLoggingStreamValue(*field->type, "it", field->optional, true));
+
8099 WriteLineIndent("first = false;");
+
8100 Indent(-1);
+
8101 WriteLineIndent("}");
+
8102 WriteLineIndent("record.StoreList(\">\");");
+
8103 Indent(-1);
+
8104 WriteLineIndent("}");
+
8105 }
+
8106 else if (field->set)
+
8107 {
+
8108 WriteLineIndent("{");
+
8109 Indent(1);
+
8110 WriteLineIndent("bool first = true;");
+
8111 WriteLineIndent("record.StoreList(\"" + std::string(first ? "" : ",") + *field->name + "=[\").StoreList(value." + *field->name + ".size()).StoreList(\"]{\");");
+
8112 WriteLineIndent("for (const auto& it : value." + *field->name + ")");
+
8113 WriteLineIndent("{");
+
8114 Indent(1);
+
8115 WriteLineIndent(ConvertLoggingStreamValue(*field->type, "it", field->optional, true));
+
8116 WriteLineIndent("first = false;");
+
8117 Indent(-1);
+
8118 WriteLineIndent("}");
+
8119 WriteLineIndent("record.StoreList(\"}\");");
+
8120 Indent(-1);
+
8121 WriteLineIndent("}");
+
8122 }
+
8123 else if (field->map)
+
8124 {
+
8125 WriteLineIndent("{");
+
8126 Indent(1);
+
8127 WriteLineIndent("bool first = true;");
+
8128 WriteLineIndent("record.StoreList(\"" + std::string(first ? "" : ",") + *field->name + "=[\").StoreList(value." + *field->name + ".size()).StoreList(\"]<{\");");
+
8129 WriteLineIndent("for (const auto& it : value." + *field->name + ")");
+
8130 WriteLineIndent("{");
+
8131 Indent(1);
+
8132 WriteLineIndent(ConvertLoggingStreamValue(*field->key, "it.first", false, true));
+
8133 WriteLineIndent("record.StoreList(\"->\");");
+
8134 WriteLineIndent(ConvertLoggingStreamValue(*field->type, "it.second", field->optional, false));
+
8135 WriteLineIndent("first = false;");
+
8136 Indent(-1);
+
8137 WriteLineIndent("}");
+
8138 WriteLineIndent("record.StoreList(\"}>\");");
+
8139 Indent(-1);
+
8140 WriteLineIndent("}");
+
8141 }
+
8142 else if (field->hash)
+
8143 {
+
8144 WriteLineIndent("{");
+
8145 Indent(1);
+
8146 WriteLineIndent("bool first = true;");
+
8147 WriteLineIndent("record.StoreList(\"" + std::string(first ? "" : ",") + *field->name + "=[\").StoreList(value." + *field->name + ".size()).StoreList(\"][{\");");
+
8148 WriteLineIndent("for (const auto& it : value." + *field->name + ")");
+
8149 WriteLineIndent("{");
+
8150 Indent(1);
+
8151 WriteLineIndent(ConvertLoggingStreamValue(*field->key, "it.first", false, true));
+
8152 WriteLineIndent("record.StoreList(\"->\");");
+
8153 WriteLineIndent(ConvertLoggingStreamValue(*field->type, "it.second", field->optional, false));
+
8154 WriteLineIndent("first = false;");
+
8155 Indent(-1);
+
8156 WriteLineIndent("}");
+
8157 WriteLineIndent("record.StoreList(\"}]\");");
+
8158 Indent(-1);
+
8159 WriteLineIndent("}");
+
8160 }
+
8161 else
+
8162 WriteLineIndent("record.StoreList(\"" + std::string(first ? "" : ",") + *field->name + "=\"); " + ConvertLoggingStreamValue(*field->type, "value." + *field->name, field->optional, false));
+
8163 first = false;
+
8164 }
+
8165 }
+
8166 WriteLineIndent("record.StoreList(\")\");");
+
8167 WriteLineIndent("return record.StoreListEnd(begin);");
+
8168
+
8169 // Generate struct logging stream operator end
+
8170 Indent(-1);
+
8171 WriteLineIndent("}");
+
8172 WriteLineIndent("#endif");
+
8173}
+
8174
+
8175void GeneratorCpp::GenerateStructFormatter(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s)
+
8176{
+
8177 // Generate struct formatter
+
8178 WriteLine();
+
8179 WriteLineIndent("#if defined(FMT_VERSION) && (FMT_VERSION >= 90000)");
+
8180 WriteLineIndent("template <> struct fmt::formatter<" + *p->name + "::" + *s->name + "> : ostream_formatter {};");
+
8181 WriteLineIndent("#endif");
+
8182}
+
8183
+
8184void GeneratorCpp::GenerateStructHash(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s)
+
8185{
+
8186 // Generate struct hash
+
8187 WriteLine();
+
8188 WriteLineIndent("template<>");
+
8189 WriteLineIndent("struct std::hash<" + *p->name + "::" + *s->name + ">");
+
8190 WriteLineIndent("{");
+
8191 Indent(1);
+
8192 WriteLineIndent("typedef " + *p->name + "::" + *s->name + " argument_type;");
+
8193 WriteLineIndent("typedef size_t result_type;");
+
8194 WriteLine();
+
8195 WriteLineIndent("result_type operator() (const argument_type& value) const");
+
8196 WriteLineIndent("{");
+
8197 Indent(1);
+
8198 WriteLineIndent("result_type result = 17;");
+
8199 if (s->base && !s->base->empty())
+
8200 WriteLineIndent("result = result * 31 + std::hash<" + ConvertTypeName(*p->name, *s->base, false) + ">()(value);");
+
8201 if (s->body)
+
8202 for (const auto& field : s->body->fields)
+
8203 if (field->keys)
+
8204 WriteLineIndent("result = result * 31 + std::hash<decltype(value." + *field->name + ")>()(value." + *field->name + ");");
+
8205 WriteLineIndent("return result;");
+
8206 Indent(-1);
+
8207 WriteLineIndent("}");
+
8208 Indent(-1);
+
8209 WriteLineIndent("};");
+
8210}
+
8211
+
8212void GeneratorCpp::GenerateStructJson(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s)
+
8213{
+
8214 std::string struct_name = "::" + *p->name + "::" + *s->name;
+
8215
+
8216 // Generate to_json() function
+
8217 WriteLine();
+
8218 WriteLineIndent("template <class TWriter>");
+
8219 WriteLineIndent("struct ValueWriter<TWriter, " + struct_name + ">");
+
8220 WriteLineIndent("{");
+
8221 Indent(1);
+
8222 WriteLineIndent("static bool to_json(TWriter& writer, const " + struct_name + "& value, bool scope = true)");
+
8223 WriteLineIndent("{");
+
8224 Indent(1);
+
8225 WriteLineIndent("if (scope)");
+
8226 Indent(1);
+
8227 WriteLineIndent("if (!writer.StartObject())");
+
8228 Indent(1);
+
8229 WriteLineIndent("return false;");
+
8230 Indent(-1);
+
8231 Indent(-1);
+
8232 if (s->base && !s->base->empty())
+
8233 {
+
8234 WriteLineIndent("if (!FBE::JSON::to_json(writer, (const " + ConvertTypeName(*p->name, *s->base, false) + "&)value, false))");
+
8235 Indent(1);
+
8236 WriteLineIndent("return false;");
+
8237 Indent(-1);
+
8238 }
+
8239 if (s->body)
+
8240 {
+
8241 for (const auto& field : s->body->fields)
+
8242 {
+
8243 WriteLineIndent("if (!FBE::JSON::to_json_key(writer, \"" + *field->name + "\") || !FBE::JSON::to_json(writer, value." + *field->name + ", true))");
+
8244 Indent(1);
+
8245 WriteLineIndent("return false;");
+
8246 Indent(-1);
+
8247 }
+
8248 }
+
8249 WriteLineIndent("if (scope)");
+
8250 Indent(1);
+
8251 WriteLineIndent("if (!writer.EndObject())");
+
8252 Indent(1);
+
8253 WriteLineIndent("return false;");
+
8254 Indent(-1);
+
8255 Indent(-1);
+
8256 WriteLineIndent("return true;");
+
8257 Indent(-1);
+
8258 WriteLineIndent("}");
+
8259 Indent(-1);
+
8260 WriteLineIndent("};");
+
8261
+
8262 // Generate from_json() function
+
8263 WriteLine();
+
8264 WriteLineIndent("template <class TJson>");
+
8265 WriteLineIndent("struct ValueReader<TJson, " + struct_name + ">");
+
8266 WriteLineIndent("{");
+
8267 Indent(1);
+
8268 WriteLineIndent("static bool from_json(const TJson& json, " + struct_name + "& value, const char* key = nullptr)");
+
8269 WriteLineIndent("{");
+
8270 Indent(1);
+
8271 WriteLineIndent("if (key != nullptr)");
+
8272 Indent(1);
+
8273 WriteLineIndent("return FBE::JSON::from_json_child(json, value, key);");
+
8274 Indent(-1);
+
8275 WriteLineIndent("bool result = true;");
+
8276 if (s->base && !s->base->empty())
+
8277 WriteLineIndent("result &= FBE::JSON::from_json(json, (" + ConvertTypeName(*p->name, *s->base, false) + "&)value);");
+
8278 if (s->body)
+
8279 for (const auto& field : s->body->fields)
+
8280 WriteLineIndent("result &= FBE::JSON::from_json(json, value." + *field->name + ", \"" + *field->name + "\");");
+
8281 WriteLineIndent("return result;");
+
8282 Indent(-1);
+
8283 WriteLineIndent("}");
+
8284 Indent(-1);
+
8285 WriteLineIndent("};");
+
8286}
+
8287
+
8288void GeneratorCpp::GenerateStructFieldModel_Header(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s)
+
8289{
+
8290 std::string struct_name = "::" + *p->name + "::" + *s->name;
+
8291
+
8292 // Generate struct field model begin
+
8293 WriteLine();
+
8294 WriteLineIndent("// Fast Binary Encoding " + struct_name + " field model");
+
8295 WriteLineIndent("template <>");
+
8296 WriteLineIndent("class FieldModel<" + struct_name + ">");
+
8297 WriteLineIndent("{");
+
8298 WriteLineIndent("public:");
+
8299 Indent(1);
+
8300
+
8301 // Generate struct field model constructor
+
8302 WriteLineIndent("FieldModel(FBEBuffer& buffer, size_t offset) noexcept;");
+
8303
+
8304 // Generate struct field model FBE methods
+
8305 WriteLine();
+
8306 WriteLineIndent("// Get the field offset");
+
8307 WriteLineIndent("size_t fbe_offset() const noexcept { return _offset; }");
+
8308 WriteLineIndent("// Get the field size");
+
8309 WriteLineIndent("size_t fbe_size() const noexcept { return 4; }");
+
8310 WriteLineIndent("// Get the field body size");
+
8311 WriteLineIndent("size_t fbe_body() const noexcept;");
+
8312 WriteLineIndent("// Get the field extra size");
+
8313 WriteLineIndent("size_t fbe_extra() const noexcept;");
+
8314 WriteLineIndent("// Get the field type");
+
8315 if (s->base && !s->base->empty() && (s->type == 0))
+
8316 WriteLineIndent("static constexpr size_t fbe_type() noexcept { return FieldModel<" + ConvertTypeName(*p->name, *s->base, false) + ">::fbe_type(); }");
+
8317 else
+
8318 WriteLineIndent("static constexpr size_t fbe_type() noexcept { return " + std::to_string(s->type) + "; }");
+
8319 WriteLine();
+
8320 WriteLineIndent("// Shift the current field offset");
+
8321 WriteLineIndent("void fbe_shift(size_t size) noexcept { _offset += size; }");
+
8322 WriteLineIndent("// Unshift the current field offset");
+
8323 WriteLineIndent("void fbe_unshift(size_t size) noexcept { _offset -= size; }");
+
8324
+
8325 // Generate struct field model verify(), verify_fields() methods
+
8326 WriteLine();
+
8327 WriteLineIndent("// Check if the struct value is valid");
+
8328 WriteLineIndent("bool verify(bool fbe_verify_type = true) const noexcept;");
+
8329 WriteLineIndent("// Check if the struct fields are valid");
+
8330 WriteLineIndent("bool verify_fields(size_t fbe_struct_size) const noexcept;");
+
8331
+
8332 // Generate struct field model get_begin(), get_end() methods
+
8333 WriteLine();
+
8334 WriteLineIndent("// Get the struct value (begin phase)");
+
8335 WriteLineIndent("size_t get_begin() const noexcept;");
+
8336 WriteLineIndent("// Get the struct value (end phase)");
+
8337 WriteLineIndent("void get_end(size_t fbe_begin) const noexcept;");
+
8338
+
8339 // Generate struct field model get(), get_fields() methods
+
8340 WriteLine();
+
8341 WriteLineIndent("// Get the struct value");
+
8342 WriteLineIndent("void get(" + struct_name + "& fbe_value) const noexcept;");
+
8343 WriteLineIndent("// Get the struct fields values");
+
8344 WriteLineIndent("void get_fields(" + struct_name + "& fbe_value, size_t fbe_struct_size) const noexcept;");
+
8345
+
8346 // Generate struct field model set_begin(), set_end() methods
+
8347 WriteLine();
+
8348 WriteLineIndent("// Set the struct value (begin phase)");
+
8349 WriteLineIndent("size_t set_begin();");
+
8350 WriteLineIndent("// Set the struct value (end phase)");
+
8351 WriteLineIndent("void set_end(size_t fbe_begin);");
+
8352
+
8353 // Generate struct field model set(), set_fields() methods
+
8354 WriteLine();
+
8355 WriteLineIndent("// Set the struct value");
+
8356 WriteLineIndent("void set(const " + struct_name + "& fbe_value) noexcept;");
+
8357 WriteLineIndent("// Set the struct fields values");
+
8358 WriteLineIndent("void set_fields(const " + struct_name + "& fbe_value) noexcept;");
+
8359
+
8360 // Generate struct field model buffer & offset
+
8361 Indent(-1);
+
8362 WriteLine();
+
8363 WriteLineIndent("private:");
+
8364 Indent(1);
+
8365 WriteLineIndent("FBEBuffer& _buffer;");
+
8366 WriteLineIndent("size_t _offset;");
+
8367
+
8368 // Generate struct field model accessors
+
8369 Indent(-1);
+
8370 WriteLine();
+
8371 WriteLineIndent("public:");
+
8372 Indent(1);
+
8373 if (s->base && !s->base->empty())
+
8374 WriteLineIndent("FieldModel<" + ConvertTypeName(*p->name, *s->base, false) + "> parent;");
+
8375 if (s->body)
+
8376 {
+
8377 for (const auto& field : s->body->fields)
+
8378 {
+
8379 if (field->array)
+
8380 WriteLineIndent("FieldModelArray<" + ConvertTypeName(*p->name, *field->type, field->optional) + ", " + std::to_string(field->N) + "> " + *field->name + ";");
+
8381 else if (field->vector || field->list || field->set)
+
8382 WriteLineIndent("FieldModelVector<" + ConvertTypeName(*p->name, *field->type, field->optional) + "> " + *field->name + ";");
+
8383 else if (field->map || field->hash)
+
8384 WriteLineIndent("FieldModelMap<" + ConvertTypeName(*p->name, *field->key, false) + ", " + ConvertTypeName(*p->name, *field->type, field->optional) + "> " + *field->name + ";");
+
8385 else
+
8386 WriteLineIndent("FieldModel<" + ConvertTypeName(*p->name, *field->type, field->optional) + "> " + *field->name + ";");
+
8387 }
+
8388 }
+
8389
+
8390 // Generate struct field model end
+
8391 Indent(-1);
+
8392 WriteLineIndent("};");
+
8393}
+
8394
+
8395void GeneratorCpp::GenerateStructFieldModel_Source(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s)
+
8396{
+
8397 std::string struct_name = "::" + *p->name + "::" + *s->name;
+
8398 std::string model_name = "FieldModel<" + struct_name + ">";
+
8399
+
8400 // Generate struct field model constructor
+
8401 WriteLine();
+
8402 WriteLineIndent(model_name + "::FieldModel(FBEBuffer& buffer, size_t offset) noexcept : _buffer(buffer), _offset(offset)");
+
8403 Indent(1);
+
8404 std::string prev_offset("4");
+
8405 std::string prev_size("4");
+
8406 if (s->base && !s->base->empty())
+
8407 {
+
8408 WriteLineIndent(", parent(buffer, " + prev_offset + " + " + prev_size + ")");
+
8409 prev_offset = "parent.fbe_offset()";
+
8410 prev_size = "parent.fbe_body() - 4 - 4";
+
8411 }
+
8412 if (s->body)
+
8413 {
+
8414 for (const auto& field : s->body->fields)
+
8415 {
+
8416 WriteLineIndent(", " + *field->name + "(buffer, " + prev_offset + " + " + prev_size + ")");
+
8417 prev_offset = *field->name + ".fbe_offset()";
+
8418 prev_size = *field->name + ".fbe_size()";
+
8419 }
+
8420 }
+
8421 Indent(-1);
+
8422 WriteLineIndent("{}");
+
8423 WriteLine();
+
8424
+
8425 // Generate struct field model FBE methods
+
8426 WriteLineIndent("size_t " + model_name + "::fbe_body() const noexcept");
+
8427 WriteLineIndent("{");
+
8428 Indent(1);
+
8429 WriteLineIndent("size_t fbe_result = 4 + 4");
+
8430 Indent(1);
+
8431 if (s->base && !s->base->empty())
+
8432 WriteLineIndent("+ parent.fbe_body() - 4 - 4");
+
8433 if (s->body)
+
8434 for (const auto& field : s->body->fields)
+
8435 WriteLineIndent("+ " + *field->name + ".fbe_size()");
+
8436 WriteLineIndent(";");
+
8437 Indent(-1);
+
8438 WriteLineIndent("return fbe_result;");
+
8439 Indent(-1);
+
8440 WriteLineIndent("}");
+
8441 WriteLine();
+
8442 WriteLineIndent("size_t " + model_name + "::fbe_extra() const noexcept");
+
8443 WriteLineIndent("{");
+
8444 Indent(1);
+
8445 WriteLineIndent("if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size())");
+
8446 Indent(1);
+
8447 WriteLineIndent("return 0;");
+
8448 Indent(-1);
+
8449 WriteLine();
+
8450 WriteLineIndent("uint32_t fbe_struct_offset = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset()));");
+
8451 WriteLineIndent("if ((fbe_struct_offset == 0) || ((_buffer.offset() + fbe_struct_offset + 4) > _buffer.size()))");
+
8452 Indent(1);
+
8453 WriteLineIndent("return 0;");
+
8454 Indent(-1);
+
8455 WriteLine();
+
8456 WriteLineIndent("_buffer.shift(fbe_struct_offset);");
+
8457 WriteLine();
+
8458 WriteLineIndent("size_t fbe_result = fbe_body()");
+
8459 Indent(1);
+
8460 if (s->base && !s->base->empty())
+
8461 WriteLineIndent("+ parent.fbe_extra()");
+
8462 if (s->body)
+
8463 for (const auto& field : s->body->fields)
+
8464 WriteLineIndent("+ " + *field->name + ".fbe_extra()");
+
8465 WriteLineIndent(";");
+
8466 Indent(-1);
+
8467 WriteLine();
+
8468 WriteLineIndent("_buffer.unshift(fbe_struct_offset);");
+
8469 WriteLine();
+
8470 WriteLineIndent("return fbe_result;");
+
8471 Indent(-1);
+
8472 WriteLineIndent("}");
+
8473 WriteLine();
+
8474
+
8475 // Generate struct field model verify() method
+
8476 WriteLineIndent("bool " + model_name + "::verify(bool fbe_verify_type) const noexcept");
+
8477 WriteLineIndent("{");
+
8478 Indent(1);
+
8479 WriteLineIndent("if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size())");
+
8480 Indent(1);
+
8481 WriteLineIndent("return true;");
+
8482 Indent(-1);
+
8483 WriteLine();
+
8484 WriteLineIndent("uint32_t fbe_struct_offset = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset()));");
+
8485 WriteLineIndent("if ((fbe_struct_offset == 0) || ((_buffer.offset() + fbe_struct_offset + 4 + 4) > _buffer.size()))");
+
8486 Indent(1);
+
8487 WriteLineIndent("return false;");
+
8488 Indent(-1);
+
8489 WriteLine();
+
8490 WriteLineIndent("uint32_t fbe_struct_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_struct_offset));");
+
8491 WriteLineIndent("if (fbe_struct_size < (4 + 4))");
+
8492 Indent(1);
+
8493 WriteLineIndent("return false;");
+
8494 Indent(-1);
+
8495 WriteLine();
+
8496 WriteLineIndent("uint32_t fbe_struct_type = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_struct_offset + 4));");
+
8497 WriteLineIndent("if (fbe_verify_type && (fbe_struct_type != fbe_type()))");
+
8498 Indent(1);
+
8499 WriteLineIndent("return false;");
+
8500 Indent(-1);
+
8501 WriteLine();
+
8502 WriteLineIndent("_buffer.shift(fbe_struct_offset);");
+
8503 WriteLineIndent("bool fbe_result = verify_fields(fbe_struct_size);");
+
8504 WriteLineIndent("_buffer.unshift(fbe_struct_offset);");
+
8505 WriteLineIndent("return fbe_result;");
+
8506 Indent(-1);
+
8507 WriteLineIndent("}");
+
8508 WriteLine();
+
8509
+
8510 // Generate struct field model verify_fields() method
+
8511 WriteLineIndent("bool " + model_name + "::verify_fields(size_t fbe_struct_size) const noexcept");
+
8512 WriteLineIndent("{");
+
8513 Indent(1);
+
8514 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
8515 {
+
8516 WriteLineIndent("size_t fbe_current_size = 4 + 4;");
+
8517 if (s->base && !s->base->empty())
+
8518 {
+
8519 WriteLine();
+
8520 WriteLineIndent("if ((fbe_current_size + parent.fbe_body() - 4 - 4) > fbe_struct_size)");
+
8521 Indent(1);
+
8522 WriteLineIndent("return true;");
+
8523 Indent(-1);
+
8524 WriteLineIndent("if (!parent.verify_fields(fbe_struct_size))");
+
8525 Indent(1);
+
8526 WriteLineIndent("return false;");
+
8527 Indent(-1);
+
8528 WriteLineIndent("fbe_current_size += parent.fbe_body() - 4 - 4;");
+
8529 }
+
8530 if (s->body)
+
8531 {
+
8532 for (const auto& field : s->body->fields)
+
8533 {
+
8534 WriteLine();
+
8535 WriteLineIndent("if ((fbe_current_size + " + *field->name + ".fbe_size()) > fbe_struct_size)");
+
8536 Indent(1);
+
8537 WriteLineIndent("return true;");
+
8538 Indent(-1);
+
8539 WriteLineIndent("if (!" + *field->name + ".verify())");
+
8540 Indent(1);
+
8541 WriteLineIndent("return false;");
+
8542 Indent(-1);
+
8543 WriteLineIndent("fbe_current_size += " + *field->name + ".fbe_size();");
+
8544 }
+
8545 }
+
8546 WriteLine();
+
8547 }
+
8548 WriteLineIndent("return true;");
+
8549 Indent(-1);
+
8550 WriteLineIndent("}");
+
8551 WriteLine();
+
8552
+
8553 // Generate struct field model get_begin() method
+
8554 WriteLineIndent("size_t " + model_name + "::get_begin() const noexcept");
+
8555 WriteLineIndent("{");
+
8556 Indent(1);
+
8557 WriteLineIndent("if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size())");
+
8558 Indent(1);
+
8559 WriteLineIndent("return 0;");
+
8560 Indent(-1);
+
8561 WriteLine();
+
8562 WriteLineIndent("uint32_t fbe_struct_offset = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset()));");
+
8563 WriteLineIndent("assert(((fbe_struct_offset > 0) && ((_buffer.offset() + fbe_struct_offset + 4 + 4) <= _buffer.size())) && \"Model is broken!\");");
+
8564 WriteLineIndent("if ((fbe_struct_offset == 0) || ((_buffer.offset() + fbe_struct_offset + 4 + 4) > _buffer.size()))");
+
8565 Indent(1);
+
8566 WriteLineIndent("return 0;");
+
8567 Indent(-1);
+
8568 WriteLine();
+
8569 WriteLineIndent("uint32_t fbe_struct_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_struct_offset));");
+
8570 WriteLineIndent("assert((fbe_struct_size >= (4 + 4)) && \"Model is broken!\");");
+
8571 WriteLineIndent("if (fbe_struct_size < (4 + 4))");
+
8572 Indent(1);
+
8573 WriteLineIndent("return 0;");
+
8574 Indent(-1);
+
8575 WriteLine();
+
8576 WriteLineIndent("_buffer.shift(fbe_struct_offset);");
+
8577 WriteLineIndent("return fbe_struct_offset;");
+
8578 Indent(-1);
+
8579 WriteLineIndent("}");
+
8580 WriteLine();
+
8581
+
8582 // Generate struct field model get_end() method
+
8583 WriteLineIndent("void " + model_name + "::get_end(size_t fbe_begin) const noexcept");
+
8584 WriteLineIndent("{");
+
8585 Indent(1);
+
8586 WriteLineIndent("_buffer.unshift(fbe_begin);");
+
8587 Indent(-1);
+
8588 WriteLineIndent("}");
+
8589 WriteLine();
+
8590
+
8591 // Generate struct field model get() method
+
8592 WriteLineIndent("void " + model_name + "::get(" + struct_name + "& fbe_value) const noexcept");
+
8593 WriteLineIndent("{");
+
8594 Indent(1);
+
8595 WriteLineIndent("size_t fbe_begin = get_begin();");
+
8596 WriteLineIndent("if (fbe_begin == 0)");
+
8597 Indent(1);
+
8598 WriteLineIndent("return;");
+
8599 Indent(-1);
+
8600 WriteLine();
+
8601 WriteLineIndent("uint32_t fbe_struct_size = *((const uint32_t*)(_buffer.data() + _buffer.offset()));");
+
8602 WriteLineIndent("get_fields(fbe_value, fbe_struct_size);");
+
8603 WriteLineIndent("get_end(fbe_begin);");
+
8604 Indent(-1);
+
8605 WriteLineIndent("}");
+
8606 WriteLine();
+
8607
+
8608 // Generate struct field model get_fields() method
+
8609 WriteLineIndent("void " + model_name + "::get_fields(" + struct_name + "& fbe_value, size_t fbe_struct_size) const noexcept");
+
8610 WriteLineIndent("{");
+
8611 Indent(1);
+
8612 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
8613 {
+
8614 WriteLineIndent("size_t fbe_current_size = 4 + 4;");
+
8615 if (s->base && !s->base->empty())
+
8616 {
+
8617 WriteLine();
+
8618 WriteLineIndent("if ((fbe_current_size + parent.fbe_body() - 4 - 4) <= fbe_struct_size)");
+
8619 Indent(1);
+
8620 WriteLineIndent("parent.get_fields(fbe_value, fbe_struct_size);");
+
8621 Indent(-1);
+
8622 WriteLineIndent("fbe_current_size += parent.fbe_body() - 4 - 4;");
+
8623 }
+
8624 if (s->body)
+
8625 {
+
8626 for (const auto& field : s->body->fields)
+
8627 {
+
8628 WriteLine();
+
8629 WriteLineIndent("if ((fbe_current_size + " + *field->name + ".fbe_size()) <= fbe_struct_size)");
+
8630 Indent(1);
+
8631 WriteLineIndent(*field->name + ".get(fbe_value." + *field->name + (field->value ? (", " + ConvertConstant(*field->type, *field->value, field->optional)) : "") +");");
+
8632 Indent(-1);
+
8633 WriteLineIndent("else");
+
8634 Indent(1);
+
8635 if (field->array)
+
8636 {
+
8637 // Do nothing here...
+
8638 }
+
8639 else if (field->vector || field->list || field->set || field->map || field->hash || ((*field->type == "bytes") && !field->optional))
+
8640 WriteLineIndent("fbe_value." + *field->name + ".clear();");
+
8641 else
+
8642 WriteLineIndent("fbe_value." + *field->name + " = " + ConvertDefault(*p->name, *field) + ";");
+
8643 Indent(-1);
+
8644 WriteLineIndent("fbe_current_size += " + *field->name + ".fbe_size();");
+
8645 }
+
8646 }
+
8647 }
+
8648 Indent(-1);
+
8649 WriteLineIndent("}");
+
8650 WriteLine();
+
8651
+
8652 // Generate struct field model set_begin() method
+
8653 WriteLineIndent("size_t " + model_name + "::set_begin()");
+
8654 WriteLineIndent("{");
+
8655 Indent(1);
+
8656 WriteLineIndent("assert(((_buffer.offset() + fbe_offset() + fbe_size()) <= _buffer.size()) && \"Model is broken!\");");
+
8657 WriteLineIndent("if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size())");
+
8658 Indent(1);
+
8659 WriteLineIndent("return 0;");
+
8660 Indent(-1);
+
8661 WriteLine();
+
8662 WriteLineIndent("uint32_t fbe_struct_size = (uint32_t)fbe_body();");
+
8663 WriteLineIndent("uint32_t fbe_struct_offset = (uint32_t)(_buffer.allocate(fbe_struct_size) - _buffer.offset());");
+
8664 WriteLineIndent("assert(((fbe_struct_offset > 0) && ((_buffer.offset() + fbe_struct_offset + fbe_struct_size) <= _buffer.size())) && \"Model is broken!\");");
+
8665 WriteLineIndent("if ((fbe_struct_offset == 0) || ((_buffer.offset() + fbe_struct_offset + fbe_struct_size) > _buffer.size()))");
+
8666 Indent(1);
+
8667 WriteLineIndent("return 0;");
+
8668 Indent(-1);
+
8669 WriteLine();
+
8670 WriteLineIndent("*((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())) = fbe_struct_offset;");
+
8671 WriteLineIndent("*((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_struct_offset)) = fbe_struct_size;");
+
8672 WriteLineIndent("*((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_struct_offset + 4)) = (uint32_t)fbe_type();");
+
8673 WriteLine();
+
8674 WriteLineIndent("_buffer.shift(fbe_struct_offset);");
+
8675 WriteLineIndent("return fbe_struct_offset;");
+
8676 Indent(-1);
+
8677 WriteLineIndent("}");
+
8678 WriteLine();
+
8679
+
8680 // Generate struct field model set_end() method
+
8681 WriteLineIndent("void " + model_name + "::set_end(size_t fbe_begin)");
+
8682 WriteLineIndent("{");
+
8683 Indent(1);
+
8684 WriteLineIndent("_buffer.unshift(fbe_begin);");
+
8685 Indent(-1);
+
8686 WriteLineIndent("}");
+
8687 WriteLine();
+
8688
+
8689 // Generate struct field model set() method
+
8690 WriteLineIndent("void " + model_name + "::set(const " + struct_name + "& fbe_value) noexcept");
+
8691 WriteLineIndent("{");
+
8692 Indent(1);
+
8693 WriteLineIndent("size_t fbe_begin = set_begin();");
+
8694 WriteLineIndent("if (fbe_begin == 0)");
+
8695 Indent(1);
+
8696 WriteLineIndent("return;");
+
8697 Indent(-1);
+
8698 WriteLine();
+
8699 WriteLineIndent("set_fields(fbe_value);");
+
8700 WriteLineIndent("set_end(fbe_begin);");
+
8701 Indent(-1);
+
8702 WriteLineIndent("}");
+
8703 WriteLine();
+
8704
+
8705 // Generate struct field model set_fields() method
+
8706 WriteLineIndent("void " + model_name + "::set_fields(const " + struct_name + "& fbe_value) noexcept");
+
8707 WriteLineIndent("{");
+
8708 Indent(1);
+
8709 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
8710 {
+
8711 if (s->base && !s->base->empty())
+
8712 WriteLineIndent("parent.set_fields(fbe_value);");
+
8713 if (s->body)
+
8714 for (const auto& field : s->body->fields)
+
8715 WriteLineIndent(*field->name + ".set(fbe_value." + *field->name + ");");
+
8716 }
+
8717 Indent(-1);
+
8718 WriteLineIndent("}");
+
8719}
+
8720
+
8721void GeneratorCpp::GenerateStructModel_Header(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s)
+
8722{
+
8723 // Generate namespace begin
+
8724 WriteLine();
+
8725 WriteLineIndent("namespace " + *p->name + " {");
+
8726
+
8727 std::string struct_name = "::" + *p->name + "::" + *s->name;
+
8728
+
8729 // Generate struct model begin
+
8730 WriteLine();
+
8731 WriteLineIndent("// Fast Binary Encoding " + *s->name + " model");
+
8732 WriteLineIndent("class " + *s->name + "Model : public FBE::Model");
+
8733 WriteLineIndent("{");
+
8734 WriteLineIndent("public:");
+
8735 Indent(1);
+
8736
+
8737 // Generate struct model constructor
+
8738 WriteLineIndent(*s->name + "Model() : model(this->buffer(), 4) {}");
+
8739 WriteLineIndent(*s->name + "Model(const std::shared_ptr<FBEBuffer>& buffer) : FBE::Model(buffer), model(this->buffer(), 4) {}");
+
8740
+
8741 // Generate struct model FBE methods
+
8742 WriteLine();
+
8743 WriteLineIndent("// Get the model size");
+
8744 WriteLineIndent("size_t fbe_size() const noexcept { return model.fbe_size() + model.fbe_extra(); }");
+
8745 WriteLineIndent("// Get the model type");
+
8746 WriteLineIndent("static constexpr size_t fbe_type() noexcept { return FieldModel<" + struct_name + ">::fbe_type(); }");
+
8747
+
8748 // Generate struct model verify() method
+
8749 WriteLine();
+
8750 WriteLineIndent("// Check if the struct value is valid");
+
8751 WriteLineIndent("bool verify();");
+
8752
+
8753 // Generate struct model create_begin(), create_end() methods
+
8754 WriteLine();
+
8755 WriteLineIndent("// Create a new model (begin phase)");
+
8756 WriteLineIndent("size_t create_begin();");
+
8757 WriteLineIndent("// Create a new model (end phase)");
+
8758 WriteLineIndent("size_t create_end(size_t fbe_begin);");
+
8759
+
8760 // Generate struct model serialize(), deserialize() methods
+
8761 WriteLine();
+
8762 WriteLineIndent("// Serialize the struct value");
+
8763 WriteLineIndent("size_t serialize(const " + struct_name + "& value);");
+
8764 WriteLineIndent("// Deserialize the struct value");
+
8765 WriteLineIndent("size_t deserialize(" + struct_name + "& value) const noexcept;");
+
8766
+
8767 // Generate struct model next() method
+
8768 WriteLine();
+
8769 WriteLineIndent("// Move to the next struct value");
+
8770 WriteLineIndent("void next(size_t prev) noexcept { model.fbe_shift(prev); }");
+
8771
+
8772 // Generate struct model accessor
+
8773 Indent(-1);
+
8774 WriteLine();
+
8775 WriteLineIndent("public:");
+
8776 Indent(1);
+
8777 WriteLineIndent("FieldModel<" + struct_name + "> model;");
+
8778
+
8779 // Generate struct model end
+
8780 Indent(-1);
+
8781 WriteLineIndent("};");
+
8782
+
8783 // Generate namespace end
+
8784 WriteLine();
+
8785 WriteLineIndent("} // namespace " + *p->name);
+
8786}
+
8787
+
8788void GeneratorCpp::GenerateStructModel_Source(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s)
+
8789{
+
8790 // Generate namespace begin
+
8791 WriteLine();
+
8792 WriteLineIndent("namespace " + *p->name + " {");
+
8793
+
8794 std::string struct_name = "::" + *p->name + "::" + *s->name;
+
8795 std::string model_name = *s->name + "Model";
+
8796
+
8797 // Generate struct model verify() method
+
8798 WriteLine();
+
8799 WriteLineIndent("bool " + model_name + "::verify()");
+
8800 WriteLineIndent("{");
+
8801 Indent(1);
+
8802 WriteLineIndent("if ((this->buffer().offset() + model.fbe_offset() - 4) > this->buffer().size())");
+
8803 Indent(1);
+
8804 WriteLineIndent("return false;");
+
8805 Indent(-1);
+
8806 WriteLine();
+
8807 WriteLineIndent("uint32_t fbe_full_size = *((const uint32_t*)(this->buffer().data() + this->buffer().offset() + model.fbe_offset() - 4));");
+
8808 WriteLineIndent("if (fbe_full_size < model.fbe_size())");
+
8809 Indent(1);
+
8810 WriteLineIndent("return false;");
+
8811 Indent(-1);
+
8812 WriteLine();
+
8813 WriteLineIndent("return model.verify();");
+
8814 Indent(-1);
+
8815 WriteLineIndent("}");
+
8816 WriteLine();
+
8817
+
8818 // Generate struct model create_begin() method
+
8819 WriteLineIndent("size_t " + model_name + "::create_begin()");
+
8820 WriteLineIndent("{");
+
8821 Indent(1);
+
8822 WriteLineIndent("size_t fbe_begin = this->buffer().allocate(4 + model.fbe_size());");
+
8823 WriteLineIndent("return fbe_begin;");
+
8824 Indent(-1);
+
8825 WriteLineIndent("}");
+
8826 WriteLine();
+
8827
+
8828 // Generate struct model create_end() method
+
8829 WriteLineIndent("size_t " + model_name + "::create_end(size_t fbe_begin)");
+
8830 WriteLineIndent("{");
+
8831 Indent(1);
+
8832 WriteLineIndent("size_t fbe_end = this->buffer().size();");
+
8833 WriteLineIndent("uint32_t fbe_full_size = (uint32_t)(fbe_end - fbe_begin);");
+
8834 WriteLineIndent("*((uint32_t*)(this->buffer().data() + this->buffer().offset() + model.fbe_offset() - 4)) = fbe_full_size;");
+
8835 WriteLineIndent("return fbe_full_size;");
+
8836 Indent(-1);
+
8837 WriteLineIndent("}");
+
8838 WriteLine();
+
8839
+
8840 // Generate struct model serialize() method
+
8841 WriteLineIndent("size_t " + model_name + "::serialize(const " + struct_name + "& value)");
+
8842 WriteLineIndent("{");
+
8843 Indent(1);
+
8844 WriteLineIndent("size_t fbe_begin = create_begin();");
+
8845 WriteLineIndent("model.set(value);");
+
8846 WriteLineIndent("size_t fbe_full_size = create_end(fbe_begin);");
+
8847 WriteLineIndent("return fbe_full_size;");
+
8848 Indent(-1);
+
8849 WriteLineIndent("}");
+
8850 WriteLine();
+
8851
+
8852 // Generate struct model deserialize() method
+
8853 WriteLineIndent("size_t " + model_name + "::deserialize(" + struct_name + "& value) const noexcept");
+
8854 WriteLineIndent("{");
+
8855 Indent(1);
+
8856 WriteLineIndent("if ((this->buffer().offset() + model.fbe_offset() - 4) > this->buffer().size())");
+
8857 Indent(1);
+
8858 WriteLineIndent("return 0;");
+
8859 Indent(-1);
+
8860 WriteLine();
+
8861 WriteLineIndent("uint32_t fbe_full_size = *((const uint32_t*)(this->buffer().data() + this->buffer().offset() + model.fbe_offset() - 4));");
+
8862 WriteLineIndent("assert((fbe_full_size >= model.fbe_size()) && \"Model is broken!\");");
+
8863 WriteLineIndent("if (fbe_full_size < model.fbe_size())");
+
8864 Indent(1);
+
8865 WriteLineIndent("return 0;");
+
8866 Indent(-1);
+
8867 WriteLine();
+
8868 WriteLineIndent("model.get(value);");
+
8869 WriteLineIndent("return fbe_full_size;");
+
8870 Indent(-1);
+
8871 WriteLineIndent("}");
+
8872
+
8873 // Generate namespace end
+
8874 WriteLine();
+
8875 WriteLineIndent("} // namespace " + *p->name);
+
8876}
+
8877
+
8878void GeneratorCpp::GenerateStructFinalModel_Header(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s)
+
8879{
+
8880 std::string struct_name = "::" + *p->name + "::" + *s->name;
+
8881
+
8882 // Generate struct final model begin
+
8883 WriteLine();
+
8884 WriteLineIndent("// Fast Binary Encoding " + struct_name + " final model");
+
8885 WriteLineIndent("template <>");
+
8886 WriteLineIndent("class FinalModel<" + struct_name + ">");
+
8887 WriteLineIndent("{");
+
8888 WriteLineIndent("public:");
+
8889 Indent(1);
+
8890
+
8891 // Generate struct final model constructor
+
8892 WriteLineIndent("FinalModel(FBEBuffer& buffer, size_t offset) noexcept;");
+
8893
+
8894 // Generate struct final model FBE methods
+
8895 WriteLine();
+
8896 WriteLineIndent("// Get the allocation size");
+
8897 WriteLineIndent("size_t fbe_allocation_size(const " + struct_name + "& fbe_value) const noexcept;");
+
8898 WriteLineIndent("// Get the final offset");
+
8899 WriteLineIndent("size_t fbe_offset() const noexcept { return _offset; }");
+
8900 WriteLineIndent("// Set the final offset");
+
8901 WriteLineIndent("size_t fbe_offset(size_t offset) const noexcept { return _offset = offset; }");
+
8902 WriteLineIndent("// Get the final type");
+
8903 if (s->base && !s->base->empty() && (s->type == 0))
+
8904 WriteLineIndent("static constexpr size_t fbe_type() noexcept { return FinalModel<" + ConvertTypeName(*p->name, *s->base, false) + ">::fbe_type(); }");
+
8905 else
+
8906 WriteLineIndent("static constexpr size_t fbe_type() noexcept { return " + std::to_string(s->type) + "; }");
+
8907 WriteLine();
+
8908 WriteLineIndent("// Shift the current final offset");
+
8909 WriteLineIndent("void fbe_shift(size_t size) noexcept { _offset += size; }");
+
8910 WriteLineIndent("// Unshift the current final offset");
+
8911 WriteLineIndent("void fbe_unshift(size_t size) noexcept { _offset -= size; }");
+
8912
+
8913 // Generate struct final model verify(), verify_fields() methods
+
8914 WriteLine();
+
8915 WriteLineIndent("// Check if the struct value is valid");
+
8916 WriteLineIndent("size_t verify() const noexcept;");
+
8917 WriteLineIndent("// Check if the struct fields are valid");
+
8918 WriteLineIndent("size_t verify_fields() const noexcept;");
+
8919
+
8920 // Generate struct final model get(), get_fields() methods
+
8921 WriteLine();
+
8922 WriteLineIndent("// Get the struct value");
+
8923 WriteLineIndent("size_t get(" + struct_name + "& fbe_value) const noexcept;");
+
8924 WriteLineIndent("// Get the struct fields values");
+
8925 WriteLineIndent("size_t get_fields(" + struct_name + "& fbe_value) const noexcept;");
+
8926
+
8927 // Generate struct final model set(), set_fields() method
+
8928 WriteLine();
+
8929 WriteLineIndent("// Set the struct value");
+
8930 WriteLineIndent("size_t set(const " + struct_name + "& fbe_value) noexcept;");
+
8931 WriteLineIndent("// Set the struct fields values");
+
8932 WriteLineIndent("size_t set_fields(const " + struct_name + "& fbe_value) noexcept;");
+
8933
+
8934 // Generate struct final model buffer & offset
+
8935 Indent(-1);
+
8936 WriteLine();
+
8937 WriteLineIndent("private:");
+
8938 Indent(1);
+
8939 WriteLineIndent("FBEBuffer& _buffer;");
+
8940 WriteLineIndent("mutable size_t _offset;");
+
8941
+
8942 // Generate struct final model accessors
+
8943 Indent(-1);
+
8944 WriteLine();
+
8945 WriteLineIndent("public:");
+
8946 Indent(1);
+
8947 if (s->base && !s->base->empty())
+
8948 WriteLineIndent("FinalModel<" + ConvertTypeName(*p->name, *s->base, false) + "> parent;");
+
8949 if (s->body)
+
8950 {
+
8951 for (const auto& field : s->body->fields)
+
8952 {
+
8953 if (field->array)
+
8954 WriteLineIndent("FinalModelArray<" + ConvertTypeName(*p->name, *field->type, field->optional) + ", " + std::to_string(field->N) + "> " + *field->name + ";");
+
8955 else if (field->vector || field->list || field->set)
+
8956 WriteLineIndent("FinalModelVector<" + ConvertTypeName(*p->name, *field->type, field->optional) + "> " + *field->name + ";");
+
8957 else if (field->map || field->hash)
+
8958 WriteLineIndent("FinalModelMap<" + ConvertTypeName(*p->name, *field->key, false) + ", " + ConvertTypeName(*p->name, *field->type, field->optional) + "> " + *field->name + ";");
+
8959 else
+
8960 WriteLineIndent("FinalModel<" + ConvertTypeName(*p->name, *field->type, field->optional) + "> " + *field->name + ";");
+
8961 }
+
8962 }
+
8963
+
8964 // Generate struct final model end
+
8965 Indent(-1);
+
8966 WriteLineIndent("};");
+
8967}
+
8968
+
8969void GeneratorCpp::GenerateStructFinalModel_Source(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s)
+
8970{
+
8971 std::string struct_name = "::" + *p->name + "::" + *s->name;
+
8972 std::string model_name = "FinalModel<" + struct_name + ">";
+
8973
+
8974 // Generate struct final model constructor
+
8975 WriteLine();
+
8976 WriteLineIndent(model_name + "::FinalModel(FBEBuffer& buffer, size_t offset) noexcept : _buffer(buffer), _offset(offset)");
+
8977 Indent(1);
+
8978 if (s->base && !s->base->empty())
+
8979 WriteLineIndent(", parent(buffer, 0)");
+
8980 if (s->body)
+
8981 for (const auto& field : s->body->fields)
+
8982 WriteLineIndent(", " + *field->name + "(buffer, 0)");
+
8983 Indent(-1);
+
8984 WriteLineIndent("{}");
+
8985 WriteLine();
+
8986
+
8987 // Generate struct final model FBE methods
+
8988 WriteLineIndent("size_t " + model_name + "::fbe_allocation_size(const " + struct_name + "& fbe_value) const noexcept");
+
8989 WriteLineIndent("{");
+
8990 Indent(1);
+
8991 WriteLineIndent("size_t fbe_result = 0");
+
8992 Indent(1);
+
8993 if (s->base && !s->base->empty())
+
8994 WriteLineIndent("+ parent.fbe_allocation_size(fbe_value)");
+
8995 if (s->body)
+
8996 for (const auto& field : s->body->fields)
+
8997 WriteLineIndent("+ " + *field->name + ".fbe_allocation_size(fbe_value." + *field->name + ")");
+
8998 WriteLineIndent(";");
+
8999 Indent(-1);
+
9000 WriteLineIndent("return fbe_result;");
+
9001 Indent(-1);
+
9002 WriteLineIndent("}");
+
9003 WriteLine();
+
9004
+
9005 // Generate struct final model verify() method
+
9006 WriteLineIndent("size_t " + model_name + "::verify() const noexcept");
+
9007 WriteLineIndent("{");
+
9008 Indent(1);
+
9009 WriteLineIndent("_buffer.shift(fbe_offset());");
+
9010 WriteLineIndent("size_t fbe_result = verify_fields();");
+
9011 WriteLineIndent("_buffer.unshift(fbe_offset());");
+
9012 WriteLineIndent("return fbe_result;");
+
9013 Indent(-1);
+
9014 WriteLineIndent("}");
+
9015 WriteLine();
+
9016
+
9017 // Generate struct final model verify_fields() method
+
9018 WriteLineIndent("size_t " + model_name + "::verify_fields() const noexcept");
+
9019 WriteLineIndent("{");
+
9020 Indent(1);
+
9021 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
9022 {
+
9023 WriteLineIndent("size_t fbe_current_offset = 0;");
+
9024 WriteLineIndent("size_t fbe_field_size;");
+
9025 if (s->base && !s->base->empty())
+
9026 {
+
9027 WriteLine();
+
9028 WriteLineIndent("parent.fbe_offset(fbe_current_offset);");
+
9029 WriteLineIndent("fbe_field_size = parent.verify_fields();");
+
9030 WriteLineIndent("if (fbe_field_size == std::numeric_limits<std::size_t>::max())");
+
9031 Indent(1);
+
9032 WriteLineIndent("return std::numeric_limits<std::size_t>::max();");
+
9033 Indent(-1);
+
9034 WriteLineIndent("fbe_current_offset += fbe_field_size;");
+
9035 }
+
9036 if (s->body)
+
9037 {
+
9038 for (const auto& field : s->body->fields)
+
9039 {
+
9040 WriteLine();
+
9041 WriteLineIndent(*field->name + ".fbe_offset(fbe_current_offset);");
+
9042 WriteLineIndent("fbe_field_size = " + *field->name + ".verify();");
+
9043 WriteLineIndent("if (fbe_field_size == std::numeric_limits<std::size_t>::max())");
+
9044 Indent(1);
+
9045 WriteLineIndent("return std::numeric_limits<std::size_t>::max();");
+
9046 Indent(-1);
+
9047 WriteLineIndent("fbe_current_offset += fbe_field_size;");
+
9048 }
+
9049 }
+
9050 WriteLine();
+
9051 WriteLineIndent("return fbe_current_offset;");
+
9052 }
+
9053 else
+
9054 WriteLineIndent("return 0;");
+
9055 Indent(-1);
+
9056 WriteLineIndent("}");
+
9057 WriteLine();
+
9058
+
9059 // Generate struct final model get() method
+
9060 WriteLineIndent("size_t " + model_name + "::get(" + struct_name + "& fbe_value) const noexcept");
+
9061 WriteLineIndent("{");
+
9062 Indent(1);
+
9063 WriteLineIndent("_buffer.shift(fbe_offset());");
+
9064 WriteLineIndent("size_t fbe_result = get_fields(fbe_value);");
+
9065 WriteLineIndent("_buffer.unshift(fbe_offset());");
+
9066 WriteLineIndent("return fbe_result;");
+
9067 Indent(-1);
+
9068 WriteLineIndent("}");
+
9069 WriteLine();
+
9070
+
9071 // Generate struct final model get_fields() method
+
9072 WriteLineIndent("size_t " + model_name + "::get_fields(" + struct_name + "& fbe_value) const noexcept");
+
9073 WriteLineIndent("{");
+
9074 Indent(1);
+
9075 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
9076 {
+
9077 WriteLineIndent("size_t fbe_current_offset = 0;");
+
9078 WriteLineIndent("size_t fbe_current_size = 0;");
+
9079 WriteLineIndent("size_t fbe_field_size;");
+
9080 if (s->base && !s->base->empty())
+
9081 {
+
9082 WriteLine();
+
9083 WriteLineIndent("parent.fbe_offset(fbe_current_offset);");
+
9084 WriteLineIndent("fbe_field_size = parent.get_fields(fbe_value);");
+
9085 WriteLineIndent("fbe_current_offset += fbe_field_size;");
+
9086 WriteLineIndent("fbe_current_size += fbe_field_size;");
+
9087 }
+
9088 if (s->body)
+
9089 {
+
9090 for (const auto& field : s->body->fields)
+
9091 {
+
9092 WriteLine();
+
9093 WriteLineIndent(*field->name + ".fbe_offset(fbe_current_offset);");
+
9094 WriteLineIndent("fbe_field_size = " + *field->name + ".get(fbe_value." + *field->name + ");");
+
9095 WriteLineIndent("fbe_current_offset += fbe_field_size;");
+
9096 WriteLineIndent("fbe_current_size += fbe_field_size;");
+
9097 }
+
9098 }
+
9099 WriteLine();
+
9100 WriteLineIndent("return fbe_current_size;");
+
9101 }
+
9102 else
+
9103 WriteLineIndent("return 0;");
+
9104 Indent(-1);
+
9105 WriteLineIndent("}");
+
9106 WriteLine();
+
9107
+
9108 // Generate struct final model set() method
+
9109 WriteLineIndent("size_t " + model_name + "::set(const " + struct_name + "& fbe_value) noexcept");
+
9110 WriteLineIndent("{");
+
9111 Indent(1);
+
9112 WriteLineIndent("_buffer.shift(fbe_offset());");
+
9113 WriteLineIndent("size_t fbe_result = set_fields(fbe_value);");
+
9114 WriteLineIndent("_buffer.unshift(fbe_offset());");
+
9115 WriteLineIndent("return fbe_result;");
+
9116 Indent(-1);
+
9117 WriteLineIndent("}");
+
9118 WriteLine();
+
9119
+
9120 // Generate struct final model set_fields() method
+
9121 WriteLineIndent("size_t " + model_name + "::set_fields(const " + struct_name + "& fbe_value) noexcept");
+
9122 WriteLineIndent("{");
+
9123 Indent(1);
+
9124 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
9125 {
+
9126 WriteLineIndent("size_t fbe_current_offset = 0;");
+
9127 WriteLineIndent("size_t fbe_current_size = 0;");
+
9128 WriteLineIndent("size_t fbe_field_size;");
+
9129 if (s->base && !s->base->empty())
+
9130 {
+
9131 WriteLine();
+
9132 WriteLineIndent("parent.fbe_offset(fbe_current_offset);");
+
9133 WriteLineIndent("fbe_field_size = parent.set_fields(fbe_value);");
+
9134 WriteLineIndent("fbe_current_offset += fbe_field_size;");
+
9135 WriteLineIndent("fbe_current_size += fbe_field_size;");
+
9136 }
+
9137 if (s->body)
+
9138 {
+
9139 for (const auto& field : s->body->fields)
+
9140 {
+
9141 WriteLine();
+
9142 WriteLineIndent(*field->name + ".fbe_offset(fbe_current_offset);");
+
9143 WriteLineIndent("fbe_field_size = " + *field->name + ".set(fbe_value." + *field->name + ");");
+
9144 WriteLineIndent("fbe_current_offset += fbe_field_size;");
+
9145 WriteLineIndent("fbe_current_size += fbe_field_size;");
+
9146 }
+
9147 }
+
9148 WriteLine();
+
9149 WriteLineIndent("return fbe_current_size;");
+
9150 }
+
9151 else
+
9152 WriteLineIndent("return 0;");
+
9153 Indent(-1);
+
9154 WriteLineIndent("}");
+
9155}
+
9156
+
9157void GeneratorCpp::GenerateStructModelFinal_Header(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s)
+
9158{
+
9159 // Generate namespace begin
+
9160 WriteLine();
+
9161 WriteLineIndent("namespace " + *p->name + " {");
+
9162
+
9163 std::string struct_name = "::" + *p->name + "::" + *s->name;
+
9164
+
9165 // Generate struct model final begin
+
9166 WriteLine();
+
9167 WriteLineIndent("// Fast Binary Encoding " + *s->name + " final model");
+
9168 WriteLineIndent("class " + *s->name + "FinalModel : public FBE::Model");
+
9169 WriteLineIndent("{");
+
9170 WriteLineIndent("public:");
+
9171 Indent(1);
+
9172
+
9173 // Generate struct model final constructor
+
9174 WriteLineIndent(*s->name + "FinalModel() : _model(this->buffer(), 8) {}");
+
9175 WriteLineIndent(*s->name + "FinalModel(const std::shared_ptr<FBEBuffer>& buffer) : FBE::Model(buffer), _model(this->buffer(), 8) {}");
+
9176
+
9177 // Generate struct model final FBE methods
+
9178 WriteLine();
+
9179 WriteLineIndent("// Get the model type");
+
9180 WriteLineIndent("static constexpr size_t fbe_type() noexcept { return FinalModel<" + struct_name + ">::fbe_type(); }");
+
9181
+
9182 // Generate struct model final verify() method
+
9183 WriteLine();
+
9184 WriteLineIndent("// Check if the struct value is valid");
+
9185 WriteLineIndent("bool verify();");
+
9186
+
9187 // Generate struct model final serialize(), deserialize() methods
+
9188 WriteLine();
+
9189 WriteLineIndent("// Serialize the struct value");
+
9190 WriteLineIndent("size_t serialize(const " + struct_name + "& value);");
+
9191 WriteLineIndent("// Deserialize the struct value");
+
9192 WriteLineIndent("size_t deserialize(" + struct_name + "& value) const noexcept;");
+
9193
+
9194 // Generate struct model final next() method
+
9195 WriteLine();
+
9196 WriteLineIndent("// Move to the next struct value");
+
9197 WriteLineIndent("void next(size_t prev) noexcept { _model.fbe_shift(prev); }");
+
9198
+
9199 // Generate struct model final accessor
+
9200 Indent(-1);
+
9201 WriteLine();
+
9202 WriteLineIndent("private:");
+
9203 Indent(1);
+
9204 WriteLineIndent("FinalModel<" + struct_name + "> _model;");
+
9205
+
9206 // Generate struct model final end
+
9207 Indent(-1);
+
9208 WriteLineIndent("};");
+
9209
+
9210 // Generate namespace end
+
9211 WriteLine();
+
9212 WriteLineIndent("} // namespace " + *p->name);
+
9213}
+
9214
+
9215void GeneratorCpp::GenerateStructModelFinal_Source(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s)
+
9216{
+
9217 // Generate namespace begin
+
9218 WriteLine();
+
9219 WriteLineIndent("namespace " + *p->name + " {");
+
9220
+
9221 std::string struct_name = "::" + *p->name + "::" + *s->name;
+
9222 std::string model_name = *s->name + "FinalModel";
+
9223
+
9224 // Generate struct model final verify() method
+
9225 WriteLine();
+
9226 WriteLineIndent("bool " + model_name + "::verify()");
+
9227 WriteLineIndent("{");
+
9228 Indent(1);
+
9229 WriteLineIndent("if ((this->buffer().offset() + _model.fbe_offset()) > this->buffer().size())");
+
9230 Indent(1);
+
9231 WriteLineIndent("return false;");
+
9232 Indent(-1);
+
9233 WriteLine();
+
9234 WriteLineIndent("size_t fbe_struct_size = *((const uint32_t*)(this->buffer().data() + this->buffer().offset() + _model.fbe_offset() - 8));");
+
9235 WriteLineIndent("size_t fbe_struct_type = *((const uint32_t*)(this->buffer().data() + this->buffer().offset() + _model.fbe_offset() - 4));");
+
9236 WriteLineIndent("if ((fbe_struct_size == 0) || (fbe_struct_type != fbe_type()))");
+
9237 Indent(1);
+
9238 WriteLineIndent("return false;");
+
9239 Indent(-1);
+
9240 WriteLine();
+
9241 WriteLineIndent("return ((8 + _model.verify()) == fbe_struct_size);");
+
9242 Indent(-1);
+
9243 WriteLineIndent("}");
+
9244 WriteLine();
+
9245
+
9246 // Generate struct model final serialize() method
+
9247 WriteLineIndent("size_t " + model_name + "::serialize(const " + struct_name + "& value)");
+
9248 WriteLineIndent("{");
+
9249 Indent(1);
+
9250 WriteLineIndent("size_t fbe_initial_size = this->buffer().size();");
+
9251 WriteLine();
+
9252 WriteLineIndent("uint32_t fbe_struct_type = (uint32_t)fbe_type();");
+
9253 WriteLineIndent("uint32_t fbe_struct_size = (uint32_t)(8 + _model.fbe_allocation_size(value));");
+
9254 WriteLineIndent("uint32_t fbe_struct_offset = (uint32_t)(this->buffer().allocate(fbe_struct_size) - this->buffer().offset());");
+
9255 WriteLineIndent("assert(((this->buffer().offset() + fbe_struct_offset + fbe_struct_size) <= this->buffer().size()) && \"Model is broken!\");");
+
9256 WriteLineIndent("if ((this->buffer().offset() + fbe_struct_offset + fbe_struct_size) > this->buffer().size())");
+
9257 Indent(1);
+
9258 WriteLineIndent("return 0;");
+
9259 Indent(-1);
+
9260 WriteLine();
+
9261 WriteLineIndent("fbe_struct_size = (uint32_t)(8 + _model.set(value));");
+
9262 WriteLineIndent("this->buffer().resize(fbe_initial_size + fbe_struct_size);");
+
9263 WriteLine();
+
9264 WriteLineIndent("*((uint32_t*)(this->buffer().data() + this->buffer().offset() + _model.fbe_offset() - 8)) = fbe_struct_size;");
+
9265 WriteLineIndent("*((uint32_t*)(this->buffer().data() + this->buffer().offset() + _model.fbe_offset() - 4)) = fbe_struct_type;");
+
9266 WriteLine();
+
9267 WriteLineIndent("return fbe_struct_size;");
+
9268 Indent(-1);
+
9269 WriteLineIndent("}");
+
9270 WriteLine();
+
9271
+
9272 // Generate struct model final deserialize() method
+
9273 WriteLineIndent("size_t " + model_name + "::deserialize(" + struct_name + "& value) const noexcept");
+
9274 WriteLineIndent("{");
+
9275 Indent(1);
+
9276 WriteLineIndent("assert(((this->buffer().offset() + _model.fbe_offset()) <= this->buffer().size()) && \"Model is broken!\");");
+
9277 WriteLineIndent("if ((this->buffer().offset() + _model.fbe_offset()) > this->buffer().size())");
+
9278 Indent(1);
+
9279 WriteLineIndent("return 0;");
+
9280 Indent(-1);
+
9281 WriteLine();
+
9282 WriteLineIndent("size_t fbe_struct_size = *((const uint32_t*)(this->buffer().data() + this->buffer().offset() + _model.fbe_offset() - 8));");
+
9283 WriteLineIndent("size_t fbe_struct_type = *((const uint32_t*)(this->buffer().data() + this->buffer().offset() + _model.fbe_offset() - 4));");
+
9284 WriteLineIndent("assert(((fbe_struct_size > 0) && (fbe_struct_type == fbe_type())) && \"Model is broken!\");");
+
9285 WriteLineIndent("if ((fbe_struct_size == 0) || (fbe_struct_type != fbe_type()))");
+
9286 Indent(1);
+
9287 WriteLineIndent("return 8;");
+
9288 Indent(-1);
+
9289 WriteLine();
+
9290 WriteLineIndent("return 8 + _model.get(value);");
+
9291 Indent(-1);
+
9292 WriteLineIndent("}");
+
9293
+
9294 // Generate namespace end
+
9295 WriteLine();
+
9296 WriteLineIndent("} // namespace " + *p->name);
+
9297}
+
9298
+
9299void GeneratorCpp::GenerateProtocolVersion(const std::shared_ptr<Package>& p)
+
9300{
+
9301 // Generate protocol version struct
+
9302 WriteLine();
+
9303 WriteLineIndent("// Fast Binary Encoding " + *p->name + " protocol version");
+
9304 WriteLineIndent("struct ProtocolVersion");
+
9305 WriteLineIndent("{");
+
9306 Indent(1);
+
9307 WriteLineIndent("// Protocol major version");
+
9308 WriteLineIndent("static const int major = " + std::to_string(p->version->major) + ";");
+
9309 WriteLineIndent("// Protocol minor version");
+
9310 WriteLineIndent("static const int minor = " + std::to_string(p->version->minor) + ";");
+
9311 Indent(-1);
+
9312 WriteLineIndent("};");
+
9313}
+
9314
+
9315void GeneratorCpp::GenerateSender_Header(const std::shared_ptr<Package>& p, bool final)
+
9316{
+
9317 std::string sender = (final ? "FinalSender" : "Sender");
+
9318 std::string model = (final ? "FinalModel" : "Model");
+
9319
+
9320 // Generate sender begin
+
9321 WriteLine();
+
9322 if (final)
+
9323 WriteLineIndent("// Fast Binary Encoding " + *p->name + " final sender");
+
9324 else
+
9325 WriteLineIndent("// Fast Binary Encoding " + *p->name + " sender");
+
9326 WriteLineIndent("class " + sender + " : public virtual FBE::Sender");
+
9327 if (p->import)
+
9328 {
+
9329 Indent(1);
+
9330 for (const auto& import : p->import->imports)
+
9331 WriteLineIndent(", public virtual " + *import + "::" + sender);
+
9332 Indent(-1);
+
9333 }
+
9334 WriteLineIndent("{");
+
9335 WriteLineIndent("public:");
+
9336 Indent(1);
+
9337
+
9338 // Generate sender constructors
+
9339 WriteLineIndent(sender + "()");
+
9340 bool first = true;
+
9341 if (p->body)
+
9342 {
+
9343 Indent(1);
+
9344 for (const auto& s : p->body->structs)
+
9345 {
+
9346 if (s->message)
+
9347 {
+
9348 WriteLineIndent((first ? ": " : ", ") + *s->name + "" + "Model(this->_buffer)");
+
9349 first = false;
+
9350 }
+
9351 }
+
9352 Indent(-1);
+
9353 }
+
9354 WriteLineIndent("{" + std::string(final ? " this->final(true); " : "") + "}");
+
9355 WriteLineIndent(sender + "(const " + sender + "&) = delete;");
+
9356 WriteLineIndent(sender + "(" + sender + "&&) noexcept = delete;");
+
9357 WriteLineIndent("virtual ~" + sender + "() = default;");
+
9358
+
9359 // Generate sender operators
+
9360 WriteLine();
+
9361 WriteLineIndent(sender + "& operator=(const " + sender + "&) = delete;");
+
9362 WriteLineIndent(sender + "& operator=(" + sender + "&&) noexcept = delete;");
+
9363
+
9364 // Generate imported senders accessors
+
9365 if (p->import)
+
9366 {
+
9367 WriteLine();
+
9368 WriteLineIndent("// Imported senders");
+
9369 for (const auto& import : p->import->imports)
+
9370 WriteLineIndent(*import + "::" + sender + "& " + *import + "_sender() noexcept { return *this; }");
+
9371 }
+
9372
+
9373 // Generate send() methods
+
9374 if (p->body)
+
9375 {
+
9376 first = true;
+
9377 for (const auto& s : p->body->structs)
+
9378 {
+
9379 if (s->message)
+
9380 {
+
9381 std::string struct_name = "::" + *p->name + "::" + *s->name;
+
9382 if (first)
+
9383 WriteLine();
+
9384 WriteLineIndent("size_t send(const " + struct_name + "& value);");
+
9385 first = false;
+
9386 }
+
9387 }
+
9388 }
+
9389
+
9390 // Generate sender models accessors
+
9391 if (p->body)
+
9392 {
+
9393 Indent(-1);
+
9394 WriteLine();
+
9395 WriteLineIndent("public:");
+
9396 Indent(1);
+
9397 WriteLineIndent("// Sender models accessors");
+
9398 for (const auto& s : p->body->structs)
+
9399 if (s->message)
+
9400 WriteLineIndent("FBE::" + *p->name + "::" + *s->name + model + " " + *s->name + "Model;");
+
9401 }
+
9402
+
9403 // Generate sender end
+
9404 Indent(-1);
+
9405 WriteLineIndent("};");
+
9406}
+
9407
+
9408void GeneratorCpp::GenerateSender_Source(const std::shared_ptr<Package>& p, bool final)
+
9409{
+
9410 std::string sender = (final ? "FinalSender" : "Sender");
+
9411
+
9412 // Generate send() methods
+
9413 if (p->body)
+
9414 {
+
9415 for (const auto& s : p->body->structs)
+
9416 {
+
9417 if (s->message)
+
9418 {
+
9419 std::string struct_name = "::" + *p->name + "::" + *s->name;
+
9420 WriteLine();
+
9421 WriteLineIndent("size_t " + sender + "::send(const " + struct_name + "& value)");
+
9422 WriteLineIndent("{");
+
9423 Indent(1);
+
9424 WriteLineIndent("// Serialize the value into the FBE stream");
+
9425 WriteLineIndent("size_t serialized = " + *s->name + "Model.serialize(value);");
+
9426 WriteLineIndent("assert((serialized > 0) && \"" + *p->name + "::" + *s->name + " serialization failed!\");");
+
9427 WriteLineIndent("assert(" + *s->name + "Model.verify() && \"" + *p->name + "::" + *s->name + " validation failed!\");");
+
9428 WriteLine();
+
9429 WriteLineIndent("// Log the value");
+
9430 WriteLineIndent("if (this->_logging)");
+
9431 WriteLineIndent("{");
+
9432 Indent(1);
+
9433 WriteLineIndent("std::string message = value.string();");
+
9434 WriteLineIndent("this->onSendLog(message);");
+
9435 Indent(-1);
+
9436 WriteLineIndent("}");
+
9437 WriteLine();
+
9438 WriteLineIndent("// Send the serialized value");
+
9439 WriteLineIndent("return this->send_serialized(serialized);");
+
9440 Indent(-1);
+
9441 WriteLineIndent("}");
+
9442 }
+
9443 }
+
9444 }
+
9445}
+
9446
+
9447void GeneratorCpp::GenerateReceiver_Header(const std::shared_ptr<Package>& p, bool final)
+
9448{
+
9449 std::string receiver = (final ? "FinalReceiver" : "Receiver");
+
9450 std::string model = (final ? "FinalModel" : "Model");
+
9451
+
9452 // Generate receiver begin
+
9453 WriteLine();
+
9454 if (final)
+
9455 WriteLineIndent("// Fast Binary Encoding " + *p->name + " final receiver");
+
9456 else
+
9457 WriteLineIndent("// Fast Binary Encoding " + *p->name + " receiver");
+
9458 WriteLineIndent("class " + receiver + " : public virtual FBE::Receiver");
+
9459 if (p->import)
+
9460 {
+
9461 Indent(1);
+
9462 for (const auto& import : p->import->imports)
+
9463 WriteLineIndent(", public virtual " + *import + "::" + receiver);
+
9464 Indent(-1);
+
9465 }
+
9466 WriteLineIndent("{");
+
9467 WriteLineIndent("public:");
+
9468 Indent(1);
+
9469
+
9470 // Generate receiver constructors
+
9471 WriteLineIndent(receiver + "() {" + std::string(final ? " this->final(true); " : "") + "}");
+
9472 WriteLineIndent(receiver + "(const " + receiver + "&) = delete;");
+
9473 WriteLineIndent(receiver + "(" + receiver + "&&) = delete;");
+
9474 WriteLineIndent("virtual ~" + receiver + "() = default;");
+
9475
+
9476 // Generate receiver operators
+
9477 WriteLine();
+
9478 WriteLineIndent(receiver + "& operator=(const " + receiver + "&) = delete;");
+
9479 WriteLineIndent(receiver + "& operator=(" + receiver + "&&) = delete;");
+
9480
+
9481 // Generate receiver handlers
+
9482 if (p->body)
+
9483 {
+
9484 WriteLine();
+
9485 Indent(-1);
+
9486 WriteLineIndent("protected:");
+
9487 Indent(1);
+
9488 WriteLineIndent("// Receive handlers");
+
9489 for (const auto& s : p->body->structs)
+
9490 {
+
9491 if (s->message)
+
9492 {
+
9493 std::string struct_name = "::" + *p->name + "::" + *s->name;
+
9494 WriteLineIndent("virtual void onReceive(const " + struct_name + "& value) {}");
+
9495 }
+
9496 }
+
9497 }
+
9498
+
9499 // Generate receiver message handler
+
9500 WriteLine();
+
9501 WriteLineIndent("// Receive message handler");
+
9502 WriteLineIndent("bool onReceive(size_t type, const void* data, size_t size) override;");
+
9503
+
9504 // Generate receiver models accessors
+
9505 if (p->body)
+
9506 {
+
9507 Indent(-1);
+
9508 WriteLine();
+
9509 WriteLineIndent("private:");
+
9510 Indent(1);
+
9511 WriteLineIndent("// Receiver values accessors");
+
9512 for (const auto& s : p->body->structs)
+
9513 {
+
9514 if (s->message)
+
9515 {
+
9516 std::string struct_name = "::" + *p->name + "::" + *s->name;
+
9517 WriteLineIndent(struct_name + " " + *s->name + "Value;");
+
9518 }
+
9519 }
+
9520 WriteLine();
+
9521 WriteLineIndent("// Receiver models accessors");
+
9522 for (const auto& s : p->body->structs)
+
9523 if (s->message)
+
9524 WriteLineIndent("FBE::" + *p->name + "::" + *s->name + model + " " + *s->name + "Model;");
+
9525 }
+
9526
+
9527 // Generate receiver end
+
9528 Indent(-1);
+
9529 WriteLineIndent("};");
+
9530}
+
9531
+
9532void GeneratorCpp::GenerateReceiver_Source(const std::shared_ptr<Package>& p, bool final)
+
9533{
+
9534 std::string receiver = (final ? "FinalReceiver" : "Receiver");
+
9535 std::string model = (final ? "FinalModel" : "Model");
+
9536
+
9537 // Generate receiver message handler
+
9538 WriteLine();
+
9539 WriteLineIndent("bool " + receiver + "::onReceive(size_t type, const void* data, size_t size)");
+
9540 WriteLineIndent("{");
+
9541 Indent(1);
+
9542 if (p->body)
+
9543 {
+
9544 WriteLineIndent("switch (type)");
+
9545 WriteLineIndent("{");
+
9546 Indent(1);
+
9547 for (const auto& s : p->body->structs)
+
9548 {
+
9549 if (s->message)
+
9550 {
+
9551 std::string struct_name = "::" + *p->name + "::" + *s->name;
+
9552 WriteLineIndent("case FBE::" + *p->name + "::" + *s->name + model + "::fbe_type():");
+
9553 WriteLineIndent("{");
+
9554 Indent(1);
+
9555 WriteLineIndent("// Deserialize the value from the FBE stream");
+
9556 WriteLineIndent(*s->name + "Model.attach(data, size);");
+
9557 WriteLineIndent("assert(" + *s->name + "Model.verify() && \"" + *p->name + "::" + *s->name + " validation failed!\");");
+
9558 WriteLineIndent("[[maybe_unused]] size_t deserialized = " + *s->name + "Model.deserialize(" + *s->name + "Value);");
+
9559 WriteLineIndent("assert((deserialized > 0) && \"" + *p->name + "::" + *s->name + " deserialization failed!\");");
+
9560 WriteLine();
+
9561 WriteLineIndent("// Log the value");
+
9562 WriteLineIndent("if (this->_logging)");
+
9563 WriteLineIndent("{");
+
9564 Indent(1);
+
9565 WriteLineIndent("std::string message = " + *s->name + "Value.string();");
+
9566 WriteLineIndent("this->onReceiveLog(message);");
+
9567 Indent(-1);
+
9568 WriteLineIndent("}");
+
9569 WriteLine();
+
9570 WriteLineIndent("// Call receive handler with deserialized value");
+
9571 WriteLineIndent("onReceive(" + *s->name + "Value);");
+
9572 WriteLineIndent("return true;");
+
9573 Indent(-1);
+
9574 WriteLineIndent("}");
+
9575 }
+
9576 }
+
9577 WriteLineIndent("default: break;");
+
9578 Indent(-1);
+
9579 WriteLineIndent("}");
+
9580 }
+
9581 if (p->import)
+
9582 {
+
9583 WriteLine();
+
9584 for (const auto& import : p->import->imports)
+
9585 {
+
9586 WriteLineIndent("if (" + *import + "::" + receiver + "::onReceive(type, data, size))");
+
9587 Indent(1);
+
9588 WriteLineIndent("return true;");
+
9589 Indent(-1);
+
9590 }
+
9591 }
+
9592 WriteLine();
+
9593 WriteLineIndent("return false;");
+
9594 Indent(-1);
+
9595 WriteLineIndent("}");
+
9596}
+
9597
+
9598void GeneratorCpp::GenerateProxy_Header(const std::shared_ptr<Package>& p, bool final)
+
9599{
+
9600 std::string proxy = (final ? "FinalProxy" : "Proxy");
+
9601 std::string model = (final ? "FinalModel" : "Model");
+
9602
+
9603 // Generate proxy begin
+
9604 WriteLine();
+
9605 if (final)
+
9606 WriteLineIndent("// Fast Binary Encoding " + *p->name + " final proxy");
+
9607 else
+
9608 WriteLineIndent("// Fast Binary Encoding " + *p->name + " proxy");
+
9609 WriteLineIndent("class " + proxy + " : public virtual FBE::Receiver");
+
9610 if (p->import)
+
9611 {
+
9612 Indent(1);
+
9613 for (const auto& import : p->import->imports)
+
9614 WriteLineIndent(", public virtual " + *import + "::" + proxy);
+
9615 Indent(-1);
+
9616 }
+
9617 WriteLineIndent("{");
+
9618 WriteLineIndent("public:");
+
9619 Indent(1);
+
9620
+
9621 // Generate proxy constructors
+
9622 WriteLineIndent(proxy + "() {" + std::string(final ? " this->final(true); " : "") + "}");
+
9623 WriteLineIndent(proxy + "(const " + proxy + "&) = delete;");
+
9624 WriteLineIndent(proxy + "(" + proxy + "&&) = delete;");
+
9625 WriteLineIndent("virtual ~" + proxy + "() = default;");
+
9626
+
9627 // Generate proxy operators
+
9628 WriteLine();
+
9629 WriteLineIndent(proxy + "& operator=(const " + proxy + "&) = delete;");
+
9630 WriteLineIndent(proxy + "& operator=(" + proxy + "&&) = delete;");
+
9631
+
9632 // Generate proxy handlers
+
9633 if (p->body)
+
9634 {
+
9635 WriteLine();
+
9636 Indent(-1);
+
9637 WriteLineIndent("protected:");
+
9638 Indent(1);
+
9639 WriteLineIndent("// Proxy handlers");
+
9640 for (const auto& s : p->body->structs)
+
9641 {
+
9642 if (s->message)
+
9643 {
+
9644 std::string struct_model = "FBE::" + *p->name + "::" + *s->name + model;
+
9645 WriteLineIndent("virtual void onProxy(" + struct_model + "& model, size_t type, const void* data, size_t size) {}");
+
9646 }
+
9647 }
+
9648 }
+
9649
+
9650 // Generate proxy message handler
+
9651 WriteLine();
+
9652 WriteLineIndent("// Receive message handler");
+
9653 WriteLineIndent("bool onReceive(size_t type, const void* data, size_t size) override;");
+
9654
+
9655 // Generate proxy models accessors
+
9656 if (p->body)
+
9657 {
+
9658 Indent(-1);
+
9659 WriteLine();
+
9660 WriteLineIndent("private:");
+
9661 Indent(1);
+
9662 WriteLineIndent("// Proxy models accessors");
+
9663 for (const auto& s : p->body->structs)
+
9664 if (s->message)
+
9665 WriteLineIndent("FBE::" + *p->name + "::" + *s->name + model + " " + *s->name + "Model;");
+
9666 }
+
9667
+
9668 // Generate proxy end
+
9669 Indent(-1);
+
9670 WriteLineIndent("};");
+
9671}
+
9672
+
9673void GeneratorCpp::GenerateProxy_Source(const std::shared_ptr<Package>& p, bool final)
+
9674{
+
9675 std::string proxy = (final ? "FinalProxy" : "Proxy");
+
9676 std::string model = (final ? "FinalModel" : "Model");
+
9677
+
9678 // Generate proxy message handler
+
9679 WriteLine();
+
9680 WriteLineIndent("bool " + proxy + "::onReceive(size_t type, const void* data, size_t size)");
+
9681 WriteLineIndent("{");
+
9682 Indent(1);
+
9683 if (p->body)
+
9684 {
+
9685 WriteLineIndent("switch (type)");
+
9686 WriteLineIndent("{");
+
9687 Indent(1);
+
9688 for (const auto& s : p->body->structs)
+
9689 {
+
9690 if (s->message)
+
9691 {
+
9692 std::string struct_name = "::" + *p->name + "::" + *s->name;
+
9693 WriteLineIndent("case FBE::" + *p->name + "::" + *s->name + model + "::fbe_type():");
+
9694 WriteLineIndent("{");
+
9695 Indent(1);
+
9696 WriteLineIndent("// Attach the FBE stream to the proxy model");
+
9697 WriteLineIndent(*s->name + "Model.attach(data, size);");
+
9698 WriteLineIndent("assert(" + *s->name + "Model.verify() && \"" + *p->name + "::" + *s->name + " validation failed!\");");
+
9699 WriteLine();
+
9700 WriteLineIndent("size_t fbe_begin = " + *s->name + "Model.model.get_begin();");
+
9701 WriteLineIndent("if (fbe_begin == 0)");
+
9702 Indent(1);
+
9703 WriteLineIndent("return false;");
+
9704 Indent(-1);
+
9705 WriteLineIndent("// Call proxy handler");
+
9706 WriteLineIndent("onProxy(" + *s->name + "Model, type, data, size);");
+
9707 WriteLineIndent(*s->name + "Model.model.get_end(fbe_begin);");
+
9708 WriteLineIndent("return true;");
+
9709 Indent(-1);
+
9710 WriteLineIndent("}");
+
9711 }
+
9712 }
+
9713 WriteLineIndent("default: break;");
+
9714 Indent(-1);
+
9715 WriteLineIndent("}");
+
9716 }
+
9717 if (p->import)
+
9718 {
+
9719 WriteLine();
+
9720 for (const auto& import : p->import->imports)
+
9721 {
+
9722 WriteLineIndent("if (" + *import + "::" + proxy + "::onReceive(type, data, size))");
+
9723 Indent(1);
+
9724 WriteLineIndent("return true;");
+
9725 Indent(-1);
+
9726 }
+
9727 }
+
9728 WriteLine();
+
9729 WriteLineIndent("return false;");
+
9730 Indent(-1);
+
9731 WriteLineIndent("}");
+
9732}
+
9733
+
9734void GeneratorCpp::GenerateClient_Header(const std::shared_ptr<Package>& p, bool final)
+
9735{
+
9736 std::string client = (final ? "FinalClient" : "Client");
+
9737 std::string sender = (final ? "FinalSender" : "Sender");
+
9738 std::string receiver = (final ? "FinalReceiver" : "Receiver");
+
9739
+
9740 // Generate client begin
+
9741 WriteLine();
+
9742 if (final)
+
9743 WriteLineIndent("// Fast Binary Encoding " + *p->name + " final client");
+
9744 else
+
9745 WriteLineIndent("// Fast Binary Encoding " + *p->name + " client");
+
9746 WriteLineIndent("class " + client + " : public virtual " + sender + ", protected virtual " + receiver);
+
9747 if (p->import)
+
9748 {
+
9749 Indent(1);
+
9750 for (const auto& import : p->import->imports)
+
9751 WriteLineIndent(", public virtual " + *import + "::" + client);
+
9752 Indent(-1);
+
9753 }
+
9754 WriteLineIndent("{");
+
9755 WriteLineIndent("public:");
+
9756 if (p->import)
+
9757 {
+
9758 Indent(1);
+
9759 for (const auto& import : p->import->imports)
+
9760 WriteLineIndent("typedef " + *import + "::" + client + " " + *import + client + ";");
+
9761 Indent(-1);
+
9762 WriteLine();
+
9763 }
+
9764 Indent(1);
+
9765
+
9766 // Generate client constructors
+
9767 WriteLineIndent(client + "() = default;");
+
9768 WriteLineIndent(client + "(const " + client + "&) = delete;");
+
9769 WriteLineIndent(client + "(" + client + "&&) = delete;");
+
9770 WriteLineIndent("virtual ~" + client + "() = default;");
+
9771
+
9772 // Generate client operators
+
9773 WriteLine();
+
9774 WriteLineIndent(client + "& operator=(const " + client + "&) = delete;");
+
9775 WriteLineIndent(client + "& operator=(" + client + "&&) = delete;");
+
9776
+
9777 // Generate imported clients accessors
+
9778 if (p->import)
+
9779 {
+
9780 WriteLine();
+
9781 WriteLineIndent("// Imported clients");
+
9782 for (const auto& import : p->import->imports)
+
9783 WriteLineIndent(*import + "::" + client + "& " + *import + "_client() noexcept { return *this; }");
+
9784 }
+
9785
+
9786 // Generate client reset method
+
9787 WriteLine();
+
9788 WriteLineIndent("// Reset client buffers");
+
9789 WriteLineIndent("void reset() { std::scoped_lock locker(this->_lock); reset_requests(); }");
+
9790
+
9791 // Generate watchdog method
+
9792 WriteLine();
+
9793 WriteLineIndent("// Watchdog for timeouts");
+
9794 WriteLineIndent("void watchdog(uint64_t utc) { std::scoped_lock locker(this->_lock); watchdog_requests(utc); }");
+
9795
+
9796 // Collect responses & rejects collections
+
9797 std::set<std::string> responses;
+
9798 std::map<std::string, bool> rejects;
+
9799 if (p->body)
+
9800 {
+
9801 for (const auto& s : p->body->structs)
+
9802 {
+
9803 if (s->message && s->request)
+
9804 {
+
9805 std::string response_name = (s->response) ? ConvertTypeName(*p->name, *s->response->response, false) : "";
+
9806
+
9807 if (!response_name.empty())
+
9808 {
+
9809 // Update responses and rejects cache
+
9810 responses.insert(*s->response->response);
+
9811 if (s->rejects)
+
9812 for (const auto& reject : s->rejects->rejects)
+
9813 rejects[*reject.reject] = reject.global;
+
9814 }
+
9815 }
+
9816 }
+
9817 }
+
9818
+
9819 // Generate request() methods
+
9820 if (p->body)
+
9821 {
+
9822 WriteLine();
+
9823 for (const auto& s : p->body->structs)
+
9824 {
+
9825 if (s->message && s->request)
+
9826 {
+
9827 std::string request_name = "::" + *p->name + "::" + *s->name;
+
9828 std::string response_name = (s->response) ? ConvertTypeName(*p->name, *s->response->response, false) : "";
+
9829 std::string response_field = (s->response) ? *s->response->response : "";
+
9830 CppCommon::StringUtils::ReplaceAll(response_field, ".", "");
+
9831
+
9832 if (response_name.empty())
+
9833 WriteLineIndent("std::future<void> request(const " + request_name + "& value, uint64_t timeout = 0);");
+
9834 else
+
9835 WriteLineIndent("std::future<" + response_name + "> request(const " + request_name + "& value, uint64_t timeout = 0);");
+
9836 }
+
9837 }
+
9838 }
+
9839
+
9840 // Generate client protected fields
+
9841 Indent(-1);
+
9842 WriteLine();
+
9843 WriteLineIndent("protected:");
+
9844 Indent(1);
+
9845 if (!p->import)
+
9846 {
+
9847 WriteLineIndent("std::mutex _lock;");
+
9848 WriteLineIndent("uint64_t _timestamp{0};");
+
9849 WriteLine();
+
9850 }
+
9851
+
9852 // Generate response handlers
+
9853 for (const auto& response : responses)
+
9854 {
+
9855 std::string response_name = ConvertTypeName(*p->name, response, false);
+
9856 WriteLineIndent("virtual bool onReceiveResponse(const " + response_name + "& response);");
+
9857 }
+
9858 if (!responses.empty())
+
9859 WriteLine();
+
9860
+
9861 // Generate remaining response handlers
+
9862 if (p->body)
+
9863 {
+
9864 bool found = false;
+
9865 std::set<std::string> cache;
+
9866 for (const auto& s : p->body->structs)
+
9867 {
+
9868 if (s->message)
+
9869 {
+
9870 std::string struct_response_name = ConvertTypeName(*p->name, *s->name, false);
+
9871 std::string struct_response_field = *s->name;
+
9872
+
9873 if ((responses.find(*s->name) == responses.end()) && (cache.find(struct_response_name) == cache.end()))
+
9874 {
+
9875 WriteLineIndent("virtual bool onReceiveResponse(const " + struct_response_name + "& response) { return false; }");
+
9876 cache.insert(struct_response_name);
+
9877 found = true;
+
9878 }
+
9879 }
+
9880 }
+
9881 if (found)
+
9882 WriteLine();
+
9883 }
+
9884
+
9885 // Generate reject handlers
+
9886 for (const auto& reject : rejects)
+
9887 {
+
9888 std::string reject_name = ConvertTypeName(*p->name, reject.first, false);
+
9889 WriteLineIndent("virtual bool onReceiveReject(const " + reject_name + "& reject);");
+
9890 }
+
9891 if (!rejects.empty())
+
9892 WriteLine();
+
9893
+
9894 // Generate remaining reject handlers
+
9895 if (p->body)
+
9896 {
+
9897 bool found = false;
+
9898 std::set<std::string> cache;
+
9899 for (const auto& s : p->body->structs)
+
9900 {
+
9901 if (s->message)
+
9902 {
+
9903 std::string struct_reject_name = ConvertTypeName(*p->name, *s->name, false);
+
9904 if ((rejects.find(*s->name) == rejects.end()) && (cache.find(struct_reject_name) == cache.end()))
+
9905 {
+
9906 WriteLineIndent("virtual bool onReceiveReject(const " + struct_reject_name + "& reject) { return false; }");
+
9907 cache.insert(struct_reject_name);
+
9908 found = true;
+
9909 }
+
9910 }
+
9911 }
+
9912 if (found)
+
9913 WriteLine();
+
9914 }
+
9915
+
9916 // Generate notify handlers
+
9917 if (p->body)
+
9918 {
+
9919 bool found = false;
+
9920 std::set<std::string> cache;
+
9921 for (const auto& s : p->body->structs)
+
9922 {
+
9923 if (s->message)
+
9924 {
+
9925 std::string struct_notify_name = ConvertTypeName(*p->name, *s->name, false);
+
9926 std::string struct_notify_field = *s->name;
+
9927 if (cache.find(struct_notify_name) == cache.end())
+
9928 {
+
9929 WriteLineIndent("virtual void onReceiveNotify(const " + struct_notify_name + "& notify) {}");
+
9930 cache.insert(struct_notify_name);
+
9931 found = true;
+
9932 }
+
9933 }
+
9934 }
+
9935 if (found)
+
9936 WriteLine();
+
9937 }
+
9938
+
9939 // Generate receive handlers
+
9940 if (p->body)
+
9941 {
+
9942 bool found = false;
+
9943 std::set<std::string> cache;
+
9944 for (const auto& s : p->body->structs)
+
9945 {
+
9946 if (s->message)
+
9947 {
+
9948 std::string struct_response_name = ConvertTypeName(*p->name, *s->name, false);
+
9949 std::string struct_response_field = *s->name;
+
9950
+
9951 if (cache.find(struct_response_name) == cache.end())
+
9952 {
+
9953 WriteLineIndent("virtual void onReceive(const " + struct_response_name + "& value) override { if (!onReceiveResponse(value) && !onReceiveReject(value)) onReceiveNotify(value); }");
+
9954 cache.insert(struct_response_name);
+
9955 found = true;
+
9956 }
+
9957 }
+
9958 }
+
9959 if (found)
+
9960 WriteLine();
+
9961 }
+
9962
+
9963 // Generate reset requests method
+
9964 WriteLineIndent("// Reset client requests");
+
9965 WriteLineIndent("virtual void reset_requests();");
+
9966
+
9967 // Generate watchdog requests method
+
9968 WriteLine();
+
9969 WriteLineIndent("// Watchdog client requests for timeouts");
+
9970 WriteLineIndent("virtual void watchdog_requests(uint64_t utc);");
+
9971
+
9972 // Generate client private fields
+
9973 if (!responses.empty())
+
9974 {
+
9975 Indent(-1);
+
9976 WriteLine();
+
9977 WriteLineIndent("private:");
+
9978 Indent(1);
+
9979 for (const auto& response : responses)
+
9980 {
+
9981 std::string response_name = ConvertTypeName(*p->name, response, false);
+
9982 std::string response_field = response;
+
9983 CppCommon::StringUtils::ReplaceAll(response_field, ".", "");
+
9984
+
9985 WriteLineIndent("std::unordered_map<FBE::uuid_t, std::tuple<uint64_t, uint64_t, std::promise<" + response_name + ">>> _requests_by_id_" + response_field + ";");
+
9986 WriteLineIndent("std::map<uint64_t, FBE::uuid_t> _requests_by_timestamp_" + response_field + ";");
+
9987 }
+
9988 }
+
9989
+
9990 // Generate client end
+
9991 Indent(-1);
+
9992 WriteLineIndent("};");
+
9993}
+
9994
+
9995void GeneratorCpp::GenerateClient_Source(const std::shared_ptr<Package>& p, bool final)
+
9996{
+
9997 std::string client = (final ? "FinalClient" : "Client");
+
9998 std::string sender = (final ? "FinalSender" : "Sender");
+
9999 std::string receiver = (final ? "FinalReceiver" : "Receiver");
+
10000
+
10001 // Collect responses & rejects collections
+
10002 std::set<std::string> responses;
+
10003 std::map<std::string, bool> rejects;
+
10004 if (p->body)
+
10005 {
+
10006 for (const auto& s : p->body->structs)
+
10007 {
+
10008 if (s->message && s->request)
+
10009 {
+
10010 std::string response_name = (s->response) ? ConvertTypeName(*p->name, *s->response->response, false) : "";
+
10011
+
10012 if (!response_name.empty())
+
10013 {
+
10014 // Update responses and rejects cache
+
10015 responses.insert(*s->response->response);
+
10016 if (s->rejects)
+
10017 for (const auto& reject : s->rejects->rejects)
+
10018 rejects[*reject.reject] = reject.global;
+
10019 }
+
10020 }
+
10021 }
+
10022 }
+
10023
+
10024 // Generate request() methods
+
10025 if (p->body)
+
10026 {
+
10027 for (const auto& s : p->body->structs)
+
10028 {
+
10029 if (s->message && s->request)
+
10030 {
+
10031 std::string request_name = "::" + *p->name + "::" + *s->name;
+
10032 std::string response_name = (s->response) ? ConvertTypeName(*p->name, *s->response->response, false) : "";
+
10033 std::string response_field = (s->response) ? *s->response->response : "";
+
10034 CppCommon::StringUtils::ReplaceAll(response_field, ".", "");
+
10035
+
10036 WriteLine();
+
10037 if (response_name.empty())
+
10038 {
+
10039 WriteLineIndent("std::future<void> " + client + "::request(const " + request_name + "& value, uint64_t timeout)");
+
10040 WriteLineIndent("{");
+
10041 Indent(1);
+
10042 WriteLineIndent("std::promise<void> promise;");
+
10043 WriteLineIndent("std::future<void> future = promise.get_future();");
+
10044 WriteLine();
+
10045 WriteLineIndent("// Send the request message");
+
10046 WriteLineIndent("size_t serialized = " + sender + "::send(value);");
+
10047 WriteLineIndent("if (serialized > 0)");
+
10048 Indent(1);
+
10049 WriteLineIndent("promise.set_value();");
+
10050 Indent(-1);
+
10051 WriteLineIndent("else");
+
10052 Indent(1);
+
10053 WriteLineIndent("promise.set_exception(std::make_exception_ptr(std::runtime_error(\"Send request failed!\")));");
+
10054 Indent(-1);
+
10055 WriteLine();
+
10056 WriteLineIndent("return future;");
+
10057 Indent(-1);
+
10058 WriteLineIndent("}");
+
10059 }
+
10060 else
+
10061 {
+
10062 WriteLineIndent("std::future<" + response_name + "> " + client + "::request(const " + request_name + "& value, uint64_t timeout)");
+
10063 WriteLineIndent("{");
+
10064 Indent(1);
+
10065 WriteLineIndent("std::scoped_lock locker(this->_lock);");
+
10066 WriteLine();
+
10067 WriteLineIndent("std::promise<" + response_name + "> promise;");
+
10068 WriteLineIndent("std::future<" + response_name + "> future = promise.get_future();");
+
10069 WriteLine();
+
10070 WriteLineIndent("uint64_t current = utc();");
+
10071 WriteLine();
+
10072 WriteLineIndent("// Send the request message");
+
10073 WriteLineIndent("size_t serialized = " + sender + "::send(value);");
+
10074 WriteLineIndent("if (serialized > 0)");
+
10075 WriteLineIndent("{");
+
10076 Indent(1);
+
10077 WriteLineIndent("// Calculate the unique timestamp");
+
10078 WriteLineIndent("this->_timestamp = (current <= this->_timestamp) ? this->_timestamp + 1 : current;");
+
10079 WriteLine();
+
10080 WriteLineIndent("// Register the request");
+
10081 WriteLineIndent("_requests_by_id_" + response_field + ".insert(std::make_pair(value.id, std::make_tuple(this->_timestamp, timeout * 1000000, std::move(promise))));");
+
10082 WriteLineIndent("if (timeout > 0)");
+
10083 Indent(1);
+
10084 WriteLineIndent("_requests_by_timestamp_" + response_field + ".insert(std::make_pair(this->_timestamp, value.id));");
+
10085 Indent(-1);
+
10086 Indent(-1);
+
10087 WriteLineIndent("}");
+
10088 WriteLineIndent("else");
+
10089 Indent(1);
+
10090 WriteLineIndent("promise.set_exception(std::make_exception_ptr(std::runtime_error(\"Send request failed!\")));");
+
10091 Indent(-1);
+
10092 WriteLine();
+
10093 WriteLineIndent("return future;");
+
10094 Indent(-1);
+
10095 WriteLineIndent("}");
+
10096 }
+
10097 }
+
10098 }
+
10099 }
+
10100
+
10101 // Generate response handlers
+
10102 for (const auto& response : responses)
+
10103 {
+
10104 std::string response_name = ConvertTypeName(*p->name, response, false);
+
10105 std::string response_field = response;
+
10106
+
10107 WriteLine();
+
10108 WriteLineIndent("bool " + client + "::onReceiveResponse(const " + response_name + "& response)");
+
10109 WriteLineIndent("{");
+
10110 Indent(1);
+
10111 if (p->body)
+
10112 {
+
10113 std::set<std::string> cache;
+
10114 WriteLineIndent("std::scoped_lock locker(this->_lock);");
+
10115 WriteLine();
+
10116 for (const auto& s : p->body->structs)
+
10117 {
+
10118 if (s->message && s->response)
+
10119 {
+
10120 std::string struct_response_name = ConvertTypeName(*p->name, *s->response->response, false);
+
10121 std::string struct_response_field = *s->response->response;
+
10122 CppCommon::StringUtils::ReplaceAll(struct_response_field, ".", "");
+
10123
+
10124 if ((struct_response_name == response_name) && (cache.find(struct_response_name) == cache.end()))
+
10125 {
+
10126 WriteLineIndent("auto it_" + struct_response_field + " = _requests_by_id_" + struct_response_field + ".find(response.id);");
+
10127 WriteLineIndent("if (it_" + struct_response_field + " != _requests_by_id_" + struct_response_field + ".end())");
+
10128 WriteLineIndent("{");
+
10129 Indent(1);
+
10130 WriteLineIndent("auto timestamp = std::get<0>(it_" + struct_response_field + "->second);");
+
10131 WriteLineIndent("[[maybe_unused]] auto timespan = std::get<1>(it_" + struct_response_field + "->second);");
+
10132 WriteLineIndent("auto& promise = std::get<2>(it_" + struct_response_field + "->second);");
+
10133 WriteLineIndent("promise.set_value(response);");
+
10134 WriteLineIndent("_requests_by_id_" + struct_response_field + ".erase(response.id);");
+
10135 WriteLineIndent("_requests_by_timestamp_" + struct_response_field + ".erase(timestamp);");
+
10136 WriteLineIndent("return true;");
+
10137 cache.insert(struct_response_name);
+
10138 Indent(-1);
+
10139 WriteLineIndent("}");
+
10140 WriteLine();
+
10141 }
+
10142 }
+
10143 }
+
10144 }
+
10145 WriteLineIndent("return false;");
+
10146 Indent(-1);
+
10147 WriteLineIndent("}");
+
10148 }
+
10149
+
10150 // Generate reject handlers
+
10151 for (const auto& reject : rejects)
+
10152 {
+
10153 std::string reject_name = ConvertTypeName(*p->name, reject.first, false);
+
10154 std::string reject_field = reject.first;
+
10155 bool global = reject.second;
+
10156 bool imported = CppCommon::StringUtils::ReplaceAll(reject_field, ".", "");
+
10157
+
10158 WriteLine();
+
10159 WriteLineIndent("bool " + client + "::onReceiveReject(const " + reject_name + "& reject)");
+
10160 WriteLineIndent("{");
+
10161 Indent(1);
+
10162 if (global)
+
10163 {
+
10164 if (p->import)
+
10165 {
+
10166 for (const auto& import : p->import->imports)
+
10167 {
+
10168 WriteLineIndent("if (" + *import + client + "::onReceiveReject(reject))");
+
10169 Indent(1);
+
10170 WriteLineIndent("return true;");
+
10171 Indent(-1);
+
10172 }
+
10173 WriteLine();
+
10174 }
+
10175 }
+
10176 else if (imported)
+
10177 {
+
10178 std::string ns = "";
+
10179 std::string t = reject.first;
+
10180 std::string type = reject.first;
+
10181
+
10182 size_t pos = type.find_last_of('.');
+
10183 if (pos != std::string::npos)
+
10184 {
+
10185 ns.assign(type, 0, pos);
+
10186 t.assign(type, pos + 1, type.size() - pos);
+
10187 }
+
10188
+
10189 WriteLineIndent("if (" + ns + client + "::onReceiveReject(reject))");
+
10190 Indent(1);
+
10191 WriteLineIndent("return true;");
+
10192 Indent(-1);
+
10193 WriteLine();
+
10194 }
+
10195 if (p->body)
+
10196 {
+
10197 std::set<std::string> cache;
+
10198 WriteLineIndent("std::scoped_lock locker(this->_lock);");
+
10199 WriteLine();
+
10200 for (const auto& s : p->body->structs)
+
10201 {
+
10202 if (s->message && s->response && s->rejects)
+
10203 {
+
10204 for (const auto& r : s->rejects->rejects)
+
10205 {
+
10206 std::string struct_response_name = ConvertTypeName(*p->name, *s->response->response, false);
+
10207 std::string struct_response_field = *s->response->response;
+
10208 CppCommon::StringUtils::ReplaceAll(struct_response_field, ".", "");
+
10209
+
10210 std::string struct_reject_name = ConvertTypeName(*p->name, *r.reject, false);
+
10211 std::string struct_reject_field = *r.reject;
+
10212 CppCommon::StringUtils::ReplaceAll(struct_reject_field, ".", "");
+
10213
+
10214 if ((struct_reject_name == reject_name) && (cache.find(struct_response_field) == cache.end()))
+
10215 {
+
10216 WriteLineIndent("auto it_" + struct_response_field + " = _requests_by_id_" + struct_response_field + ".find(reject.id);");
+
10217 WriteLineIndent("if (it_" + struct_response_field + " != _requests_by_id_" + struct_response_field + ".end())");
+
10218 WriteLineIndent("{");
+
10219 Indent(1);
+
10220 WriteLineIndent("auto timestamp = std::get<0>(it_" + struct_response_field + "->second);");
+
10221 WriteLineIndent("[[maybe_unused]] auto timespan = std::get<1>(it_" + struct_response_field + "->second);");
+
10222 WriteLineIndent("auto& promise = std::get<2>(it_" + struct_response_field + "->second);");
+
10223 WriteLineIndent("promise.set_exception(std::make_exception_ptr(std::runtime_error(reject.string())));");
+
10224 WriteLineIndent("_requests_by_id_" + struct_response_field + ".erase(reject.id);");
+
10225 WriteLineIndent("_requests_by_timestamp_" + struct_response_field + ".erase(timestamp);");
+
10226 WriteLineIndent("return true;");
+
10227 cache.insert(struct_response_field);
+
10228 Indent(-1);
+
10229 WriteLineIndent("}");
+
10230 WriteLine();
+
10231 }
+
10232 }
+
10233 }
+
10234 }
+
10235 }
+
10236 WriteLineIndent("return false;");
+
10237 Indent(-1);
+
10238 WriteLineIndent("}");
+
10239 }
+
10240
+
10241 // Generate reset requests method
+
10242 WriteLine();
+
10243 WriteLineIndent("void " + client + "::reset_requests()");
+
10244 WriteLineIndent("{");
+
10245 Indent(1);
+
10246 if (p->import)
+
10247 {
+
10248 for (const auto& import : p->import->imports)
+
10249 WriteLineIndent(*import + "::" + client + "::reset_requests();");
+
10250 }
+
10251 else
+
10252 {
+
10253 WriteLineIndent(sender + "::reset();");
+
10254 WriteLineIndent(receiver + "::reset();");
+
10255 }
+
10256 for (const auto& response : responses)
+
10257 {
+
10258 std::string response_name = ConvertTypeName(*p->name, response, false);
+
10259 std::string response_field = response;
+
10260 CppCommon::StringUtils::ReplaceAll(response_field, ".", "");
+
10261
+
10262 WriteLine();
+
10263 WriteLineIndent("for (auto& request : _requests_by_id_" + response_field + ")");
+
10264 Indent(1);
+
10265 WriteLineIndent("std::get<2>(request.second).set_exception(std::make_exception_ptr(std::runtime_error(\"Reset client!\")));");
+
10266 Indent(-1);
+
10267 WriteLineIndent("_requests_by_id_" + response_field + ".clear();");
+
10268 WriteLineIndent("_requests_by_timestamp_" + response_field + ".clear();");
+
10269 }
+
10270 Indent(-1);
+
10271 WriteLineIndent("}");
+
10272
+
10273 // Generate watchdog requests method
+
10274 WriteLine();
+
10275 WriteLineIndent("void " + client + "::watchdog_requests(uint64_t utc)");
+
10276 WriteLineIndent("{");
+
10277 Indent(1);
+
10278 if (p->import)
+
10279 {
+
10280 for (const auto& import : p->import->imports)
+
10281 WriteLineIndent(*import + "::" + client + "::watchdog_requests(utc);");
+
10282 WriteLine();
+
10283 }
+
10284 for (const auto& response : responses)
+
10285 {
+
10286 std::string response_name = ConvertTypeName(*p->name, response, false);
+
10287 std::string response_field = response;
+
10288 CppCommon::StringUtils::ReplaceAll(response_field, ".", "");
+
10289
+
10290 WriteLineIndent("auto it_request_by_timestamp_" + response_field + " = _requests_by_timestamp_" + response_field + ".begin();");
+
10291 WriteLineIndent("while (it_request_by_timestamp_" + response_field + " != _requests_by_timestamp_" + response_field + ".end())");
+
10292 WriteLineIndent("{");
+
10293 Indent(1);
+
10294 WriteLineIndent("auto& it_request_by_id_" + response_field + " = _requests_by_id_" + response_field + "[it_request_by_timestamp_" + response_field + "->second];");
+
10295 WriteLineIndent("auto id = it_request_by_timestamp_" + response_field + "->second;");
+
10296 WriteLineIndent("auto timestamp = std::get<0>(it_request_by_id_" + response_field + ");");
+
10297 WriteLineIndent("auto timespan = std::get<1>(it_request_by_id_" + response_field + ");");
+
10298 WriteLineIndent("if ((timestamp + timespan) <= utc)");
+
10299 WriteLineIndent("{");
+
10300 Indent(1);
+
10301 WriteLineIndent("auto& promise = std::get<2>(it_request_by_id_" + response_field + ");");
+
10302 WriteLineIndent("promise.set_exception(std::make_exception_ptr(std::runtime_error(\"Timeout!\")));");
+
10303 WriteLineIndent("_requests_by_id_" + response_field + ".erase(id);");
+
10304 WriteLineIndent("_requests_by_timestamp_" + response_field + ".erase(timestamp);");
+
10305 WriteLineIndent("it_request_by_timestamp_" + response_field + " = _requests_by_timestamp_" + response_field + ".begin();");
+
10306 WriteLineIndent("continue;");
+
10307 Indent(-1);
+
10308 WriteLineIndent("}");
+
10309 WriteLineIndent("else");
+
10310 Indent(1);
+
10311 WriteLineIndent("break;");
+
10312 Indent(-1);
+
10313 Indent(-1);
+
10314 WriteLineIndent("}");
+
10315 WriteLine();
+
10316 }
+
10317 Indent(-1);
+
10318 WriteLineIndent("}");
+
10319}
+
10320
+
10321bool GeneratorCpp::IsKnownType(const std::string& type)
+
10322{
+
10323 return ((type == "bool") ||
+
10324 (type == "byte") || (type == "bytes") ||
+
10325 (type == "char") || (type == "wchar") ||
+
10326 (type == "int8") || (type == "uint8") ||
+
10327 (type == "int16") || (type == "uint16") ||
+
10328 (type == "int32") || (type == "uint32") ||
+
10329 (type == "int64") || (type == "uint64") ||
+
10330 (type == "float") || (type == "double") ||
+
10331 (type == "decimal") || (type == "string") ||
+
10332 (type == "timestamp") || (type == "uuid"));
+
10333}
+
10334
+
10335bool GeneratorCpp::IsPrimitiveType(const std::string& type, bool optional)
+
10336{
+
10337 if (optional)
+
10338 return false;
+
10339
+
10340 return ((type == "bool") || (type == "byte") ||
+
10341 (type == "char") || (type == "wchar") ||
+
10342 (type == "int8") || (type == "uint8") ||
+
10343 (type == "int16") || (type == "uint16") ||
+
10344 (type == "int32") || (type == "uint32") ||
+
10345 (type == "int64") || (type == "uint64") ||
+
10346 (type == "float") || (type == "double") ||
+
10347 (type == "timestamp"));
+
10348}
+
10349
+
10350std::string GeneratorCpp::ConvertEnumType(const std::string& type)
+
10351{
+
10352 if (type == "byte")
+
10353 return "uint8_t";
+
10354 else if (type == "char")
+
10355 return "uint8_t";
+
10356 else if (type == "wchar")
+
10357 return "uint32_t";
+
10358 else if (type == "int8")
+
10359 return "int8_t";
+
10360 else if (type == "uint8")
+
10361 return "uint8_t";
+
10362 else if (type == "int16")
+
10363 return "int16_t";
+
10364 else if (type == "uint16")
+
10365 return "uint16_t";
+
10366 else if (type == "int32")
+
10367 return "int32_t";
+
10368 else if (type == "uint32")
+
10369 return "uint32_t";
+
10370 else if (type == "int64")
+
10371 return "int64_t";
+
10372 else if (type == "uint64")
+
10373 return "uint64_t";
+
10374
+
10375 yyerror("Unsupported enum base type - " + type);
+
10376 return "";
+
10377}
+
10378
+
10379std::string GeneratorCpp::ConvertTypeName(const std::string& package, const std::string& type, bool optional)
+
10380{
+
10381 if (optional)
+
10382 return "std::optional<" + ConvertTypeName(package, type, false) + ">";
+
10383
+
10384 if (type == "bool")
+
10385 return "bool";
+
10386 else if (type == "byte")
+
10387 return "uint8_t";
+
10388 else if (type == "bytes")
+
10389 return "FBE::buffer_t";
+
10390 else if (type == "char")
+
10391 return "char";
+
10392 else if (type == "wchar")
+
10393 return "wchar_t";
+
10394 else if (type == "int8")
+
10395 return "int8_t";
+
10396 else if (type == "uint8")
+
10397 return "uint8_t";
+
10398 else if (type == "int16")
+
10399 return "int16_t";
+
10400 else if (type == "uint16")
+
10401 return "uint16_t";
+
10402 else if (type == "int32")
+
10403 return "int32_t";
+
10404 else if (type == "uint32")
+
10405 return "uint32_t";
+
10406 else if (type == "int64")
+
10407 return "int64_t";
+
10408 else if (type == "uint64")
+
10409 return "uint64_t";
+
10410 else if (type == "float")
+
10411 return "float";
+
10412 else if (type == "double")
+
10413 return "double";
+
10414 else if (type == "decimal")
+
10415 return "FBE::decimal_t";
+
10416 else if (type == "string")
+
10417 return "std::string";
+
10418 else if (type == "timestamp")
+
10419 return "uint64_t";
+
10420 else if (type == "uuid")
+
10421 return "FBE::uuid_t";
+
10422
+
10423 std::string result = type;
+
10424 bool pkg = !CppCommon::StringUtils::ReplaceAll(result, ".", "::");
+
10425 return (pkg ? ("::" + package) : "") + "::" + result;
+
10426}
+
10427
+
10428std::string GeneratorCpp::ConvertTypeName(const std::string& package, const StructField& field)
+
10429{
+
10430 if (field.array)
+
10431 return "std::array<" + ConvertTypeName(package, *field.type, field.optional) + ", " + std::to_string(field.N) + ">";
+
10432 else if (field.vector)
+
10433 return "std::vector<" + ConvertTypeName(package, *field.type, field.optional) + ">";
+
10434 else if (field.list)
+
10435 return "std::list<" + ConvertTypeName(package, *field.type, field.optional) + ">";
+
10436 else if (field.set)
+
10437 return "std::set<" + ConvertTypeName(package, *field.key, false) + ">";
+
10438 else if (field.map)
+
10439 return "std::map<" + ConvertTypeName(package, *field.key, false) + ", " + ConvertTypeName(package, *field.type, field.optional) +">";
+
10440 else if (field.hash)
+
10441 return "std::unordered_map<" + ConvertTypeName(package, *field.key, false) + ", " + ConvertTypeName(package, *field.type, field.optional) +">";
+
10442
+
10443 return ConvertTypeName(package, *field.type, field.optional);
+
10444}
+
10445
+
10446std::string GeneratorCpp::ConvertTypeNameAsArgument(const std::string& package, const StructField& field)
+
10447{
+
10448 if (field.optional || field.array || field.vector || field.list || field.set || field.map || field.hash)
+
10449 return "const " + ConvertTypeName(package, field) + "&";
+
10450
+
10451 if (IsPrimitiveType(*field.type, false))
+
10452 return ConvertTypeName(package, field);
+
10453
+
10454 return "const " + ConvertTypeName(package, field) + "&";
+
10455}
+
10456
+
10457std::string GeneratorCpp::ConvertConstant(const std::string& type, const std::string& value, bool optional)
+
10458{
+
10459 if (value == "true")
+
10460 return "true";
+
10461 else if (value == "false")
+
10462 return "false";
+
10463 else if (value == "null")
+
10464 return optional ? "std::nullopt" : "std::nullptr";
+
10465 else if (value == "min")
+
10466 {
+
10467 if ((type == "byte") || (type == "uint8") || (type == "uint16") || (type == "uint32") || (type == "uint64"))
+
10468 return ConvertConstantPrefix(type) + "0" + ConvertConstantSuffix(type);
+
10469 else if (type == "int8")
+
10470 return ConvertConstantPrefix(type) + "-128" + ConvertConstantSuffix(type);
+
10471 else if (type == "int16")
+
10472 return ConvertConstantPrefix(type) + "-32768" + ConvertConstantSuffix(type);
+
10473 else if (type == "int32")
+
10474 return ConvertConstantPrefix(type) + "-2147483648ll" + ConvertConstantSuffix(type);
+
10475 else if (type == "int64")
+
10476 return ConvertConstantPrefix(type) + "-9223372036854775808ll" + ConvertConstantSuffix(type);
+
10477
+
10478 yyerror("Unsupported type " + type + " for 'min' constant");
+
10479 return "";
+
10480 }
+
10481 else if (value == "max")
+
10482 {
+
10483 if (type == "byte")
+
10484 return ConvertConstantPrefix(type) + "255" + ConvertConstantSuffix(type);
+
10485 else if (type == "int8")
+
10486 return ConvertConstantPrefix(type) + "127" + ConvertConstantSuffix(type);
+
10487 else if (type == "uint8")
+
10488 return ConvertConstantPrefix(type) + "255" + ConvertConstantSuffix(type);
+
10489 else if (type == "int16")
+
10490 return ConvertConstantPrefix(type) + "32767" + ConvertConstantSuffix(type);
+
10491 else if (type == "uint16")
+
10492 return ConvertConstantPrefix(type) + "65535" + ConvertConstantSuffix(type);
+
10493 else if (type == "int32")
+
10494 return ConvertConstantPrefix(type) + "2147483647" + ConvertConstantSuffix(type);
+
10495 else if (type == "uint32")
+
10496 return ConvertConstantPrefix(type) + "4294967295" + ConvertConstantSuffix(type);
+
10497 else if (type == "int64")
+
10498 return ConvertConstantPrefix(type) + "9223372036854775807" + ConvertConstantSuffix(type);
+
10499 else if (type == "uint64")
+
10500 return ConvertConstantPrefix(type) + "18446744073709551615" + ConvertConstantSuffix(type);
+
10501
+
10502 yyerror("Unsupported type " + type + " for 'max' constant");
+
10503 return "";
+
10504 }
+
10505 else if (value == "epoch")
+
10506 return "FBE::epoch()";
+
10507 else if (value == "utc")
+
10508 return "FBE::utc()";
+
10509 else if (value == "uuid0")
+
10510 return "FBE::uuid_t::nil()";
+
10511 else if (value == "uuid1")
+
10512 return "FBE::uuid_t::sequential()";
+
10513 else if (value == "uuid4")
+
10514 return "FBE::uuid_t::random()";
+
10515
+
10516 if (IsKnownType(type))
+
10517 return ConvertConstantPrefix(type) + value + ConvertConstantSuffix(type);
+
10518
+
10519 bool first = true;
+
10520 std::string result;
+
10521 auto items = CppCommon::StringUtils::Split(value, "|");
+
10522 for (auto& item : items)
+
10523 {
+
10524 bool pkg = (CppCommon::StringUtils::CountAll(item, ".") > 1);
+
10525 CppCommon::StringUtils::ReplaceAll(item, ".", "::");
+
10526 result += (!first ? " | " : "");
+
10527 result += (pkg ? "::" : "") + item;
+
10528 first = false;
+
10529 }
+
10530
+
10531 return result;
+
10532}
+
10533
+
10534std::string GeneratorCpp::ConvertConstantPrefix(const std::string& type)
+
10535{
+
10536 if (type == "bool")
+
10537 return "(bool)";
+
10538 else if (type == "byte")
+
10539 return "(uint8_t)";
+
10540 else if (type == "char")
+
10541 return "(char)";
+
10542 else if (type == "wchar")
+
10543 return "(wchar_t)";
+
10544 else if (type == "int8")
+
10545 return "(int8_t)";
+
10546 else if (type == "uint8")
+
10547 return "(uint8_t)";
+
10548 else if (type == "int16")
+
10549 return "(int16_t)";
+
10550 else if (type == "uint16")
+
10551 return "(uint16_t)";
+
10552 else if (type == "int32")
+
10553 return "(int32_t)";
+
10554 else if (type == "uint32")
+
10555 return "(uint32_t)";
+
10556 else if (type == "int64")
+
10557 return "(int64_t)";
+
10558 else if (type == "uint64")
+
10559 return "(uint64_t)";
+
10560 else if (type == "float")
+
10561 return "(float)";
+
10562 else if (type == "double")
+
10563 return "(double)";
+
10564 else if (type == "decimal")
+
10565 return "FBE::decimal_t(";
+
10566 else if (type == "timestamp")
+
10567 return "(uint64_t)";
+
10568 else if (type == "uuid")
+
10569 return "FBE::uuid_t(";
+
10570
+
10571 return "";
+
10572}
+
10573
+
10574std::string GeneratorCpp::ConvertConstantSuffix(const std::string& type)
+
10575{
+
10576 if ((type == "byte") || (type == "uint8") || (type == "uint16"))
+
10577 return "u";
+
10578 else if ((type == "int32") || (type == "int64"))
+
10579 return "ll";
+
10580 else if ((type == "uint32") || (type == "uint64") || (type == "timestamp"))
+
10581 return "ull";
+
10582 else if (type == "float")
+
10583 return "f";
+
10584 else if ((type == "decimal") || (type == "uuid"))
+
10585 return ")";
+
10586
+
10587 return "";
+
10588}
+
10589
+
10590std::string GeneratorCpp::ConvertDefault(const std::string& package, const std::string& type)
+
10591{
+
10592 if (type == "bool")
+
10593 return "false";
+
10594 else if (type == "bytes")
+
10595 return "";
+
10596 else if (type == "char")
+
10597 return "'\\0'";
+
10598 else if (type == "wchar")
+
10599 return "L'\\0'";
+
10600 else if ((type == "byte") || (type == "int8") || (type == "uint8") || (type == "int16") || (type == "uint16") || (type == "int32") || (type == "uint32") || (type == "int64") || (type == "uint64") || (type == "timestamp"))
+
10601 return ConvertConstantPrefix(type) + "0" + ConvertConstantSuffix(type);
+
10602 else if (type == "float")
+
10603 return "0.0f";
+
10604 else if (type == "double")
+
10605 return "0.0";
+
10606 else if (type == "decimal")
+
10607 return "FBE::decimal_t()";
+
10608 else if (type == "string")
+
10609 return "\"\"";
+
10610 else if (type == "uuid")
+
10611 return "FBE::uuid_t::nil()";
+
10612
+
10613 std::string result = type + "()";
+
10614 bool pkg = !CppCommon::StringUtils::ReplaceAll(result, ".", "::");
+
10615 return (pkg ? ("::" + package) : "") + "::" + result;
+
10616}
+
10617
+
10618std::string GeneratorCpp::ConvertDefault(const std::string& package, const StructField& field)
+
10619{
+
10620 if (field.value)
+
10621 return ConvertConstant(*field.type, *field.value, field.optional);
+
10622
+
10623 if (field.array || field.vector || field.list || field.set || field.map || field.hash)
+
10624 return "";
+
10625 else if (field.optional)
+
10626 return "std::nullopt";
+
10627
+
10628 return ConvertDefault(package, *field.type);
+
10629}
+
10630
+
10631std::string GeneratorCpp::ConvertOutputStreamType(const std::string& type, const std::string& name, bool optional)
+
10632{
+
10633 if (type == "bool")
+
10634 return "(" + std::string(optional ? "*" : "") + name + " ? \"true\" : \"false\"" + ")";
+
10635 else if ((type == "byte") || (type == "int8") || (type == "uint8"))
+
10636 return "(int)" + std::string(optional ? "*" : "") + name;
+
10637 else if (type == "bytes")
+
10638 return "\"bytes[\" << " + name + std::string(optional ? "->" : ".") + "size() << \"]\"";
+
10639 else if (type == "char")
+
10640 return "\"'\" << " + std::string(optional ? "*" : "") + name + " << \"'\"";
+
10641 else if (type == "wchar")
+
10642 return "\"'\" << (char)" + std::string(optional ? "*" : "") + name + " << \"'\"";
+
10643 else if ((type == "string") || (type == "uuid"))
+
10644 return "\"\\\"\" << " + std::string(optional ? "*" : "") + name + " << \"\\\"\"";
+
10645 else
+
10646 return std::string(optional ? "*" : "") + name;
+
10647}
+
10648
+
10649std::string GeneratorCpp::ConvertOutputStreamValue(const std::string& type, const std::string& name, bool optional, bool separate)
+
10650{
+
10651 std::string comma = separate ? "<< std::string(first ? \"\" : \",\") " : "";
+
10652
+
10653 if (optional)
+
10654 return "if (" + name + ") stream " + comma + "<< " + ConvertOutputStreamType(type, name, true) + "; else stream " + comma + "<< \"null\";";
+
10655 else
+
10656 return "stream " + comma + "<< " + ConvertOutputStreamType(type, name, false) + ";";
+
10657}
+
10658
+
10659std::string GeneratorCpp::ConvertLoggingStreamType(const std::string& type, const std::string& name, bool optional)
+
10660{
+
10661 if (type == "bool")
+
10662 return "StoreList(" + std::string(optional ? "*" : "") + name + " ? \"true\" : \"false\"" + ")";
+
10663 else if ((type == "byte") || (type == "int8") || (type == "uint8"))
+
10664 return "StoreList((int)" + std::string(optional ? "*" : "") + name + ")";
+
10665 else if (type == "bytes")
+
10666 return "StoreList(\"bytes[\").StoreList(" + name + std::string(optional ? "->" : ".") + "size()).StoreList(\"]\")";
+
10667 else if ((type == "char") || (type == "wchar"))
+
10668 return "StoreList(\"'\").StoreList(" + std::string(optional ? "*" : "") + name + ").StoreList(\"'\")";
+
10669 else if ((type == "string") || (type == "uuid"))
+
10670 return "StoreList(\"\\\"\").StoreList(" + std::string(optional ? "*" : "") + name + ").StoreList(\"\\\"\")";
+
10671 else
+
10672 return "StoreList(" + std::string(optional ? "*" : "") + name + ")";
+
10673}
+
10674
+
10675std::string GeneratorCpp::ConvertLoggingStreamValue(const std::string& type, const std::string& name, bool optional, bool separate)
+
10676{
+
10677 std::string comma = separate ? "StoreList(first ? \"\" : \",\")." : "";
+
10678
+
10679 if (optional)
+
10680 return "if (" + name + ") record." + comma + ConvertLoggingStreamType(type, name, true) + "; else record." + comma + "StoreList(\"null\");";
+
10681 else
+
10682 return "record." + comma + ConvertLoggingStreamType(type, name, false) + ";";
+
10683}
+
10684
+
10685} // namespace FBE
+
bool Proto() const noexcept
+
bool Logging() const noexcept
+
bool JSON() const noexcept
+
void Generate(const std::shared_ptr< Package > &package) override
+
bool Final() const noexcept
+
void WriteBegin()
Definition generator.inl:24
+
void Store(const CppCommon::Path &filename)
Definition generator.cpp:17
+
static std::string EndLine()
Definition generator.inl:68
+
std::string _input
Definition generator.h:25
+ +
std::string _output
Definition generator.h:26
+
void WriteLineIndent(const std::string &str)
Definition generator.inl:58
+
void Write(const std::string &str)
Definition generator.inl:29
+ +
void Indent(int count)
Definition generator.inl:19
+
void WriteIndent()
Definition generator.inl:34
+
int yyerror(const char *msg)
Definition fbe.l:163
+
Fast binary encoding C++ generator definition.
+
Definition fbe.h:33
+
const char version[]
Definition version.h:15
+ +
+ + +
+ + diff --git a/documents/html/generator__cpp_8h.html b/documents/html/generator__cpp_8h.html new file mode 100644 index 000000000..f5921e8df --- /dev/null +++ b/documents/html/generator__cpp_8h.html @@ -0,0 +1,114 @@ + + + + + + + +FastBinaryEncoding: include/generator_cpp.h File Reference + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+ +
generator_cpp.h File Reference
+
+
+ +

Fast binary encoding C++ generator definition. +More...

+
#include "generator.h"
+
+

Go to the source code of this file.

+ + + +

+Classes

class  FBE::GeneratorCpp
+ + +

+Namespaces

namespace  FBE
+

Detailed Description

+

Fast binary encoding C++ generator definition.

+
Author
Ivan Shynkarenka
+
Date
20.04.2018
+ + +

Definition in file generator_cpp.h.

+
+ + +
+ + diff --git a/documents/html/generator__cpp_8h_source.html b/documents/html/generator__cpp_8h_source.html new file mode 100644 index 000000000..f0acf8e25 --- /dev/null +++ b/documents/html/generator__cpp_8h_source.html @@ -0,0 +1,290 @@ + + + + + + + +FastBinaryEncoding: include/generator_cpp.h Source File + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+
generator_cpp.h
+
+
+Go to the documentation of this file.
1
+
8
+
9#ifndef GENERATOR_CPP_H
+
10#define GENERATOR_CPP_H
+
11
+
12#include "generator.h"
+
13
+
14namespace FBE {
+
15
+
+
16class GeneratorCpp : public Generator
+
17{
+
18public:
+ +
20
+
21 // Final protocol code generation
+
22 bool Final() const noexcept { return _final; }
+
23 GeneratorCpp& Final(bool final) noexcept { _final = final; return *this; }
+
24
+
25 // JSON protocol code generation
+
26 bool JSON() const noexcept { return _json; }
+
27 GeneratorCpp& JSON(bool json) noexcept { _json = json; return *this; }
+
28
+
29 // Sender/Receiver protocol code generation
+
30 bool Proto() const noexcept { return _proto; }
+
31 GeneratorCpp& Proto(bool proto) noexcept { _proto = proto; return *this; }
+
32
+
33 // Logging protocol code generation
+
34 bool Logging() const noexcept { return _logging; }
+
35 GeneratorCpp& Logging(bool logging) noexcept { _logging = logging; return *this; }
+
36
+
37 void Generate(const std::shared_ptr<Package>& package) override;
+
38
+
39private:
+
40 bool _final{false};
+
41 bool _json{false};
+
42 bool _proto{false};
+
43 bool _logging{false};
+
44
+
45 void GenerateHeader(const std::string& source);
+
46 void GenerateInline(const std::string& source);
+
47 void GenerateSource(const std::string& source);
+
48 void GenerateWarningsHeader();
+
49 void GenerateWarningsFooter();
+
50 void GenerateFooter();
+
51 void GenerateImports();
+
52 void GenerateImportsSource();
+
53 void GenerateImports(const std::string& source);
+
54 void GenerateImports(const std::shared_ptr<Package>& p);
+
55 void GenerateImportsModels(const std::shared_ptr<Package>& p, bool final);
+
56 void GenerateImportsProtocol(const std::shared_ptr<Package>& p, bool final);
+
57 void GenerateImportsJson();
+
58 void GenerateImportsJson(const std::shared_ptr<Package>& p);
+
59 void GenerateBufferWrapper_Header();
+
60 void GenerateBufferWrapper_Source();
+
61 void GenerateDecimalWrapper_Header();
+
62 void GenerateFlagsWrapper_Header();
+
63 void GenerateTimeWrapper_Header();
+
64 void GenerateTimeWrapper_Source();
+
65 void GenerateUUIDWrapper_Header();
+
66 void GenerateUUIDWrapper_Source();
+
67 void GenerateFBEBuffer_Header();
+
68 void GenerateFBEBuffer_Source();
+
69 void GenerateFBEBaseModel_Header();
+
70 void GenerateFBEFieldModel_Header();
+
71 void GenerateFBEFieldModel_Inline();
+
72 void GenerateFBEFieldModelDecimal_Header();
+
73 void GenerateFBEFieldModelDecimal_Source();
+
74 void GenerateFBEFieldModelUUID_Header();
+
75 void GenerateFBEFieldModelUUID_Source();
+
76 void GenerateFBEFieldModelBytes_Header();
+
77 void GenerateFBEFieldModelBytes_Source();
+
78 void GenerateFBEFieldModelString_Header();
+
79 void GenerateFBEFieldModelString_Source();
+
80 void GenerateFBEFieldModelOptional_Header();
+
81 void GenerateFBEFieldModelOptional_Inline();
+
82 void GenerateFBEFieldModelArray_Header();
+
83 void GenerateFBEFieldModelArray_Inline();
+
84 void GenerateFBEFieldModelVector_Header();
+
85 void GenerateFBEFieldModelVector_Inline();
+
86 void GenerateFBEFieldModelMap_Header();
+
87 void GenerateFBEFieldModelMap_Inline();
+
88 void GenerateFBEFinalModel_Header();
+
89 void GenerateFBEFinalModel_Inline();
+
90 void GenerateFBEFinalModelDecimal_Header();
+
91 void GenerateFBEFinalModelDecimal_Source();
+
92 void GenerateFBEFinalModelUUID_Header();
+
93 void GenerateFBEFinalModelUUID_Source();
+
94 void GenerateFBEFinalModelBytes_Header();
+
95 void GenerateFBEFinalModelBytes_Source();
+
96 void GenerateFBEFinalModelString_Header();
+
97 void GenerateFBEFinalModelString_Source();
+
98 void GenerateFBEFinalModelOptional_Header();
+
99 void GenerateFBEFinalModelOptional_Inline();
+
100 void GenerateFBEFinalModelArray_Header();
+
101 void GenerateFBEFinalModelArray_Inline();
+
102 void GenerateFBEFinalModelVector_Header();
+
103 void GenerateFBEFinalModelVector_Inline();
+
104 void GenerateFBEFinalModelMap_Header();
+
105 void GenerateFBEFinalModelMap_Inline();
+
106 void GenerateFBESender_Header();
+
107 void GenerateFBESender_Source();
+
108 void GenerateFBEReceiver_Header();
+
109 void GenerateFBEReceiver_Source();
+
110 void GenerateFBEJson();
+
111 void GenerateFBE_Header(const CppCommon::Path& path);
+
112 void GenerateFBE_Source(const CppCommon::Path& path);
+
113 void GenerateFBEModels_Header(const CppCommon::Path& path);
+
114 void GenerateFBEModels_Inline(const CppCommon::Path& path);
+
115 void GenerateFBEModels_Source(const CppCommon::Path& path);
+
116 void GenerateFBEFinalModels_Header(const CppCommon::Path& path);
+
117 void GenerateFBEFinalModels_Inline(const CppCommon::Path& path);
+
118 void GenerateFBEFinalModels_Source(const CppCommon::Path& path);
+
119 void GenerateFBEProtocol_Header(const CppCommon::Path& path);
+
120 void GenerateFBEProtocol_Source(const CppCommon::Path& path);
+
121 void GenerateFBEJson_Header(const CppCommon::Path& path);
+
122
+
123 void GeneratePackage_Header(const std::shared_ptr<Package>& p);
+
124 void GeneratePackage_Source(const std::shared_ptr<Package>& p);
+
125 void GeneratePackage_Json(const std::shared_ptr<Package>& p);
+
126 void GeneratePackageModels_Header(const std::shared_ptr<Package>& p);
+
127 void GeneratePackageModels_Source(const std::shared_ptr<Package>& p);
+
128 void GeneratePackageFinalModels_Header(const std::shared_ptr<Package>& p);
+
129 void GeneratePackageFinalModels_Source(const std::shared_ptr<Package>& p);
+
130 void GeneratePackageProtocol_Header(const std::shared_ptr<Package>& p, bool final);
+
131 void GeneratePackageProtocol_Source(const std::shared_ptr<Package>& p, bool final);
+
132 void GenerateEnum(const std::shared_ptr<Package>& p, const std::shared_ptr<EnumType>& e);
+
133 void GenerateEnumOutputStream(const std::shared_ptr<EnumType>& e);
+
134 void GenerateEnumLoggingStream(const std::shared_ptr<EnumType>& e);
+
135 void GenerateEnumJson(const std::shared_ptr<Package>& p, const std::shared_ptr<EnumType>& e);
+
136 void GenerateEnumFieldModel(const std::shared_ptr<Package>& p, const std::shared_ptr<EnumType>& e);
+
137 void GenerateEnumFinalModel(const std::shared_ptr<Package>& p, const std::shared_ptr<EnumType>& e);
+
138 void GenerateFlags(const std::shared_ptr<Package>& p, const std::shared_ptr<FlagsType>& f);
+
139 void GenerateFlagsOutputStream(const std::shared_ptr<FlagsType>& f);
+
140 void GenerateFlagsLoggingStream(const std::shared_ptr<FlagsType>& f);
+
141 void GenerateFlagsJson(const std::shared_ptr<Package>& p, const std::shared_ptr<FlagsType>& f);
+
142 void GenerateFlagsFieldModel(const std::shared_ptr<Package>& p, const std::shared_ptr<FlagsType>& f);
+
143 void GenerateFlagsFinalModel(const std::shared_ptr<Package>& p, const std::shared_ptr<FlagsType>& f);
+
144 void GenerateStruct_Header(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s);
+
145 void GenerateStruct_Source(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s);
+
146 void GenerateStructOutputStream(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s);
+
147 void GenerateStructLoggingStream(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s);
+
148 void GenerateStructFormatter(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s);
+
149 void GenerateStructHash(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s);
+
150 void GenerateStructJson(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s);
+
151 void GenerateStructFieldModel_Header(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s);
+
152 void GenerateStructFieldModel_Source(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s);
+
153 void GenerateStructModel_Header(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s);
+
154 void GenerateStructModel_Source(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s);
+
155 void GenerateStructFinalModel_Header(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s);
+
156 void GenerateStructFinalModel_Source(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s);
+
157 void GenerateStructModelFinal_Header(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s);
+
158 void GenerateStructModelFinal_Source(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s);
+
159 void GenerateProtocolVersion(const std::shared_ptr<Package>& p);
+
160 void GenerateSender_Header(const std::shared_ptr<Package>& p, bool final);
+
161 void GenerateSender_Source(const std::shared_ptr<Package>& p, bool final);
+
162 void GenerateReceiver_Header(const std::shared_ptr<Package>& p, bool final);
+
163 void GenerateReceiver_Source(const std::shared_ptr<Package>& p, bool final);
+
164 void GenerateProxy_Header(const std::shared_ptr<Package>& p, bool final);
+
165 void GenerateProxy_Source(const std::shared_ptr<Package>& p, bool final);
+
166 void GenerateClient_Header(const std::shared_ptr<Package>& p, bool final);
+
167 void GenerateClient_Source(const std::shared_ptr<Package>& p, bool final);
+
168
+
169 bool IsKnownType(const std::string& type);
+
170 bool IsPrimitiveType(const std::string& type, bool optional);
+
171
+
172 std::string ConvertEnumType(const std::string& type);
+
173 std::string ConvertTypeName(const std::string& package, const std::string& type, bool optional);
+
174 std::string ConvertTypeName(const std::string& package, const StructField& field);
+
175 std::string ConvertTypeNameAsArgument(const std::string& package, const StructField& field);
+
176 std::string ConvertConstant(const std::string& type, const std::string& value, bool optional);
+
177 std::string ConvertConstantPrefix(const std::string& type);
+
178 std::string ConvertConstantSuffix(const std::string& type);
+
179 std::string ConvertDefault(const std::string& package, const std::string& type);
+
180 std::string ConvertDefault(const std::string& package, const StructField& field);
+
181
+
182 std::string ConvertOutputStreamType(const std::string& type, const std::string& name, bool optional);
+
183 std::string ConvertOutputStreamValue(const std::string& type, const std::string& name, bool optional, bool separate);
+
184
+
185 std::string ConvertLoggingStreamType(const std::string& type, const std::string& name, bool optional);
+
186 std::string ConvertLoggingStreamValue(const std::string& type, const std::string& name, bool optional, bool separate);
+
187};
+
+
188
+
189} // namespace FBE
+
190
+
191#endif // GENERATOR_CPP_H
+ +
bool Proto() const noexcept
+
GeneratorCpp & Proto(bool proto) noexcept
+
bool Logging() const noexcept
+
GeneratorCpp & JSON(bool json) noexcept
+
bool JSON() const noexcept
+
void Generate(const std::shared_ptr< Package > &package) override
+
GeneratorCpp & Logging(bool logging) noexcept
+
GeneratorCpp & Final(bool final) noexcept
+
Generator(const std::string &input, const std::string &output, int indent, char space)
Definition generator.inl:11
+
bool Final() const noexcept
+
Generator(const std::string &input, const std::string &output, int indent, char space)
Definition generator.inl:11
+
Fast binary encoding generator definition.
+
Definition fbe.h:33
+
+ + +
+ + diff --git a/documents/html/generator__csharp_8cpp.html b/documents/html/generator__csharp_8cpp.html new file mode 100644 index 000000000..cda30da4b --- /dev/null +++ b/documents/html/generator__csharp_8cpp.html @@ -0,0 +1,109 @@ + + + + + + + +FastBinaryEncoding: source/generator_csharp.cpp File Reference + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+ +
generator_csharp.cpp File Reference
+
+
+ +

Fast binary encoding C# generator implementation. +More...

+
#include "generator_csharp.h"
+
+

Go to the source code of this file.

+ + + +

+Namespaces

namespace  FBE
+

Detailed Description

+

Fast binary encoding C# generator implementation.

+
Author
Ivan Shynkarenka
+
Date
20.04.2018
+ + +

Definition in file generator_csharp.cpp.

+
+ + +
+ + diff --git a/documents/html/generator__csharp_8cpp_source.html b/documents/html/generator__csharp_8cpp_source.html new file mode 100644 index 000000000..5d3b94c9e --- /dev/null +++ b/documents/html/generator__csharp_8cpp_source.html @@ -0,0 +1,8835 @@ + + + + + + + +FastBinaryEncoding: source/generator_csharp.cpp Source File + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+
generator_csharp.cpp
+
+
+Go to the documentation of this file.
1
+
8
+
9#include "generator_csharp.h"
+
10
+
11namespace FBE {
+
12
+
+
13void GeneratorCSharp::Generate(const std::shared_ptr<Package>& package)
+
14{
+
15 std::string domain = (package->domain && !package->domain->empty()) ? (*package->domain + ".") : "";
+
16
+
17 GeneratePackage(domain, package);
+
18}
+
+
19
+
20void GeneratorCSharp::GenerateHeader(const std::string& source)
+
21{
+
22 std::string code = R"CODE(//------------------------------------------------------------------------------
+
23// <auto-generated>
+
24// Automatically generated by the Fast Binary Encoding compiler, do not modify!
+
25// https://github.com/chronoxor/FastBinaryEncoding
+
26// Source: _INPUT_
+
27// FBE version: _VERSION_
+
28//
+
29// Changes to this file may cause incorrect behavior and will be lost if
+
30// the code is regenerated.
+
31// </auto-generated>
+
32//------------------------------------------------------------------------------
+
33)CODE";
+
34
+
35 // Prepare code template
+
36 code = std::regex_replace(code, std::regex("_INPUT_"), source);
+
37 code = std::regex_replace(code, std::regex("_VERSION_"), version);
+
38 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
39
+
40 Write(code);
+
41}
+
42
+
43void GeneratorCSharp::GenerateFooter()
+
44{
+
45}
+
46
+
47void GeneratorCSharp::GenerateImports()
+
48{
+
49 // Generate common imports
+
50 WriteLine();
+
51 WriteLineIndent("using System;");
+
52 WriteLineIndent("using System.Collections.Generic;");
+
53 WriteLineIndent("using System.Diagnostics;");
+
54 WriteLineIndent("using System.Globalization;");
+
55 WriteLineIndent("using System.IO;");
+
56 WriteLineIndent("using System.Linq;");
+
57 WriteLineIndent("using System.Numerics;");
+
58 WriteLineIndent("using System.Runtime.Serialization;");
+
59 WriteLineIndent("using System.Text;");
+
60 WriteLineIndent("using System.Threading;");
+
61 WriteLineIndent("using System.Threading.Tasks;");
+
62 if (JSON())
+
63 {
+
64 WriteLineIndent("#if UTF8JSON");
+
65 WriteLineIndent("using Utf8Json;");
+
66 WriteLineIndent("using Utf8Json.Resolvers;");
+
67 WriteLineIndent("#elif NEWTONSOFTJSON");
+
68 WriteLineIndent("using Newtonsoft.Json;");
+
69 WriteLineIndent("#else");
+
70 WriteLineIndent("using System.Text.Json;");
+
71 WriteLineIndent("using System.Text.Json.Serialization;");
+
72 WriteLineIndent("#endif");
+
73 }
+
74}
+
75
+
76void GeneratorCSharp::GenerateImports(const std::string& domain, const std::shared_ptr<Package>& p)
+
77{
+
78 // Generate common imports
+
79 GenerateImports();
+
80
+
81 // Generate packages import
+
82 if (p->import)
+
83 {
+
84 WriteLine();
+
85 for (auto import : p->import->imports)
+
86 WriteLineIndent("using " + domain + *import + ";");
+
87 }
+
88}
+
89
+
90void GeneratorCSharp::GenerateFBEUuidGenerator()
+
91{
+
92 std::string code = R"CODE(
+
93 // Fast Binary Encoding UUID generator
+
94 public static class UuidGenerator
+
95 {
+
96 // Gregorian epoch
+
97 private static readonly DateTime GregorianEpoch = new DateTime(1582, 10, 15, 0, 0, 0, DateTimeKind.Utc);
+
98
+
99 // Lock and random generator
+
100 private static readonly object Lock = new object();
+
101 private static readonly Random Generator = new Random();
+
102
+
103 // Node & clock sequence bytes
+
104 private static readonly byte[] NodeBytes;
+
105 private static readonly byte[] ClockSequenceBytes;
+
106
+
107 // Last UUID generated timestamp
+
108 private static DateTime _last = DateTime.UtcNow;
+
109
+
110 static UuidGenerator()
+
111 {
+
112 NodeBytes = new byte[6];
+
113 Generator.NextBytes(NodeBytes);
+
114
+
115 ClockSequenceBytes = new byte[2];
+
116 Generator.NextBytes(ClockSequenceBytes);
+
117 }
+
118
+
119 // Generate nil UUID0 (all bits set to zero)
+
120 public static Guid Nil() { return new Guid(); }
+
121
+
122 // Generate sequential UUID1 (time based version)
+
123 public static Guid Sequential()
+
124 {
+
125 var now = DateTime.UtcNow;
+
126
+
127 // Generate new clock sequence bytes to get rid of UUID duplicates
+
128 lock (Lock)
+
129 {
+
130 if (now <= _last)
+
131 Generator.NextBytes(ClockSequenceBytes);
+
132 _last = now;
+
133 }
+
134
+
135 long ticks = (now - GregorianEpoch).Ticks;
+
136 Span<byte> guid = stackalloc byte[16];
+
137 byte[] timestamp = BitConverter.GetBytes(ticks);
+
138
+
139 // Copy node
+
140 for (int i = 0; i < Math.Min(6, NodeBytes.Length); i++)
+
141 guid[10 + i] = NodeBytes[i];
+
142
+
143 // Copy clock sequence
+
144 for (int i = 0; i < Math.Min(2, ClockSequenceBytes.Length); i++)
+
145 guid[8 + i] = ClockSequenceBytes[i];
+
146
+
147 // Copy timestamp
+
148 for (int i = 0; i < Math.Min(8, timestamp.Length); i++)
+
149 guid[i] = timestamp[i];
+
150
+
151 // Set the variant
+
152 guid[8] &= 0x3F;
+
153 guid[8] |= 0x80;
+
154
+
155 // Set the version
+
156 guid[7] &= 0x0F;
+
157 guid[7] |= 0x10;
+
158
+
159 return new Guid(guid);
+
160 }
+
161
+
162 // Generate random UUID4 (randomly or pseudo-randomly generated version)
+
163 public static Guid Random() { return Guid.NewGuid(); }
+
164 }
+
165)CODE";
+
166
+
167 // Prepare code template
+
168 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
169
+
170 Write(code);
+
171}
+
172
+
173void GeneratorCSharp::GenerateFBEBuffer()
+
174{
+
175 std::string code = R"CODE(
+
176 // Fast Binary Encoding dynamic bytes buffer
+
177 public class Buffer
+
178 {
+
179 private byte[] _data;
+
180 private long _size;
+
181 private long _offset;
+
182
+
183 // Is the buffer empty?
+
184 public bool IsEmpty => (_data == null) || (_size == 0);
+
185 // Bytes memory buffer
+
186 public byte[] Data => _data;
+
187 // Bytes memory buffer capacity
+
188 public long Capacity => _data.Length;
+
189 // Bytes memory buffer size
+
190 public long Size => _size;
+
191 // Bytes memory buffer offset
+
192 public long Offset => _offset;
+
193
+
194 // Initialize a new expandable buffer with zero capacity
+
195 public Buffer() { Attach(); }
+
196 // Initialize a new expandable buffer with the given capacity
+
197 public Buffer(long capacity) { Attach(capacity); }
+
198 // Initialize a new buffer based on the specified byte array
+
199 public Buffer(byte[] buffer) { Attach(buffer); }
+
200 // Initialize a new buffer based on the specified region (offset) of a byte array
+
201 public Buffer(byte[] buffer, long offset) { Attach(buffer, offset); }
+
202 // Initialize a new buffer based on the specified region (size and offset) of a byte array
+
203 public Buffer(byte[] buffer, long size, long offset) { Attach(buffer, size, offset); }
+
204
+
205 #region Attach memory buffer methods
+
206
+
207 public void Attach() { _data = new byte[0]; _size = 0; _offset = 0; }
+
208 public void Attach(long capacity) { _data = new byte[capacity]; _size = 0; _offset = 0; }
+
209 public void Attach(byte[] buffer) { _data = buffer; _size = buffer.Length; _offset = 0; }
+
210 public void Attach(byte[] buffer, long offset) { _data = buffer; _size = buffer.Length; _offset = offset; }
+
211 public void Attach(byte[] buffer, long size, long offset) { _data = buffer; _size = size; _offset = offset; }
+
212
+
213 #endregion
+
214
+
215 #region Memory buffer methods
+
216
+
217 // Allocate memory in the current buffer and return offset to the allocated memory block
+
218 public long Allocate(long size)
+
219 {
+
220 Debug.Assert((size >= 0), "Invalid allocation size!");
+
221 if (size < 0)
+
222 throw new ArgumentException("Invalid allocation size!", nameof(size));
+
223
+
224 long offset = Size;
+
225
+
226 // Calculate a new buffer size
+
227 long total = _size + size;
+
228
+
229 if (total <= Capacity)
+
230 {
+
231 _size = total;
+
232 return offset;
+
233 }
+
234
+
235 byte[] data = new byte[Math.Max(total, 2 * Capacity)];
+
236 Array.Copy(_data, 0, data, 0, _size);
+
237 _data = data;
+
238 _size = total;
+
239 return offset;
+
240 }
+
241
+
242 // Remove some memory of the given size from the current buffer
+
243 public void Remove(long offset, long size)
+
244 {
+
245 Debug.Assert(((offset + size) <= Size), "Invalid offset & size!");
+
246 if ((offset + size) > Size)
+
247 throw new ArgumentException("Invalid offset & size!", nameof(offset));
+
248
+
249 Array.Copy(_data, offset + size, _data, offset, _size - size - offset);
+
250 _size -= size;
+
251 if (_offset >= (offset + size))
+
252 _offset -= size;
+
253 else if (_offset >= offset)
+
254 {
+
255 _offset -= _offset - offset;
+
256 if (_offset > Size)
+
257 _offset = Size;
+
258 }
+
259 }
+
260
+
261 // Reserve memory of the given capacity in the current buffer
+
262 public void Reserve(long capacity)
+
263 {
+
264 Debug.Assert((capacity >= 0), "Invalid reserve capacity!");
+
265 if (capacity < 0)
+
266 throw new ArgumentException("Invalid reserve capacity!", nameof(capacity));
+
267
+
268 if (capacity > Capacity)
+
269 {
+
270 byte[] data = new byte[Math.Max(capacity, 2 * Capacity)];
+
271 Array.Copy(_data, 0, data, 0, _size);
+
272 _data = data;
+
273 }
+
274 }
+
275
+
276 // Resize the current buffer
+
277 public void Resize(long size)
+
278 {
+
279 Reserve(size);
+
280 _size = size;
+
281 if (_offset > _size)
+
282 _offset = _size;
+
283 }
+
284
+
285 // Reset the current buffer and its offset
+
286 public void Reset()
+
287 {
+
288 _size = 0;
+
289 _offset = 0;
+
290 }
+
291
+
292 // Shift the current buffer offset
+
293 public void Shift(long offset) { _offset += offset; }
+
294 // Unshift the current buffer offset
+
295 public void Unshift(long offset) { _offset -= offset; }
+
296
+
297 #endregion
+
298)CODE";
+
299
+
300 // Prepare code template
+
301 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
302
+
303 Write(code);
+
304
+
305 code = R"CODE(
+
306 #region Buffer I/O methods
+
307
+
308 public static bool ReadBool(byte[] buffer, long offset)
+
309 {
+
310 return buffer[offset] != 0;
+
311 }
+
312
+
313 public static byte ReadByte(byte[] buffer, long offset)
+
314 {
+
315 return buffer[offset];
+
316 }
+
317
+
318 public static char ReadChar(byte[] buffer, long offset)
+
319 {
+
320 return (char)ReadUInt8(buffer, offset);
+
321 }
+
322
+
323 public static char ReadWChar(byte[] buffer, long offset)
+
324 {
+
325 return (char)ReadUInt32(buffer, offset);
+
326 }
+
327
+
328 public static sbyte ReadInt8(byte[] buffer, long offset)
+
329 {
+
330 return (sbyte)buffer[offset];
+
331 }
+
332
+
333 public static byte ReadUInt8(byte[] buffer, long offset)
+
334 {
+
335 return buffer[offset];
+
336 }
+
337
+
338 public static short ReadInt16(byte[] buffer, long offset)
+
339 {
+
340 return (short)(buffer[offset + 0] | (buffer[offset + 1] << 8));
+
341 }
+
342
+
343 public static ushort ReadUInt16(byte[] buffer, long offset)
+
344 {
+
345 return (ushort)(buffer[offset + 0] | (buffer[offset + 1] << 8));
+
346 }
+
347
+
348 public static int ReadInt32(byte[] buffer, long offset)
+
349 {
+
350 return (buffer[offset + 0] << 0)|
+
351 (buffer[offset + 1] << 8)|
+
352 (buffer[offset + 2] << 16)|
+
353 (buffer[offset + 3] << 24);
+
354 }
+
355
+
356 public static uint ReadUInt32(byte[] buffer, long offset)
+
357 {
+
358 return ((uint)buffer[offset + 0] << 0)|
+
359 ((uint)buffer[offset + 1] << 8)|
+
360 ((uint)buffer[offset + 2] << 16)|
+
361 ((uint)buffer[offset + 3] << 24);
+
362 }
+
363
+
364 public static long ReadInt64(byte[] buffer, long offset)
+
365 {
+
366 return ((long)buffer[offset + 0] << 0)|
+
367 ((long)buffer[offset + 1] << 8)|
+
368 ((long)buffer[offset + 2] << 16)|
+
369 ((long)buffer[offset + 3] << 24)|
+
370 ((long)buffer[offset + 4] << 32)|
+
371 ((long)buffer[offset + 5] << 40)|
+
372 ((long)buffer[offset + 6] << 48)|
+
373 ((long)buffer[offset + 7] << 56);
+
374 }
+
375
+
376 public static ulong ReadUInt64(byte[] buffer, long offset)
+
377 {
+
378 return ((ulong)buffer[offset + 0] << 0)|
+
379 ((ulong)buffer[offset + 1] << 8)|
+
380 ((ulong)buffer[offset + 2] << 16)|
+
381 ((ulong)buffer[offset + 3] << 24)|
+
382 ((ulong)buffer[offset + 4] << 32)|
+
383 ((ulong)buffer[offset + 5] << 40)|
+
384 ((ulong)buffer[offset + 6] << 48)|
+
385 ((ulong)buffer[offset + 7] << 56);
+
386 }
+
387
+
388 public static ulong ReadUInt64Guid(byte[] buffer, long offset)
+
389 {
+
390 return ((ulong)buffer[offset + 0] << 24)|
+
391 ((ulong)buffer[offset + 1] << 16)|
+
392 ((ulong)buffer[offset + 2] << 8)|
+
393 ((ulong)buffer[offset + 3] << 0)|
+
394 ((ulong)buffer[offset + 4] << 40)|
+
395 ((ulong)buffer[offset + 5] << 32)|
+
396 ((ulong)buffer[offset + 6] << 56)|
+
397 ((ulong)buffer[offset + 7] << 48);
+
398 }
+
399
+
400 public static float ReadFloat(byte[] buffer, long offset)
+
401 {
+
402 var bits = default(FloatUnion);
+
403 bits.UIntData = ReadUInt32(buffer, offset);
+
404 return bits.FloatData;
+
405 }
+
406
+
407 public static double ReadDouble(byte[] buffer, long offset)
+
408 {
+
409 var bits = default(DoubleUnion);
+
410 bits.ULongData = ReadUInt64(buffer, offset);
+
411 return bits.DoubleData;
+
412 }
+
413
+
414 public static decimal ReadDecimal(byte[] buffer, long offset)
+
415 {
+
416 var bits = default(DecimalUnion);
+
417 bits.UIntLow = ReadUInt32(buffer, offset);
+
418 bits.UIntMid = ReadUInt32(buffer, offset + 4);
+
419 bits.UIntHigh = ReadUInt32(buffer, offset + 8);
+
420 bits.UIntFlags = ReadUInt32(buffer, offset + 12);
+
421 return bits.DecimalData;
+
422 }
+
423
+
424 public static byte[] ReadBytes(byte[] buffer, long offset, long size)
+
425 {
+
426 byte[] result = new byte[size];
+
427 Array.Copy(buffer, offset, result, 0, (int)size);
+
428 return result;
+
429 }
+
430
+
431 public static string ReadString(byte[] buffer, long offset, long size)
+
432 {
+
433 return Encoding.UTF8.GetString(buffer, (int)offset, (int)size);
+
434 }
+
435
+
436 public static Guid ReadUUID(byte[] buffer, long offset)
+
437 {
+
438 var bits = default(GuidUnion);
+
439 bits.ULongHigh = ReadUInt64Guid(buffer, offset);
+
440 bits.ULongLow = ReadUInt64(buffer, offset + 8);
+
441 return bits.GuidData;
+
442 }
+
443
+
444 public static void Write(byte[] buffer, long offset, bool value)
+
445 {
+
446 buffer[offset] = (byte)(value ? 1 : 0);
+
447 }
+
448
+
449 public static void Write(byte[] buffer, long offset, sbyte value)
+
450 {
+
451 buffer[offset] = (byte)value;
+
452 }
+
453
+
454 public static void Write(byte[] buffer, long offset, byte value)
+
455 {
+
456 buffer[offset] = value;
+
457 }
+
458
+
459 public static void Write(byte[] buffer, long offset, short value)
+
460 {
+
461 buffer[offset + 0] = (byte)(value >> 0);
+
462 buffer[offset + 1] = (byte)(value >> 8);
+
463 }
+
464
+
465 public static void Write(byte[] buffer, long offset, ushort value)
+
466 {
+
467 buffer[offset + 0] = (byte)(value >> 0);
+
468 buffer[offset + 1] = (byte)(value >> 8);
+
469 }
+
470
+
471 public static void Write(byte[] buffer, long offset, int value)
+
472 {
+
473 buffer[offset + 0] = (byte)(value >> 0);
+
474 buffer[offset + 1] = (byte)(value >> 8);
+
475 buffer[offset + 2] = (byte)(value >> 16);
+
476 buffer[offset + 3] = (byte)(value >> 24);
+
477 }
+
478
+
479 public static void Write(byte[] buffer, long offset, uint value)
+
480 {
+
481 buffer[offset + 0] = (byte)(value >> 0);
+
482 buffer[offset + 1] = (byte)(value >> 8);
+
483 buffer[offset + 2] = (byte)(value >> 16);
+
484 buffer[offset + 3] = (byte)(value >> 24);
+
485 }
+
486
+
487 public static void Write(byte[] buffer, long offset, long value)
+
488 {
+
489 buffer[offset + 0] = (byte)(value >> 0);
+
490 buffer[offset + 1] = (byte)(value >> 8);
+
491 buffer[offset + 2] = (byte)(value >> 16);
+
492 buffer[offset + 3] = (byte)(value >> 24);
+
493 buffer[offset + 4] = (byte)(value >> 32);
+
494 buffer[offset + 5] = (byte)(value >> 40);
+
495 buffer[offset + 6] = (byte)(value >> 48);
+
496 buffer[offset + 7] = (byte)(value >> 56);
+
497 }
+
498
+
499 public static void Write(byte[] buffer, long offset, ulong value)
+
500 {
+
501 buffer[offset + 0] = (byte)(value >> 0);
+
502 buffer[offset + 1] = (byte)(value >> 8);
+
503 buffer[offset + 2] = (byte)(value >> 16);
+
504 buffer[offset + 3] = (byte)(value >> 24);
+
505 buffer[offset + 4] = (byte)(value >> 32);
+
506 buffer[offset + 5] = (byte)(value >> 40);
+
507 buffer[offset + 6] = (byte)(value >> 48);
+
508 buffer[offset + 7] = (byte)(value >> 56);
+
509 }
+
510
+
511 public static void WriteGuid(byte[] buffer, long offset, ulong value)
+
512 {
+
513 buffer[offset + 0] = (byte)(value >> 24);
+
514 buffer[offset + 1] = (byte)(value >> 16);
+
515 buffer[offset + 2] = (byte)(value >> 8);
+
516 buffer[offset + 3] = (byte)(value >> 0);
+
517 buffer[offset + 4] = (byte)(value >> 40);
+
518 buffer[offset + 5] = (byte)(value >> 32);
+
519 buffer[offset + 6] = (byte)(value >> 56);
+
520 buffer[offset + 7] = (byte)(value >> 48);
+
521 }
+
522
+
523 public static void Write(byte[] buffer, long offset, float value)
+
524 {
+
525 var bits = default(FloatUnion);
+
526 bits.FloatData = value;
+
527 Write(buffer, offset, bits.UIntData);
+
528 }
+
529
+
530 public static void Write(byte[] buffer, long offset, double value)
+
531 {
+
532 var bits = default(DoubleUnion);
+
533 bits.DoubleData = value;
+
534 Write(buffer, offset, bits.ULongData);
+
535 }
+
536
+
537 public static void Write(byte[] buffer, long offset, decimal value)
+
538 {
+
539 var bits = default(DecimalUnion);
+
540 bits.DecimalData = value;
+
541 Write(buffer, offset, bits.UIntLow);
+
542 Write(buffer, offset + 4, bits.UIntMid);
+
543 Write(buffer, offset + 8, bits.UIntHigh);
+
544 Write(buffer, offset + 12, bits.UIntFlags);
+
545 }
+
546
+
547 public static void Write(byte[] buffer, long offset, byte[] value)
+
548 {
+
549 Array.Copy(value, 0, buffer, offset, value.Length);
+
550 }
+
551
+
552 public static void Write(byte[] buffer, long offset, byte[] value, long valueOffset, long valueSize)
+
553 {
+
554 Array.Copy(value, valueOffset, buffer, offset, valueSize);
+
555 }
+
556
+
557 public static void Write(byte[] buffer, long offset, byte value, long valueCount)
+
558 {
+
559 for (long i = 0; i < valueCount; i++)
+
560 buffer[offset + i] = value;
+
561 }
+
562
+
563 public static long Write(byte[] buffer, long offset, string value)
+
564 {
+
565 return Encoding.UTF8.GetBytes(value, 0, value.Length, buffer, (int)offset);
+
566 }
+
567
+
568 public static void Write(byte[] buffer, long offset, Guid value)
+
569 {
+
570 var bits = default(GuidUnion);
+
571 bits.GuidData = value;
+
572 WriteGuid(buffer, offset, bits.ULongHigh);
+
573 Write(buffer, offset + 8, bits.ULongLow);
+
574 }
+
575
+
576 #endregion
+
577
+
578 #region Utilities
+
579
+
580 [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Explicit)]
+
581 private struct FloatUnion
+
582 {
+
583 [System.Runtime.InteropServices.FieldOffset(0)]
+
584 public uint UIntData;
+
585 [System.Runtime.InteropServices.FieldOffset(0)]
+
586 public float FloatData;
+
587 }
+
588
+
589 [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Explicit)]
+
590 private struct DoubleUnion
+
591 {
+
592 [System.Runtime.InteropServices.FieldOffset(0)]
+
593 public ulong ULongData;
+
594 [System.Runtime.InteropServices.FieldOffset(0)]
+
595 public double DoubleData;
+
596 }
+
597
+
598 [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Explicit)]
+
599 private struct DecimalUnion
+
600 {
+
601 [System.Runtime.InteropServices.FieldOffset(0)]
+
602 public uint UIntFlags;
+
603 [System.Runtime.InteropServices.FieldOffset(4)]
+
604 public uint UIntHigh;
+
605 [System.Runtime.InteropServices.FieldOffset(8)]
+
606 public uint UIntLow;
+
607 [System.Runtime.InteropServices.FieldOffset(12)]
+
608 public uint UIntMid;
+
609 [System.Runtime.InteropServices.FieldOffset(0)]
+
610 public decimal DecimalData;
+
611 }
+
612
+
613 [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Explicit)]
+
614 private struct GuidUnion
+
615 {
+
616 [System.Runtime.InteropServices.FieldOffset(0)]
+
617 public ulong ULongHigh;
+
618 [System.Runtime.InteropServices.FieldOffset(8)]
+
619 public ulong ULongLow;
+
620 [System.Runtime.InteropServices.FieldOffset(0)]
+
621 public Guid GuidData;
+
622 }
+
623
+
624 #endregion
+
625 }
+
626)CODE";
+
627
+
628 // Prepare code template
+
629 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
630
+
631 Write(code);
+
632}
+
633
+
634void GeneratorCSharp::GenerateFBEBaseModel()
+
635{
+
636 std::string code = R"CODE(
+
637 // Fast Binary Encoding base model
+
638 public class Model
+
639 {
+
640 // Bytes buffer
+
641 public Buffer Buffer { get; }
+
642
+
643 protected Model() { Buffer = new Buffer(); }
+
644 protected Model(Buffer buffer) { Buffer = buffer; }
+
645
+
646 #region Attach memory buffer methods
+
647
+
648 public void Attach() { Buffer.Attach(); }
+
649 public void Attach(long capacity) { Buffer.Attach(capacity); }
+
650 public void Attach(byte[] buffer) { Buffer.Attach(buffer); }
+
651 public void Attach(byte[] buffer, long offset) { Buffer.Attach(buffer, offset); }
+
652 public void Attach(byte[] buffer, long size, long offset) { Buffer.Attach(buffer, size, offset); }
+
653 public void Attach(Buffer buffer) { Buffer.Attach(buffer.Data, buffer.Size, buffer.Offset); }
+
654 public void Attach(Buffer buffer, long offset) { Buffer.Attach(buffer.Data, buffer.Size, offset); }
+
655
+
656 #endregion
+
657
+
658 #region Memory buffer methods
+
659
+
660 public long Allocate(long size) { return Buffer.Allocate(size); }
+
661 public void Remove(long offset, long size) { Buffer.Remove(offset, size); }
+
662 public void Reserve(long capacity) { Buffer.Reserve(capacity); }
+
663 public void Resize(long size) { Buffer.Resize(size); }
+
664 public void Reset() { Buffer.Reset(); }
+
665 public void Shift(long offset) { Buffer.Shift(offset); }
+
666 public void Unshift(long offset) { Buffer.Unshift(offset); }
+
667
+
668 #endregion
+
669
+
670 #region Buffer I/O methods
+
671
+
672 protected uint ReadUInt32(long offset) { return Buffer.ReadUInt32(Buffer.Data, Buffer.Offset + offset); }
+
673 protected void Write(long offset, uint value) { Buffer.Write(Buffer.Data, Buffer.Offset + offset, value); }
+
674
+
675 #endregion
+
676 }
+
677)CODE";
+
678
+
679 // Prepare code template
+
680 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
681
+
682 Write(code);
+
683}
+
684
+
685void GeneratorCSharp::GenerateFBEFieldModelBase()
+
686{
+
687 std::string code = R"CODE(
+
688 // Fast Binary Encoding base types enumeration
+
689 public enum BaseTypes
+
690 {
+
691 BOOL,
+
692 BYTE,
+
693 BYTES,
+
694 CHAR,
+
695 WCHAR,
+
696 INT8,
+
697 UINT8,
+
698 INT16,
+
699 UINT16,
+
700 INT32,
+
701 UINT32,
+
702 INT64,
+
703 UINT64,
+
704 FLOAT,
+
705 DOUBLE,
+
706 DECIMAL,
+
707 UUID,
+
708 STRING,
+
709 TIMESTAMP
+
710 }
+
711
+
712 // Fast Binary Encoding base field model
+
713 public abstract class FieldModelBase
+
714 {
+
715 protected Buffer _buffer;
+
716 protected long _offset;
+
717
+
718 protected FieldModelBase(Buffer buffer, long offset)
+
719 {
+
720 _buffer = buffer;
+
721 _offset = offset;
+
722 }
+
723
+
724 // Get the field offset
+
725 public long FBEOffset { get => _offset; set => _offset = value; }
+
726 // Get the field size
+
727 public virtual long FBESize => 0;
+
728 // Get the field extra size
+
729 public virtual long FBEExtra => 0;
+
730
+
731 // Shift the current field offset
+
732 public void FBEShift(long size) { _offset += size; }
+
733 // Unshift the current field offset
+
734 public void FBEUnshift(long size) { _offset -= size; }
+
735
+
736 #region Buffer I/O methods
+
737
+
738 protected bool ReadBool(long offset) { return Buffer.ReadBool(_buffer.Data, _buffer.Offset + offset); }
+
739 protected byte ReadByte(long offset) { return Buffer.ReadByte(_buffer.Data, _buffer.Offset + offset); }
+
740 protected char ReadChar(long offset) { return Buffer.ReadChar(_buffer.Data, _buffer.Offset + offset); }
+
741 protected char ReadWChar(long offset) { return Buffer.ReadWChar(_buffer.Data, _buffer.Offset + offset); }
+
742 protected sbyte ReadInt8(long offset) { return Buffer.ReadInt8(_buffer.Data, _buffer.Offset + offset); }
+
743 protected byte ReadUInt8(long offset) { return Buffer.ReadUInt8(_buffer.Data, _buffer.Offset + offset); }
+
744 protected short ReadInt16(long offset) { return Buffer.ReadInt16(_buffer.Data, _buffer.Offset + offset); }
+
745 protected ushort ReadUInt16(long offset) { return Buffer.ReadUInt16(_buffer.Data, _buffer.Offset + offset); }
+
746 protected int ReadInt32(long offset) { return Buffer.ReadInt32(_buffer.Data, _buffer.Offset + offset); }
+
747 protected uint ReadUInt32(long offset) { return Buffer.ReadUInt32(_buffer.Data, _buffer.Offset + offset); }
+
748 protected long ReadInt64(long offset) { return Buffer.ReadInt64(_buffer.Data, _buffer.Offset + offset); }
+
749 protected ulong ReadUInt64(long offset) { return Buffer.ReadUInt64(_buffer.Data, _buffer.Offset + offset); }
+
750 protected float ReadFloat(long offset) { return Buffer.ReadFloat(_buffer.Data, _buffer.Offset + offset); }
+
751 protected double ReadDouble(long offset) { return Buffer.ReadDouble(_buffer.Data, _buffer.Offset + offset); }
+
752 protected decimal ReadDecimal(long offset) { return Buffer.ReadDecimal(_buffer.Data, _buffer.Offset + offset); }
+
753 protected byte[] ReadBytes(long offset, long size) { return Buffer.ReadBytes(_buffer.Data, _buffer.Offset + offset, size); }
+
754 protected string ReadString(long offset, long size) { return Buffer.ReadString(_buffer.Data, _buffer.Offset + offset, size); }
+
755 protected Guid ReadUUID(long offset) { return Buffer.ReadUUID(_buffer.Data, _buffer.Offset + offset); }
+
756 protected void Write(long offset, bool value) { Buffer.Write(_buffer.Data, _buffer.Offset + offset, value); }
+
757 protected void Write(long offset, sbyte value) { Buffer.Write(_buffer.Data, _buffer.Offset + offset, value); }
+
758 protected void Write(long offset, byte value) { Buffer.Write(_buffer.Data, _buffer.Offset + offset, value); }
+
759 protected void Write(long offset, short value) { Buffer.Write(_buffer.Data, _buffer.Offset + offset, value); }
+
760 protected void Write(long offset, ushort value) { Buffer.Write(_buffer.Data, _buffer.Offset + offset, value); }
+
761 protected void Write(long offset, int value) { Buffer.Write(_buffer.Data, _buffer.Offset + offset, value); }
+
762 protected void Write(long offset, uint value) { Buffer.Write(_buffer.Data, _buffer.Offset + offset, value); }
+
763 protected void Write(long offset, long value) { Buffer.Write(_buffer.Data, _buffer.Offset + offset, value); }
+
764 protected void Write(long offset, ulong value) { Buffer.Write(_buffer.Data, _buffer.Offset + offset, value); }
+
765 protected void Write(long offset, float value) { Buffer.Write(_buffer.Data, _buffer.Offset + offset, value); }
+
766 protected void Write(long offset, double value) { Buffer.Write(_buffer.Data, _buffer.Offset + offset, value); }
+
767 protected void Write(long offset, decimal value) { Buffer.Write(_buffer.Data, _buffer.Offset + offset, value); }
+
768 protected void Write(long offset, byte[] value) { Buffer.Write(_buffer.Data, _buffer.Offset + offset, value); }
+
769 protected void Write(long offset, byte[] value, long valueOffset, long valueSize) { Buffer.Write(_buffer.Data, _buffer.Offset + offset, value, valueOffset, valueSize); }
+
770 protected void Write(long offset, byte value, long valueCount) { Buffer.Write(_buffer.Data, _buffer.Offset + offset, value, valueCount); }
+
771 protected long Write(long offset, string value) { return Buffer.Write(_buffer.Data, _buffer.Offset + offset, value); }
+
772 protected void Write(long offset, Guid value) { Buffer.Write(_buffer.Data, _buffer.Offset + offset, value); }
+
773
+
774 #endregion
+
775 }
+
776
+
777 // Fast Binary Encoding field model value type
+
778 public abstract class FieldModelValueType<T> : FieldModelBase
+
779 where T : struct
+
780 {
+
781 protected FieldModelValueType(Buffer buffer, long offset) : base(buffer, offset) {}
+
782
+
783 // Clone the field model
+
784 public abstract FieldModelValueType<T> Clone();
+
785
+
786 // Check if the value is valid
+
787 public virtual bool Verify() { return true; }
+
788
+
789 // Get the value
+
790 public abstract void Get(out T value);
+
791 public abstract void Get(out T value, T defaults);
+
792
+
793 // Set the value
+
794 public abstract void Set(T value);
+
795
+
796 // Create field model of the given type
+
797 public static FieldModelValueType<T> CreateFieldModel(BaseTypes type, Buffer buffer, long offset)
+
798 {
+
799 switch (type)
+
800 {
+
801 case BaseTypes.BOOL:
+
802 return new FieldModelBool(buffer, offset) as FieldModelValueType<T>;
+
803 case BaseTypes.BYTE:
+
804 return new FieldModelByte(buffer, offset) as FieldModelValueType<T>;
+
805 case BaseTypes.CHAR:
+
806 return new FieldModelChar(buffer, offset) as FieldModelValueType<T>;
+
807 case BaseTypes.WCHAR:
+
808 return new FieldModelWChar(buffer, offset) as FieldModelValueType<T>;
+
809 case BaseTypes.INT8:
+
810 return new FieldModelInt8(buffer, offset) as FieldModelValueType<T>;
+
811 case BaseTypes.UINT8:
+
812 return new FieldModelUInt8(buffer, offset) as FieldModelValueType<T>;
+
813 case BaseTypes.INT16:
+
814 return new FieldModelInt16(buffer, offset) as FieldModelValueType<T>;
+
815 case BaseTypes.UINT16:
+
816 return new FieldModelUInt16(buffer, offset) as FieldModelValueType<T>;
+
817 case BaseTypes.INT32:
+
818 return new FieldModelInt32(buffer, offset) as FieldModelValueType<T>;
+
819 case BaseTypes.UINT32:
+
820 return new FieldModelUInt32(buffer, offset) as FieldModelValueType<T>;
+
821 case BaseTypes.INT64:
+
822 return new FieldModelInt64(buffer, offset) as FieldModelValueType<T>;
+
823 case BaseTypes.UINT64:
+
824 return new FieldModelUInt64(buffer, offset) as FieldModelValueType<T>;
+
825 case BaseTypes.FLOAT:
+
826 return new FieldModelFloat(buffer, offset) as FieldModelValueType<T>;
+
827 case BaseTypes.DOUBLE:
+
828 return new FieldModelDouble(buffer, offset) as FieldModelValueType<T>;
+
829 case BaseTypes.DECIMAL:
+
830 return new FieldModelDecimal(buffer, offset) as FieldModelValueType<T>;
+
831 case BaseTypes.UUID:
+
832 return new FieldModelUUID(buffer, offset) as FieldModelValueType<T>;
+
833 case BaseTypes.TIMESTAMP:
+
834 return new FieldModelTimestamp(buffer, offset) as FieldModelValueType<T>;
+
835 default:
+
836 Debug.Assert(false, "Unknown type!");
+
837 return null;
+
838 }
+
839 }
+
840 }
+
841
+
842 // Fast Binary Encoding field model reference type
+
843 public abstract class FieldModelReferenceType<T> : FieldModelBase
+
844 where T : class
+
845 {
+
846 protected FieldModelReferenceType(Buffer buffer, long offset) : base(buffer, offset) {}
+
847
+
848 // Clone the field model
+
849 public abstract FieldModelReferenceType<T> Clone();
+
850
+
851 // Check if the value is valid
+
852 public virtual bool Verify() { return true; }
+
853
+
854 // Get the value
+
855 public abstract void Get(out T value);
+
856 public abstract void Get(out T value, T defaults);
+
857
+
858 // Set the value
+
859 public abstract void Set(T value);
+
860
+
861 // Create field model of the given type
+
862 public static FieldModelReferenceType<T> CreateFieldModel(BaseTypes type, Buffer buffer, long offset)
+
863 {
+
864 switch (type)
+
865 {
+
866 case BaseTypes.BYTES:
+
867 return new FieldModelBytes(buffer, offset) as FieldModelReferenceType<T>;
+
868 case BaseTypes.STRING:
+
869 return new FieldModelString(buffer, offset) as FieldModelReferenceType<T>;
+
870 default:
+
871 Debug.Assert(false, "Unknown type!");
+
872 return null;
+
873 }
+
874 }
+
875 }
+
876)CODE";
+
877
+
878 // Prepare code template
+
879 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
880
+
881 Write(code);
+
882}
+
883
+
884void GeneratorCSharp::GenerateFBEFieldModel(const std::string& name, const std::string& type, const std::string& base, const std::string& size, const std::string& defaults)
+
885{
+
886 std::string code = R"CODE(
+
887 // Fast Binary Encoding _TYPE_ field model
+
888 public class FieldModel_NAME_ : FieldModelValueType<_TYPE_>
+
889 {
+
890 public FieldModel_NAME_(Buffer buffer, long offset) : base(buffer, offset) {}
+
891
+
892 // Get the field size
+
893 public override long FBESize => _SIZE_;
+
894
+
895 // Clone the field model
+
896 public override FieldModelValueType<_TYPE_> Clone() { return new FieldModel_NAME_(_buffer, _offset); }
+
897
+
898 // Get the value
+
899 public override void Get(out _TYPE_ value) { Get(out value, _DEFAULTS_); }
+
900 public override void Get(out _TYPE_ value, _TYPE_ defaults)
+
901 {
+
902 if ((_buffer.Offset + FBEOffset + FBESize) > _buffer.Size)
+
903 {
+
904 value = defaults;
+
905 return;
+
906 }
+
907
+
908 value = Read_NAME_(FBEOffset);
+
909 }
+
910
+
911 // Set the value
+
912 public override void Set(_TYPE_ value)
+
913 {
+
914 Debug.Assert(((_buffer.Offset + FBEOffset + FBESize) <= _buffer.Size), "Model is broken!");
+
915 if ((_buffer.Offset + FBEOffset + FBESize) > _buffer.Size)
+
916 return;
+
917
+
918 Write(FBEOffset, _BASE_value);
+
919 }
+
920 }
+
921)CODE";
+
922
+
923 // Prepare code template
+
924 code = std::regex_replace(code, std::regex("_NAME_"), name);
+
925 code = std::regex_replace(code, std::regex("_TYPE_"), type);
+
926 code = std::regex_replace(code, std::regex("_BASE_"), base);
+
927 code = std::regex_replace(code, std::regex("_SIZE_"), size);
+
928 code = std::regex_replace(code, std::regex("_DEFAULTS_"), defaults);
+
929 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
930
+
931 Write(code);
+
932}
+
933
+
934void GeneratorCSharp::GenerateFBEFieldModelTimestamp()
+
935{
+
936 std::string code = R"CODE(
+
937 // Fast Binary Encoding timestamp field model
+
938 public class FieldModelTimestamp : FieldModelValueType<DateTime>
+
939 {
+
940 private const long UnixEpoch = 621355968000000000;
+
941
+
942 public FieldModelTimestamp(Buffer buffer, long offset) : base(buffer, offset) {}
+
943
+
944 // Get the field size
+
945 public override long FBESize => 8;
+
946
+
947 // Clone the field model
+
948 public override FieldModelValueType<DateTime> Clone() { return new FieldModelTimestamp(_buffer, _offset); }
+
949
+
950 // Get the timestamp value
+
951 public override void Get(out DateTime value) { Get(out value, new DateTime(UnixEpoch, DateTimeKind.Utc)); }
+
952 public override void Get(out DateTime value, DateTime defaults)
+
953 {
+
954 if ((_buffer.Offset + FBEOffset + FBESize) > _buffer.Size)
+
955 {
+
956 value = defaults;
+
957 return;
+
958 }
+
959
+
960 ulong ticks = ReadUInt64(FBEOffset) / 100;
+
961 value = new DateTime((long)(UnixEpoch + ticks), DateTimeKind.Utc);
+
962 }
+
963
+
964 // Set the timestamp value
+
965 public override void Set(DateTime value)
+
966 {
+
967 Debug.Assert(((_buffer.Offset + FBEOffset + FBESize) <= _buffer.Size), "Model is broken!");
+
968 if ((_buffer.Offset + FBEOffset + FBESize) > _buffer.Size)
+
969 return;
+
970
+
971 ulong nanoseconds = (ulong)((value.Ticks - UnixEpoch) * 100);
+
972 Write(FBEOffset, nanoseconds);
+
973 }
+
974 }
+
975)CODE";
+
976
+
977 // Prepare code template
+
978 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
979
+
980 Write(code);
+
981}
+
982
+
983void GeneratorCSharp::GenerateFBEFieldModelBytes()
+
984{
+
985 std::string code = R"CODE(
+
986 // Fast Binary Encoding bytes field model
+
987 public class FieldModelBytes : FieldModelReferenceType<MemoryStream>
+
988 {
+
989 public FieldModelBytes(Buffer buffer, long offset) : base(buffer, offset) {}
+
990
+
991 // Get the field size
+
992 public override long FBESize => 4;
+
993 // Get the field extra size
+
994 public override long FBEExtra
+
995 {
+
996 get
+
997 {
+
998 if ((_buffer.Offset + FBEOffset + FBESize) > _buffer.Size)
+
999 return 0;
+
1000
+
1001 uint fbeBytesOffset = ReadUInt32(FBEOffset);
+
1002 if ((fbeBytesOffset == 0) || ((_buffer.Offset + fbeBytesOffset + 4) > _buffer.Size))
+
1003 return 0;
+
1004
+
1005 uint fbeBytesSize = ReadUInt32(fbeBytesOffset);
+
1006 return 4 + fbeBytesSize;
+
1007 }
+
1008 }
+
1009
+
1010 // Clone the field model
+
1011 public override FieldModelReferenceType<MemoryStream> Clone() { return new FieldModelBytes(_buffer, _offset); }
+
1012
+
1013 // Check if the bytes value is valid
+
1014 public override bool Verify()
+
1015 {
+
1016 if ((_buffer.Offset + FBEOffset + FBESize) > _buffer.Size)
+
1017 return true;
+
1018
+
1019 uint fbeBytesOffset = ReadUInt32(FBEOffset);
+
1020 if (fbeBytesOffset == 0)
+
1021 return true;
+
1022
+
1023 if ((_buffer.Offset + fbeBytesOffset + 4) > _buffer.Size)
+
1024 return false;
+
1025
+
1026 uint fbeBytesSize = ReadUInt32(fbeBytesOffset);
+
1027 if ((_buffer.Offset + fbeBytesOffset + 4 + fbeBytesSize) > _buffer.Size)
+
1028 return false;
+
1029
+
1030 return true;
+
1031 }
+
1032
+
1033 // Get the bytes value
+
1034 public override void Get(out MemoryStream value) { Get(out value, new MemoryStream()); }
+
1035 public override void Get(out MemoryStream value, MemoryStream defaults)
+
1036 {
+
1037 Debug.Assert((defaults != null), "Invalid default bytes value!");
+
1038 if (defaults == null)
+
1039 throw new ArgumentNullException(nameof(defaults), "Invalid default bytes value!");
+
1040
+
1041 value = defaults;
+
1042
+
1043 if ((_buffer.Offset + FBEOffset + FBESize) > _buffer.Size)
+
1044 return;
+
1045
+
1046 uint fbeBytesOffset = ReadUInt32(FBEOffset);
+
1047 if (fbeBytesOffset == 0)
+
1048 return;
+
1049
+
1050 Debug.Assert(((_buffer.Offset + fbeBytesOffset + 4) <= _buffer.Size), "Model is broken!");
+
1051 if ((_buffer.Offset + fbeBytesOffset + 4) > _buffer.Size)
+
1052 return;
+
1053
+
1054 uint fbeBytesSize = ReadUInt32(fbeBytesOffset);
+
1055 Debug.Assert(((_buffer.Offset + fbeBytesOffset + 4 + fbeBytesSize) <= _buffer.Size), "Model is broken!");
+
1056 if ((_buffer.Offset + fbeBytesOffset + 4 + fbeBytesSize) > _buffer.Size)
+
1057 return;
+
1058
+
1059 var buffer = ReadBytes(fbeBytesOffset + 4, fbeBytesSize);
+
1060 value.Write(buffer, 0, buffer.Length);
+
1061 }
+
1062
+
1063 // Set the bytes value
+
1064 public override void Set(MemoryStream value)
+
1065 {
+
1066 Debug.Assert((value != null), "Invalid bytes value!");
+
1067 if (value == null)
+
1068 throw new ArgumentNullException(nameof(value), "Invalid bytes value!");
+
1069
+
1070 Debug.Assert(((_buffer.Offset + FBEOffset + FBESize) <= _buffer.Size), "Model is broken!");
+
1071 if ((_buffer.Offset + FBEOffset + FBESize) > _buffer.Size)
+
1072 return;
+
1073
+
1074 uint fbeBytesSize = (uint)value.Length;
+
1075 uint fbeBytesOffset = (uint)(_buffer.Allocate(4 + fbeBytesSize) - _buffer.Offset);
+
1076 Debug.Assert(((fbeBytesOffset > 0) && ((_buffer.Offset + fbeBytesOffset + 4 + fbeBytesSize) <= _buffer.Size)), "Model is broken!");
+
1077 if ((fbeBytesOffset == 0) || ((_buffer.Offset + fbeBytesOffset + 4 + fbeBytesSize) > _buffer.Size))
+
1078 return;
+
1079
+
1080 Write(FBEOffset, fbeBytesOffset);
+
1081 Write(fbeBytesOffset, fbeBytesSize);
+
1082 Write(fbeBytesOffset + 4, value.GetBuffer(), 0, fbeBytesSize);
+
1083 }
+
1084 }
+
1085)CODE";
+
1086
+
1087 // Prepare code template
+
1088 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
1089
+
1090 Write(code);
+
1091}
+
1092
+
1093void GeneratorCSharp::GenerateFBEFieldModelString()
+
1094{
+
1095 std::string code = R"CODE(
+
1096 // Fast Binary Encoding string field model
+
1097 public class FieldModelString : FieldModelReferenceType<string>
+
1098 {
+
1099 public FieldModelString(Buffer buffer, long offset) : base(buffer, offset) {}
+
1100
+
1101 // Get the field size
+
1102 public override long FBESize => 4;
+
1103 // Get the field extra size
+
1104 public override long FBEExtra
+
1105 {
+
1106 get
+
1107 {
+
1108 if ((_buffer.Offset + FBEOffset + FBESize) > _buffer.Size)
+
1109 return 0;
+
1110
+
1111 uint fbeStringOffset = ReadUInt32(FBEOffset);
+
1112 if ((fbeStringOffset == 0) || ((_buffer.Offset + fbeStringOffset + 4) > _buffer.Size))
+
1113 return 0;
+
1114
+
1115 uint fbeStringSize = ReadUInt32(fbeStringOffset);
+
1116 return 4 + fbeStringSize;
+
1117 }
+
1118 }
+
1119
+
1120 // Clone the field model
+
1121 public override FieldModelReferenceType<string> Clone() { return new FieldModelString(_buffer, _offset); }
+
1122
+
1123 // Check if the string value is valid
+
1124 public override bool Verify()
+
1125 {
+
1126 if ((_buffer.Offset + FBEOffset + FBESize) > _buffer.Size)
+
1127 return true;
+
1128
+
1129 uint fbeStringOffset = ReadUInt32(FBEOffset);
+
1130 if (fbeStringOffset == 0)
+
1131 return true;
+
1132
+
1133 if ((_buffer.Offset + fbeStringOffset + 4) > _buffer.Size)
+
1134 return false;
+
1135
+
1136 uint fbeStringSize = ReadUInt32(fbeStringOffset);
+
1137 if ((_buffer.Offset + fbeStringOffset + 4 + fbeStringSize) > _buffer.Size)
+
1138 return false;
+
1139
+
1140 return true;
+
1141 }
+
1142
+
1143 // Get the string value
+
1144 public override void Get(out string value) { Get(out value, ""); }
+
1145 public override void Get(out string value, string defaults)
+
1146 {
+
1147 Debug.Assert((defaults != null), "Invalid default string value!");
+
1148 if (defaults == null)
+
1149 throw new ArgumentNullException(nameof(defaults), "Invalid default string value!");
+
1150
+
1151 value = defaults;
+
1152
+
1153 if ((_buffer.Offset + FBEOffset + FBESize) > _buffer.Size)
+
1154 return;
+
1155
+
1156 uint fbeStringOffset = ReadUInt32(FBEOffset);
+
1157 if (fbeStringOffset == 0)
+
1158 return;
+
1159
+
1160 Debug.Assert(((_buffer.Offset + fbeStringOffset + 4) <= _buffer.Size), "Model is broken!");
+
1161 if ((_buffer.Offset + fbeStringOffset + 4) > _buffer.Size)
+
1162 return;
+
1163
+
1164 uint fbeStringSize = ReadUInt32(fbeStringOffset);
+
1165 Debug.Assert(((_buffer.Offset + fbeStringOffset + 4 + fbeStringSize) <= _buffer.Size), "Model is broken!");
+
1166 if ((_buffer.Offset + fbeStringOffset + 4 + fbeStringSize) > _buffer.Size)
+
1167 return;
+
1168
+
1169 value = ReadString(fbeStringOffset + 4, fbeStringSize);
+
1170 }
+
1171
+
1172 // Set the string value
+
1173 public override void Set(string value)
+
1174 {
+
1175 Debug.Assert((value != null), "Invalid string value!");
+
1176 if (value == null)
+
1177 throw new ArgumentNullException(nameof(value), "Invalid string value!");
+
1178
+
1179 Debug.Assert(((_buffer.Offset + FBEOffset + FBESize) <= _buffer.Size), "Model is broken!");
+
1180 if ((_buffer.Offset + FBEOffset + FBESize) > _buffer.Size)
+
1181 return;
+
1182
+
1183 uint fbeStringSize = (uint)Encoding.UTF8.GetByteCount(value);
+
1184 uint fbeStringOffset = (uint)(_buffer.Allocate(4 + fbeStringSize) - _buffer.Offset);
+
1185 Debug.Assert(((fbeStringOffset > 0) && ((_buffer.Offset + fbeStringOffset + 4 + fbeStringSize) <= _buffer.Size)), "Model is broken!");
+
1186 if ((fbeStringOffset == 0) || ((_buffer.Offset + fbeStringOffset + 4 + fbeStringSize) > _buffer.Size))
+
1187 return;
+
1188
+
1189 Write(FBEOffset, fbeStringOffset);
+
1190 Write(fbeStringOffset, fbeStringSize);
+
1191 Write(fbeStringOffset + 4, value);
+
1192 }
+
1193 }
+
1194)CODE";
+
1195
+
1196 // Prepare code template
+
1197 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
1198
+
1199 Write(code);
+
1200}
+
1201
+
1202void GeneratorCSharp::GenerateFBEFieldModelOptional(bool valueType)
+
1203{
+
1204 std::string code = R"CODE(
+
1205 // Fast Binary Encoding field model optional (_NAME_)
+
1206 public class FieldModelOptional_TYPE_<T, TModel> : FieldModelBase
+
1207 where T : _BASE_
+
1208 where TModel : FieldModel_TYPE_<T>
+
1209 {
+
1210 public FieldModelOptional_TYPE_(TModel model, Buffer buffer, long offset) : base(buffer, offset)
+
1211 {
+
1212 Value = model.Clone() as TModel;
+
1213 // Reset the optional model offset
+
1214 if (Value != null)
+
1215 Value.FBEOffset = 0;
+
1216 }
+
1217
+
1218 // Get the field size
+
1219 public override long FBESize => 1 + 4;
+
1220 // Get the field extra size
+
1221 public override long FBEExtra
+
1222 {
+
1223 get
+
1224 {
+
1225 if (!HasValue)
+
1226 return 0;
+
1227
+
1228 uint fbeOptionalOffset = ReadUInt32(FBEOffset + 1);
+
1229 if ((fbeOptionalOffset == 0) || ((_buffer.Offset + fbeOptionalOffset + 4) > _buffer.Size))
+
1230 return 0;
+
1231
+
1232 _buffer.Shift(fbeOptionalOffset);
+
1233 long fbeResult = Value.FBESize + Value.FBEExtra;
+
1234 _buffer.Unshift(fbeOptionalOffset);
+
1235 return fbeResult;
+
1236 }
+
1237 }
+
1238
+
1239 // Clone the field model
+
1240 public FieldModelOptional_TYPE_<T, TModel> Clone() { return new FieldModelOptional_TYPE_<T, TModel>(Value, _buffer, _offset); }
+
1241
+
1243 public static implicit operator bool(FieldModelOptional_TYPE_<T, TModel> optional) { return !ReferenceEquals(optional, null) && optional.HasValue; }
+
1244
+
1245 // Checks if the object contains a value
+
1246 public bool HasValue
+
1247 {
+
1248 get
+
1249 {
+
1250 if ((_buffer.Offset + FBEOffset + FBESize) > _buffer.Size)
+
1251 return false;
+
1252
+
1253 byte fbeHasValue = ReadUInt8(FBEOffset);
+
1254 return (fbeHasValue != 0);
+
1255 }
+
1256 }
+
1257
+
1258 // Base field model value
+
1259 public TModel Value { get; }
+
1260
+
1261 // Check if the optional value is valid
+
1262 public virtual bool Verify()
+
1263 {
+
1264 if ((_buffer.Offset + FBEOffset + FBESize) > _buffer.Size)
+
1265 return true;
+
1266
+
1267 byte fbeHasValue = ReadUInt8(FBEOffset);
+
1268 if (fbeHasValue == 0)
+
1269 return true;
+
1270
+
1271 uint fbeOptionalOffset = ReadUInt32(FBEOffset + 1);
+
1272 if (fbeOptionalOffset == 0)
+
1273 return false;
+
1274
+
1275 _buffer.Shift(fbeOptionalOffset);
+
1276 bool fbeResult = Value.Verify();
+
1277 _buffer.Unshift(fbeOptionalOffset);
+
1278 return fbeResult;
+
1279 }
+
1280
+
1281 // Get the optional value (being phase)
+
1282 public long GetBegin()
+
1283 {
+
1284 if (!HasValue)
+
1285 return 0;
+
1286
+
1287 uint fbeOptionalOffset = ReadUInt32(FBEOffset + 1);
+
1288 Debug.Assert((fbeOptionalOffset > 0), "Model is broken!");
+
1289 if (fbeOptionalOffset == 0)
+
1290 return 0;
+
1291
+
1292 _buffer.Shift(fbeOptionalOffset);
+
1293 return fbeOptionalOffset;
+
1294 }
+
1295
+
1296 // Get the optional value (end phase)
+
1297 public void GetEnd(long fbeBegin)
+
1298 {
+
1299 _buffer.Unshift(fbeBegin);
+
1300 }
+
1301
+
1302 // Get the optional value
+
1303 public void Get(out _ARGS_ optional, _ARGS_ defaults = null)
+
1304 {
+
1305 optional = defaults;
+
1306
+
1307 long fbeBegin = GetBegin();
+
1308 if (fbeBegin == 0)
+
1309 return;
+
1310
+
1311 Value.Get(out var temp);
+
1312 optional = temp;
+
1313
+
1314 GetEnd(fbeBegin);
+
1315 }
+
1316
+
1317 // Set the optional value (begin phase)
+
1318 public long SetBegin(bool hasValue)
+
1319 {
+
1320 Debug.Assert(((_buffer.Offset + FBEOffset + FBESize) <= _buffer.Size), "Model is broken!");
+
1321 if ((_buffer.Offset + FBEOffset + FBESize) > _buffer.Size)
+
1322 return 0;
+
1323
+
1324 byte fbeHasValue = (byte)(hasValue ? 1 : 0);
+
1325 Write(FBEOffset, fbeHasValue);
+
1326 if (fbeHasValue == 0)
+
1327 return 0;
+
1328
+
1329 uint fbeOptionalSize = (uint)Value.FBESize;
+
1330 uint fbeOptionalOffset = (uint)(_buffer.Allocate(fbeOptionalSize) - _buffer.Offset);
+
1331 Debug.Assert(((fbeOptionalOffset > 0) && ((_buffer.Offset + fbeOptionalOffset + fbeOptionalSize) <= _buffer.Size)), "Model is broken!");
+
1332 if ((fbeOptionalOffset == 0) || ((_buffer.Offset + fbeOptionalOffset + fbeOptionalSize) > _buffer.Size))
+
1333 return 0;
+
1334
+
1335 Write(FBEOffset + 1, fbeOptionalOffset);
+
1336
+
1337 _buffer.Shift(fbeOptionalOffset);
+
1338 return fbeOptionalOffset;
+
1339 }
+
1340
+
1341 // Set the optional value (end phase)
+
1342 public void SetEnd(long fbeBegin)
+
1343 {
+
1344 _buffer.Unshift(fbeBegin);
+
1345 }
+
1346
+
1347 // Set the optional value
+
1348 public void Set(_ARGS_ optional)
+
1349 {
+
1350 long fbeBegin = SetBegin(optional_HAS_VALUE_);
+
1351 if (fbeBegin == 0)
+
1352 return;
+
1353
+
1354 if (optional_HAS_VALUE_)
+
1355 Value.Set(optional_VALUE_);
+
1356
+
1357 SetEnd(fbeBegin);
+
1358 }
+
1359 }
+
1360)CODE";
+
1361
+
1362 // Prepare code template
+
1363 code = std::regex_replace(code, std::regex("_NAME_"), (valueType ? "value type" : "reference type"));
+
1364 code = std::regex_replace(code, std::regex("_TYPE_"), (valueType ? "ValueType" : "ReferenceType"));
+
1365 code = std::regex_replace(code, std::regex("_BASE_"), (valueType ? "struct" : "class"));
+
1366 code = std::regex_replace(code, std::regex("_ARGS_"), (valueType ? "T?" : "T"));
+
1367 code = std::regex_replace(code, std::regex("_HAS_VALUE_"), (valueType ? ".HasValue" : " != null"));
+
1368 code = std::regex_replace(code, std::regex("_VALUE_"), (valueType ? ".Value" : ""));
+
1369 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
1370
+
1371 Write(code);
+
1372}
+
1373
+
1374void GeneratorCSharp::GenerateFBEFieldModelArray(bool valueType, bool optional)
+
1375{
+
1376 std::string code = R"CODE(
+
1377 // Fast Binary Encoding field model array (_NAME_)
+
1378 public class FieldModelArray_TYPE_<T, TModel> : FieldModelBase
+
1379 where T : _BASE_
+
1380 where TModel : FieldModel_MODEL_REF_<T>
+
1381 {
+
1382 private readonly _MODEL_DECL_ _model;
+
1383 private readonly long _size;
+
1384
+
1385 public FieldModelArray_TYPE_(TModel model, Buffer buffer, long offset, long size) : base(buffer, offset)
+
1386 {
+
1387 _model = _MODEL_CLONE_;
+
1388 _size = size;
+
1389 }
+
1390
+
1391 // Get the field size
+
1392 public override long FBESize => _size * _model.FBESize;
+
1393 // Get the field extra size
+
1394 public override long FBEExtra => 0;
+
1395
+
1396 // Clone the field model
+
1397 public FieldModelArray_TYPE_<T, TModel> Clone() { return new FieldModelArray_TYPE_<T, TModel>(_model_MODEL_VALUE_, _buffer, _offset, _size); }
+
1398
+
1399 // Get the array offset
+
1400 public long Offset => 0;
+
1401 // Get the array size
+
1402 public long Size => _size;
+
1403
+
1404 // Array index operator
+
1405 public _MODEL_DECL_ this[long index]
+
1406 {
+
1407 get
+
1408 {
+
1409 Debug.Assert(((_buffer.Offset + FBEOffset + FBESize) <= _buffer.Size), "Model is broken!");
+
1410 Debug.Assert((index < _size), "Index is out of bounds!");
+
1411
+
1412 _model.FBEOffset = FBEOffset;
+
1413 _model.FBEShift(index * _model.FBESize);
+
1414 return _model;
+
1415 }
+
1416 }
+
1417
+
1418 // Check if the array is valid
+
1419 public virtual bool Verify()
+
1420 {
+
1421 if ((_buffer.Offset + FBEOffset + FBESize) > _buffer.Size)
+
1422 return false;
+
1423
+
1424 _model.FBEOffset = FBEOffset;
+
1425 for (long i = _size; i-- > 0;)
+
1426 {
+
1427 if (!_model.Verify())
+
1428 return false;
+
1429 _model.FBEShift(_model.FBESize);
+
1430 }
+
1431
+
1432 return true;
+
1433 }
+
1434
+
1435 // Get the array
+
1436 public void Get(ref _ARGS_[] values)
+
1437 {
+
1438 Debug.Assert((values != null), "Invalid values parameter!");
+
1439 if (values == null)
+
1440 throw new ArgumentNullException(nameof(values), "Invalid values parameter!");
+
1441
+
1442 values = new _ARGS_[_size];
+
1443
+
1444 var fbeModel = this[0];
+
1445 for (long i = 0; i < _size; i++)
+
1446 {
+
1447 fbeModel.Get(out values[i]);
+
1448 fbeModel.FBEShift(fbeModel.FBESize);
+
1449 }
+
1450 }
+
1451
+
1452 // Get the array as List
+
1453 public void Get(ref List<_ARGS_> values)
+
1454 {
+
1455 Debug.Assert((values != null), "Invalid values parameter!");
+
1456 if (values == null)
+
1457 throw new ArgumentNullException(nameof(values), "Invalid values parameter!");
+
1458
+
1459 values.Clear();
+
1460 values.Capacity = (int)_size;
+
1461
+
1462 var fbeModel = this[0];
+
1463 for (long i = _size; i-- > 0;)
+
1464 {
+
1465 fbeModel.Get(out var value);
+
1466 values.Add(value);
+
1467 fbeModel.FBEShift(fbeModel.FBESize);
+
1468 }
+
1469 }
+
1470
+
1471 // Set the array
+
1472 public void Set(_ARGS_[] values)
+
1473 {
+
1474 Debug.Assert((values != null), "Invalid values parameter!");
+
1475 if (values == null)
+
1476 throw new ArgumentNullException(nameof(values), "Invalid values parameter!");
+
1477
+
1478 Debug.Assert(((_buffer.Offset + FBEOffset + FBESize) <= _buffer.Size), "Model is broken!");
+
1479 if ((_buffer.Offset + FBEOffset + FBESize) > _buffer.Size)
+
1480 return;
+
1481
+
1482 var fbeModel = this[0];
+
1483 for (long i = 0; (i < values.Length) && (i < _size); i++)
+
1484 {
+
1485 fbeModel.Set(values[i]);
+
1486 fbeModel.FBEShift(fbeModel.FBESize);
+
1487 }
+
1488 }
+
1489
+
1490 // Set the array as List
+
1491 public void Set(List<_ARGS_> values)
+
1492 {
+
1493 Debug.Assert((values != null), "Invalid values parameter!");
+
1494 if (values == null)
+
1495 throw new ArgumentNullException(nameof(values), "Invalid values parameter!");
+
1496
+
1497 Debug.Assert(((_buffer.Offset + FBEOffset + FBESize) <= _buffer.Size), "Model is broken!");
+
1498 if ((_buffer.Offset + FBEOffset + FBESize) > _buffer.Size)
+
1499 return;
+
1500
+
1501 var fbeModel = this[0];
+
1502 for (long i = 0; (i < values.Count) && (i < _size); i++)
+
1503 {
+
1504 fbeModel.Set(values[(int)i]);
+
1505 fbeModel.FBEShift(fbeModel.FBESize);
+
1506 }
+
1507 }
+
1508 }
+
1509)CODE";
+
1510
+
1511 // Prepare code template
+
1512 code = std::regex_replace(code, std::regex("_NAME_"), (optional ? (valueType ? "optional value type" : "optional reference type") : (valueType ? "value type" : "reference type")));
+
1513 code = std::regex_replace(code, std::regex("_TYPE_"), (optional ? (valueType ? "OptionalValueType" : "OptionalReferenceType") : (valueType ? "ValueType" : "ReferenceType")));
+
1514 code = std::regex_replace(code, std::regex("_BASE_"), (valueType ? "struct" : "class"));
+
1515 code = std::regex_replace(code, std::regex("_ARGS_"), ((optional && valueType) ? "T?" : "T"));
+
1516 code = std::regex_replace(code, std::regex("_MODEL_CLONE_"), (optional ? "new FieldModelOptional_MODEL_REF_<T, TModel>(model, buffer, offset)" : "model.Clone() as TModel"));
+
1517 code = std::regex_replace(code, std::regex("_MODEL_DECL_"), (optional ? "FieldModelOptional_MODEL_REF_<T, TModel>" : "TModel"));
+
1518 code = std::regex_replace(code, std::regex("_MODEL_REF_"), (valueType ? "ValueType" : "ReferenceType"));
+
1519 code = std::regex_replace(code, std::regex("_MODEL_VALUE_"), (optional ? ".Value" : ""));
+
1520 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
1521
+
1522 Write(code);
+
1523}
+
1524
+
1525void GeneratorCSharp::GenerateFBEFieldModelVector(bool valueType, bool optional)
+
1526{
+
1527 std::string code = R"CODE(
+
1528 // Fast Binary Encoding field model vector (_NAME_)
+
1529 public class FieldModelVector_TYPE_<T, TModel> : FieldModelBase
+
1530 where T : _BASE_
+
1531 where TModel : FieldModel_MODEL_REF_<T>
+
1532 {
+
1533 private readonly _MODEL_DECL_ _model;
+
1534
+
1535 public FieldModelVector_TYPE_(TModel model, Buffer buffer, long offset) : base(buffer, offset)
+
1536 {
+
1537 _model = _MODEL_CLONE_;
+
1538 }
+
1539
+
1540 // Get the field size
+
1541 public override long FBESize => 4;
+
1542 // Get the field extra size
+
1543 public override long FBEExtra
+
1544 {
+
1545 get
+
1546 {
+
1547 if ((_buffer.Offset + FBEOffset + FBESize) > _buffer.Size)
+
1548 return 0;
+
1549
+
1550 uint fbeVectorOffset = ReadUInt32(FBEOffset);
+
1551 if ((fbeVectorOffset == 0) || ((_buffer.Offset + fbeVectorOffset + 4) > _buffer.Size))
+
1552 return 0;
+
1553
+
1554 uint fbeVectorSize = ReadUInt32(fbeVectorOffset);
+
1555
+
1556 long fbeResult = 4;
+
1557 _model.FBEOffset = fbeVectorOffset + 4;
+
1558 for (uint i = fbeVectorSize; i-- > 0;)
+
1559 {
+
1560 fbeResult += _model.FBESize + _model.FBEExtra;
+
1561 _model.FBEShift(_model.FBESize);
+
1562 }
+
1563 return fbeResult;
+
1564 }
+
1565 }
+
1566
+
1567 // Clone the field model
+
1568 public FieldModelVector_TYPE_<T, TModel> Clone() { return new FieldModelVector_TYPE_<T, TModel>(_model_MODEL_VALUE_, _buffer, _offset); }
+
1569
+
1570 // Get the vector offset
+
1571 public long Offset
+
1572 {
+
1573 get
+
1574 {
+
1575 if ((_buffer.Offset + FBEOffset + FBESize) > _buffer.Size)
+
1576 return 0;
+
1577
+
1578 uint fbeVectorOffset = ReadUInt32(FBEOffset);
+
1579 return fbeVectorOffset;
+
1580 }
+
1581 }
+
1582
+
1583 // Get the vector size
+
1584 public long Size
+
1585 {
+
1586 get
+
1587 {
+
1588 if ((_buffer.Offset + FBEOffset + FBESize) > _buffer.Size)
+
1589 return 0;
+
1590
+
1591 uint fbeVectorOffset = ReadUInt32(FBEOffset);
+
1592 if ((fbeVectorOffset == 0) || ((_buffer.Offset + fbeVectorOffset + 4) > _buffer.Size))
+
1593 return 0;
+
1594
+
1595 uint fbeVectorSize = ReadUInt32(fbeVectorOffset);
+
1596 return fbeVectorSize;
+
1597 }
+
1598 }
+
1599
+
1600 // Vector index operator
+
1601 public _MODEL_DECL_ this[long index]
+
1602 {
+
1603 get
+
1604 {
+
1605 Debug.Assert(((_buffer.Offset + FBEOffset + FBESize) <= _buffer.Size), "Model is broken!");
+
1606
+
1607 uint fbeVectorOffset = ReadUInt32(FBEOffset);
+
1608 Debug.Assert(((fbeVectorOffset > 0) && ((_buffer.Offset + fbeVectorOffset + 4) <= _buffer.Size)), "Model is broken!");
+
1609
+
1610 uint fbeVectorSize = ReadUInt32(fbeVectorOffset);
+
1611 Debug.Assert((index < fbeVectorSize), "Index is out of bounds!");
+
1612
+
1613 _model.FBEOffset = fbeVectorOffset + 4;
+
1614 _model.FBEShift(index * _model.FBESize);
+
1615 return _model;
+
1616 }
+
1617 }
+
1618
+
1619 // Resize the vector and get its first model
+
1620 public _MODEL_DECL_ Resize(long size)
+
1621 {
+
1622 uint fbeVectorSize = (uint)(size * _model.FBESize);
+
1623 uint fbeVectorOffset = (uint)(_buffer.Allocate(4 + fbeVectorSize) - _buffer.Offset);
+
1624 Debug.Assert(((fbeVectorOffset > 0) && ((_buffer.Offset + fbeVectorOffset + 4) <= _buffer.Size)), "Model is broken!");
+
1625
+
1626 Write(FBEOffset, fbeVectorOffset);
+
1627 Write(fbeVectorOffset, (uint)size);
+
1628 Write(fbeVectorOffset + 4, 0, fbeVectorSize);
+
1629
+
1630 _model.FBEOffset = fbeVectorOffset + 4;
+
1631 return _model;
+
1632 }
+
1633
+
1634 // Check if the vector is valid
+
1635 public virtual bool Verify()
+
1636 {
+
1637 if ((_buffer.Offset + FBEOffset + FBESize) > _buffer.Size)
+
1638 return true;
+
1639
+
1640 uint fbeVectorOffset = ReadUInt32(FBEOffset);
+
1641 if (fbeVectorOffset == 0)
+
1642 return true;
+
1643
+
1644 if ((_buffer.Offset + fbeVectorOffset + 4) > _buffer.Size)
+
1645 return false;
+
1646
+
1647 uint fbeVectorSize = ReadUInt32(fbeVectorOffset);
+
1648
+
1649 _model.FBEOffset = fbeVectorOffset + 4;
+
1650 for (uint i = fbeVectorSize; i-- > 0;)
+
1651 {
+
1652 if (!_model.Verify())
+
1653 return false;
+
1654 _model.FBEShift(_model.FBESize);
+
1655 }
+
1656
+
1657 return true;
+
1658 }
+
1659
+
1660 // Get the vector as List
+
1661 public void Get(ref List<_ARGS_> values)
+
1662 {
+
1663 Debug.Assert((values != null), "Invalid values parameter!");
+
1664 if (values == null)
+
1665 throw new ArgumentNullException(nameof(values), "Invalid values parameter!");
+
1666
+
1667 values.Clear();
+
1668
+
1669 long fbeVectorSize = Size;
+
1670 if (fbeVectorSize == 0)
+
1671 return;
+
1672
+
1673 values.Capacity = (int)fbeVectorSize;
+
1674
+
1675 var fbeModel = this[0];
+
1676 for (long i = fbeVectorSize; i-- > 0;)
+
1677 {
+
1678 fbeModel.Get(out var value);
+
1679 values.Add(value);
+
1680 fbeModel.FBEShift(fbeModel.FBESize);
+
1681 }
+
1682 }
+
1683
+
1684 // Get the vector as LinkedList
+
1685 public void Get(ref LinkedList<_ARGS_> values)
+
1686 {
+
1687 Debug.Assert((values != null), "Invalid values parameter!");
+
1688 if (values == null)
+
1689 throw new ArgumentNullException(nameof(values), "Invalid values parameter!");
+
1690
+
1691 values.Clear();
+
1692
+
1693 long fbeVectorSize = Size;
+
1694 if (fbeVectorSize == 0)
+
1695 return;
+
1696
+
1697 var fbeModel = this[0];
+
1698 for (long i = fbeVectorSize; i-- > 0;)
+
1699 {
+
1700 fbeModel.Get(out var value);
+
1701 values.AddLast(value);
+
1702 fbeModel.FBEShift(fbeModel.FBESize);
+
1703 }
+
1704 }
+
1705
+
1706 // Get the vector as HashSet
+
1707 public void Get(ref HashSet<_ARGS_> values)
+
1708 {
+
1709 Debug.Assert((values != null), "Invalid values parameter!");
+
1710 if (values == null)
+
1711 throw new ArgumentNullException(nameof(values), "Invalid values parameter!");
+
1712
+
1713 values.Clear();
+
1714
+
1715 long fbeVectorSize = Size;
+
1716 if (fbeVectorSize == 0)
+
1717 return;
+
1718
+
1719 var fbeModel = this[0];
+
1720 for (long i = fbeVectorSize; i-- > 0;)
+
1721 {
+
1722 fbeModel.Get(out var value);
+
1723 values.Add(value);
+
1724 fbeModel.FBEShift(fbeModel.FBESize);
+
1725 }
+
1726 }
+
1727
+
1728 // Set the vector as List
+
1729 public void Set(List<_ARGS_> values)
+
1730 {
+
1731 Debug.Assert((values != null), "Invalid values parameter!");
+
1732 if (values == null)
+
1733 throw new ArgumentNullException(nameof(values), "Invalid values parameter!");
+
1734
+
1735 Debug.Assert(((_buffer.Offset + FBEOffset + FBESize) <= _buffer.Size), "Model is broken!");
+
1736 if ((_buffer.Offset + FBEOffset + FBESize) > _buffer.Size)
+
1737 return;
+
1738
+
1739 var fbeModel = Resize(values.Count);
+
1740 foreach (var value in values)
+
1741 {
+
1742 fbeModel.Set(value);
+
1743 fbeModel.FBEShift(fbeModel.FBESize);
+
1744 }
+
1745 }
+
1746
+
1747 // Set the vector as LinkedList
+
1748 public void Set(LinkedList<_ARGS_> values)
+
1749 {
+
1750 Debug.Assert((values != null), "Invalid values parameter!");
+
1751 if (values == null)
+
1752 throw new ArgumentNullException(nameof(values), "Invalid values parameter!");
+
1753
+
1754 Debug.Assert(((_buffer.Offset + FBEOffset + FBESize) <= _buffer.Size), "Model is broken!");
+
1755 if ((_buffer.Offset + FBEOffset + FBESize) > _buffer.Size)
+
1756 return;
+
1757
+
1758 var fbeModel = Resize(values.Count);
+
1759 foreach (var value in values)
+
1760 {
+
1761 fbeModel.Set(value);
+
1762 fbeModel.FBEShift(fbeModel.FBESize);
+
1763 }
+
1764 }
+
1765
+
1766 // Set the vector as HashSet
+
1767 public void Set(HashSet<_ARGS_> values)
+
1768 {
+
1769 Debug.Assert((values != null), "Invalid values parameter!");
+
1770 if (values == null)
+
1771 throw new ArgumentNullException(nameof(values), "Invalid values parameter!");
+
1772
+
1773 Debug.Assert(((_buffer.Offset + FBEOffset + FBESize) <= _buffer.Size), "Model is broken!");
+
1774 if ((_buffer.Offset + FBEOffset + FBESize) > _buffer.Size)
+
1775 return;
+
1776
+
1777 var fbeModel = Resize(values.Count);
+
1778 foreach (var value in values)
+
1779 {
+
1780 fbeModel.Set(value);
+
1781 fbeModel.FBEShift(fbeModel.FBESize);
+
1782 }
+
1783 }
+
1784 }
+
1785)CODE";
+
1786
+
1787 // Prepare code template
+
1788 code = std::regex_replace(code, std::regex("_NAME_"), (optional ? (valueType ? "optional value type" : "optional reference type") : (valueType ? "value type" : "reference type")));
+
1789 code = std::regex_replace(code, std::regex("_TYPE_"), (optional ? (valueType ? "OptionalValueType" : "OptionalReferenceType") : (valueType ? "ValueType" : "ReferenceType")));
+
1790 code = std::regex_replace(code, std::regex("_BASE_"), (valueType ? "struct" : "class"));
+
1791 code = std::regex_replace(code, std::regex("_ARGS_"), ((optional && valueType) ? "T?" : "T"));
+
1792 code = std::regex_replace(code, std::regex("_MODEL_CLONE_"), (optional ? "new FieldModelOptional_MODEL_REF_<T, TModel>(model, buffer, offset)" : "model.Clone() as TModel"));
+
1793 code = std::regex_replace(code, std::regex("_MODEL_DECL_"), (optional ? "FieldModelOptional_MODEL_REF_<T, TModel>" : "TModel"));
+
1794 code = std::regex_replace(code, std::regex("_MODEL_REF_"), (valueType ? "ValueType" : "ReferenceType"));
+
1795 code = std::regex_replace(code, std::regex("_MODEL_VALUE_"), (optional ? ".Value" : ""));
+
1796 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
1797
+
1798 Write(code);
+
1799}
+
1800
+
1801void GeneratorCSharp::GenerateFBEFieldModelMap(bool valueTypeKey, bool valueTypeValue, bool optional)
+
1802{
+
1803 std::string code = R"CODE(
+
1804 // Fast Binary Encoding field model map (_NAME_KEY_, _NAME_VALUE_)
+
1805 public class FieldModelMap_TYPE_KEY__TYPE_VALUE_<TKey, TKeyModel, TValue, TValueModel> : FieldModelBase
+
1806 where TKey : _BASE_KEY_
+
1807 where TKeyModel : FieldModel_MODEL_KEY_REF_<TKey>
+
1808 where TValue : _BASE_VALUE_
+
1809 where TValueModel : FieldModel_MODEL_VALUE_REF_<TValue>
+
1810 {
+
1811 private readonly _MODEL_KEY_DECL_ _modelKey;
+
1812 private readonly _MODEL_VALUE_DECL_ _modelValue;
+
1813
+
1814 public FieldModelMap_TYPE_KEY__TYPE_VALUE_(TKeyModel modelKey, TValueModel modelValue, Buffer buffer, long offset) : base(buffer, offset)
+
1815 {
+
1816 _modelKey = _MODEL_KEY_CLONE_;
+
1817 _modelValue = _MODEL_VALUE_CLONE_;
+
1818 }
+
1819
+
1820 // Get the field size
+
1821 public override long FBESize => 4;
+
1822 // Get the field extra size
+
1823 public override long FBEExtra
+
1824 {
+
1825 get
+
1826 {
+
1827 if ((_buffer.Offset + FBEOffset + FBESize) > _buffer.Size)
+
1828 return 0;
+
1829
+
1830 uint fbeMapOffset = ReadUInt32(FBEOffset);
+
1831 if ((fbeMapOffset == 0) || ((_buffer.Offset + fbeMapOffset + 4) > _buffer.Size))
+
1832 return 0;
+
1833
+
1834 uint fbeMapSize = ReadUInt32(fbeMapOffset);
+
1835
+
1836 long fbeResult = 4;
+
1837 _modelKey.FBEOffset = fbeMapOffset + 4;
+
1838 _modelValue.FBEOffset = fbeMapOffset + 4 + _modelKey.FBESize;
+
1839 for (uint i = fbeMapSize; i-- > 0;)
+
1840 {
+
1841 fbeResult += _modelKey.FBESize + _modelKey.FBEExtra;
+
1842 _modelKey.FBEShift(_modelKey.FBESize + _modelValue.FBESize);
+
1843
+
1844 fbeResult += _modelValue.FBESize + _modelValue.FBEExtra;
+
1845 _modelValue.FBEShift(_modelKey.FBESize + _modelValue.FBESize);
+
1846 }
+
1847 return fbeResult;
+
1848 }
+
1849 }
+
1850
+
1851 // Clone the field model
+
1852 public FieldModelMap_TYPE_KEY__TYPE_VALUE_<TKey, TKeyModel, TValue, TValueModel> Clone() { return new FieldModelMap_TYPE_KEY__TYPE_VALUE_<TKey, TKeyModel, TValue, TValueModel>(_modelKey_MODEL_KEY_VALUE_, _modelValue_MODEL_VALUE_VALUE_, _buffer, _offset); }
+
1853
+
1854 // Get the map offset
+
1855 public long Offset
+
1856 {
+
1857 get
+
1858 {
+
1859 if ((_buffer.Offset + FBEOffset + FBESize) > _buffer.Size)
+
1860 return 0;
+
1861
+
1862 uint fbeMapOffset = ReadUInt32(FBEOffset);
+
1863 return fbeMapOffset;
+
1864 }
+
1865 }
+
1866
+
1867 // Get the map size
+
1868 public long Size
+
1869 {
+
1870 get
+
1871 {
+
1872 if ((_buffer.Offset + FBEOffset + FBESize) > _buffer.Size)
+
1873 return 0;
+
1874
+
1875 uint fbeMapOffset = ReadUInt32(FBEOffset);
+
1876 if ((fbeMapOffset == 0) || ((_buffer.Offset + fbeMapOffset + 4) > _buffer.Size))
+
1877 return 0;
+
1878
+
1879 uint fbeMapSize = ReadUInt32(fbeMapOffset);
+
1880 return fbeMapSize;
+
1881 }
+
1882 }
+
1883
+
1884 // Map index operator
+
1885 public KeyValuePair<_MODEL_KEY_DECL_, _MODEL_VALUE_DECL_> this[long index]
+
1886 {
+
1887 get
+
1888 {
+
1889 Debug.Assert(((_buffer.Offset + FBEOffset + FBESize) <= _buffer.Size), "Model is broken!");
+
1890
+
1891 uint fbeMapOffset = ReadUInt32(FBEOffset);
+
1892 Debug.Assert(((fbeMapOffset > 0) && ((_buffer.Offset + fbeMapOffset + 4) <= _buffer.Size)), "Model is broken!");
+
1893
+
1894 uint fbeMapSize = ReadUInt32(fbeMapOffset);
+
1895 Debug.Assert((index < fbeMapSize), "Index is out of bounds!");
+
1896
+
1897 _modelKey.FBEOffset = fbeMapOffset + 4;
+
1898 _modelValue.FBEOffset = fbeMapOffset + 4 + _modelKey.FBESize;
+
1899 _modelKey.FBEShift(index * (_modelKey.FBESize + _modelValue.FBESize));
+
1900 _modelValue.FBEShift(index * (_modelKey.FBESize + _modelValue.FBESize));
+
1901 return new KeyValuePair<_MODEL_KEY_DECL_, _MODEL_VALUE_DECL_>(_modelKey, _modelValue);
+
1902 }
+
1903 }
+
1904
+
1905 // Resize the map and get its first model
+
1906 public KeyValuePair<_MODEL_KEY_DECL_, _MODEL_VALUE_DECL_> Resize(long size)
+
1907 {
+
1908 uint fbeMapSize = (uint)(size * (_modelKey.FBESize + _modelValue.FBESize));
+
1909 uint fbeMapOffset = (uint)(_buffer.Allocate(4 + fbeMapSize) - _buffer.Offset);
+
1910 Debug.Assert(((fbeMapOffset > 0) && ((_buffer.Offset + fbeMapOffset + 4) <= _buffer.Size)), "Model is broken!");
+
1911
+
1912 Write(FBEOffset, fbeMapOffset);
+
1913 Write(fbeMapOffset, (uint)size);
+
1914 Write(fbeMapOffset + 4, 0, fbeMapSize);
+
1915
+
1916 _modelKey.FBEOffset = fbeMapOffset + 4;
+
1917 _modelValue.FBEOffset = fbeMapOffset + 4 + _modelKey.FBESize;
+
1918 return new KeyValuePair<_MODEL_KEY_DECL_, _MODEL_VALUE_DECL_>(_modelKey, _modelValue);
+
1919 }
+
1920
+
1921 // Check if the map is valid
+
1922 public virtual bool Verify()
+
1923 {
+
1924 if ((_buffer.Offset + FBEOffset + FBESize) > _buffer.Size)
+
1925 return true;
+
1926
+
1927 uint fbeMapOffset = ReadUInt32(FBEOffset);
+
1928 if (fbeMapOffset == 0)
+
1929 return true;
+
1930
+
1931 if ((_buffer.Offset + fbeMapOffset + 4) > _buffer.Size)
+
1932 return false;
+
1933
+
1934 uint fbeMapSize = ReadUInt32(fbeMapOffset);
+
1935
+
1936 _modelKey.FBEOffset = fbeMapOffset + 4;
+
1937 _modelValue.FBEOffset = fbeMapOffset + 4 + _modelKey.FBESize;
+
1938 for (uint i = fbeMapSize; i-- > 0;)
+
1939 {
+
1940 if (!_modelKey.Verify())
+
1941 return false;
+
1942 _modelKey.FBEShift(_modelKey.FBESize + _modelValue.FBESize);
+
1943 if (!_modelValue.Verify())
+
1944 return false;
+
1945 _modelValue.FBEShift(_modelKey.FBESize + _modelValue.FBESize);
+
1946 }
+
1947
+
1948 return true;
+
1949 }
+
1950
+
1951 // Get the map as Dictionary
+
1952 public void Get(ref Dictionary<_ARGS_KEY_, _ARGS_VALUE_> values)
+
1953 {
+
1954 Debug.Assert((values != null), "Invalid values parameter!");
+
1955 if (values == null)
+
1956 throw new ArgumentNullException(nameof(values), "Invalid values parameter!");
+
1957
+
1958 values.Clear();
+
1959
+
1960 long fbeMapSize = Size;
+
1961 if (fbeMapSize == 0)
+
1962 return;
+
1963
+
1964 var fbeModel = this[0];
+
1965 for (long i = fbeMapSize; i-- > 0;)
+
1966 {
+
1967 fbeModel.Key.Get(out var key);
+
1968 fbeModel.Value.Get(out var value);
+
1969 values.Add(key, value);
+
1970 fbeModel.Key.FBEShift(fbeModel.Key.FBESize + fbeModel.Value.FBESize);
+
1971 fbeModel.Value.FBEShift(fbeModel.Key.FBESize + fbeModel.Value.FBESize);
+
1972 }
+
1973 }
+
1974
+
1975 // Get the map as SortedDictionary
+
1976 public void Get(ref SortedDictionary<_ARGS_KEY_, _ARGS_VALUE_> values)
+
1977 {
+
1978 Debug.Assert((values != null), "Invalid values parameter!");
+
1979 if (values == null)
+
1980 throw new ArgumentNullException(nameof(values), "Invalid values parameter!");
+
1981
+
1982 values.Clear();
+
1983
+
1984 long fbeMapSize = Size;
+
1985 if (fbeMapSize == 0)
+
1986 return;
+
1987
+
1988 var fbeModel = this[0];
+
1989 for (long i = fbeMapSize; i-- > 0;)
+
1990 {
+
1991 fbeModel.Key.Get(out var key);
+
1992 fbeModel.Value.Get(out var value);
+
1993 values.Add(key, value);
+
1994 fbeModel.Key.FBEShift(fbeModel.Key.FBESize + fbeModel.Value.FBESize);
+
1995 fbeModel.Value.FBEShift(fbeModel.Key.FBESize + fbeModel.Value.FBESize);
+
1996 }
+
1997 }
+
1998
+
1999 // Set the map as Dictionary
+
2000 public void Set(Dictionary<_ARGS_KEY_, _ARGS_VALUE_> values)
+
2001 {
+
2002 Debug.Assert((values != null), "Invalid values parameter!");
+
2003 if (values == null)
+
2004 throw new ArgumentNullException(nameof(values), "Invalid values parameter!");
+
2005
+
2006 Debug.Assert(((_buffer.Offset + FBEOffset + FBESize) <= _buffer.Size), "Model is broken!");
+
2007 if ((_buffer.Offset + FBEOffset + FBESize) > _buffer.Size)
+
2008 return;
+
2009
+
2010 var fbeModel = Resize(values.Count);
+
2011 foreach (var value in values)
+
2012 {
+
2013 fbeModel.Key.Set(value.Key);
+
2014 fbeModel.Key.FBEShift(fbeModel.Key.FBESize + fbeModel.Value.FBESize);
+
2015 fbeModel.Value.Set(value.Value);
+
2016 fbeModel.Value.FBEShift(fbeModel.Key.FBESize + fbeModel.Value.FBESize);
+
2017 }
+
2018 }
+
2019
+
2020 // Set the map as SortedDictionary
+
2021 public void Set(SortedDictionary<_ARGS_KEY_, _ARGS_VALUE_> values)
+
2022 {
+
2023 Debug.Assert((values != null), "Invalid values parameter!");
+
2024 if (values == null)
+
2025 throw new ArgumentNullException(nameof(values), "Invalid values parameter!");
+
2026
+
2027 Debug.Assert(((_buffer.Offset + FBEOffset + FBESize) <= _buffer.Size), "Model is broken!");
+
2028 if ((_buffer.Offset + FBEOffset + FBESize) > _buffer.Size)
+
2029 return;
+
2030
+
2031 var fbeModel = Resize(values.Count);
+
2032 foreach (var value in values)
+
2033 {
+
2034 fbeModel.Key.Set(value.Key);
+
2035 fbeModel.Key.FBEShift(fbeModel.Key.FBESize + fbeModel.Value.FBESize);
+
2036 fbeModel.Value.Set(value.Value);
+
2037 fbeModel.Value.FBEShift(fbeModel.Key.FBESize + fbeModel.Value.FBESize);
+
2038 }
+
2039 }
+
2040 }
+
2041)CODE";
+
2042
+
2043 // Prepare code template
+
2044 code = std::regex_replace(code, std::regex("_NAME_KEY_"), (valueTypeKey ? "value type key" : "reference type key"));
+
2045 code = std::regex_replace(code, std::regex("_NAME_VALUE_"), (optional ? (valueTypeValue ? "optional value type value" : "optional reference type value") : (valueTypeValue ? "value type value" : "reference type value")));
+
2046 code = std::regex_replace(code, std::regex("_TYPE_KEY_"), (valueTypeKey ? "ValueTypeKey" : "ReferenceTypeKey"));
+
2047 code = std::regex_replace(code, std::regex("_TYPE_VALUE_"), (optional ? (valueTypeValue ? "OptionalValueTypeValue" : "OptionalReferenceTypeValue") : (valueTypeValue ? "ValueTypeValue" : "ReferenceTypeValue")));
+
2048 code = std::regex_replace(code, std::regex("_BASE_KEY_"), (valueTypeKey ? "struct" : "class"));
+
2049 code = std::regex_replace(code, std::regex("_BASE_VALUE_"), (valueTypeValue ? "struct" : "class"));
+
2050 code = std::regex_replace(code, std::regex("_ARGS_KEY_"), "TKey");
+
2051 code = std::regex_replace(code, std::regex("_ARGS_VALUE_"), ((optional && valueTypeValue) ? "TValue?" : "TValue"));
+
2052 code = std::regex_replace(code, std::regex("_MODEL_KEY_CLONE_"), "modelKey.Clone() as TKeyModel");
+
2053 code = std::regex_replace(code, std::regex("_MODEL_KEY_DECL_"), "TKeyModel");
+
2054 code = std::regex_replace(code, std::regex("_MODEL_KEY_REF_"), (valueTypeKey ? "ValueType" : "ReferenceType"));
+
2055 code = std::regex_replace(code, std::regex("_MODEL_KEY_VALUE_"), "");
+
2056 code = std::regex_replace(code, std::regex("_MODEL_VALUE_CLONE_"), (optional ? "new FieldModelOptional_MODEL_VALUE_REF_<TValue, TValueModel>(modelValue, buffer, offset)" : "modelValue.Clone() as TValueModel"));
+
2057 code = std::regex_replace(code, std::regex("_MODEL_VALUE_DECL_"), (optional ? "FieldModelOptional_MODEL_VALUE_REF_<TValue, TValueModel>" : "TValueModel"));
+
2058 code = std::regex_replace(code, std::regex("_MODEL_VALUE_REF_"), (valueTypeValue ? "ValueType" : "ReferenceType"));
+
2059 code = std::regex_replace(code, std::regex("_MODEL_VALUE_VALUE_"), (optional ? ".Value" : ""));
+
2060 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2061
+
2062 Write(code);
+
2063}
+
2064
+
2065void GeneratorCSharp::GenerateFBEFinalModelBase()
+
2066{
+
2067 std::string code = R"CODE(
+
2068 // Fast Binary Encoding final model value type
+
2069 public abstract class FinalModelValueType<T> : FieldModelBase
+
2070 where T : struct
+
2071 {
+
2072 protected FinalModelValueType(Buffer buffer, long offset) : base(buffer, offset) {}
+
2073
+
2074 // Get the allocation size
+
2075 public abstract long FBEAllocationSize(T value);
+
2076
+
2077 // Clone the final model
+
2078 public abstract FinalModelValueType<T> Clone();
+
2079
+
2080 // Check if the value is valid
+
2081 public abstract long Verify();
+
2082
+
2083 // Get the value
+
2084 public abstract long Get(out T value);
+
2085
+
2086 // Set the value
+
2087 public abstract long Set(T value);
+
2088
+
2089 // Create final model of the given type
+
2090 public static FinalModelValueType<T> CreateFinalModel(BaseTypes type, Buffer buffer, long offset)
+
2091 {
+
2092 switch (type)
+
2093 {
+
2094 case BaseTypes.BOOL:
+
2095 return new FinalModelBool(buffer, offset) as FinalModelValueType<T>;
+
2096 case BaseTypes.BYTE:
+
2097 return new FinalModelByte(buffer, offset) as FinalModelValueType<T>;
+
2098 case BaseTypes.CHAR:
+
2099 return new FinalModelChar(buffer, offset) as FinalModelValueType<T>;
+
2100 case BaseTypes.WCHAR:
+
2101 return new FinalModelWChar(buffer, offset) as FinalModelValueType<T>;
+
2102 case BaseTypes.INT8:
+
2103 return new FinalModelInt8(buffer, offset) as FinalModelValueType<T>;
+
2104 case BaseTypes.UINT8:
+
2105 return new FinalModelUInt8(buffer, offset) as FinalModelValueType<T>;
+
2106 case BaseTypes.INT16:
+
2107 return new FinalModelInt16(buffer, offset) as FinalModelValueType<T>;
+
2108 case BaseTypes.UINT16:
+
2109 return new FinalModelUInt16(buffer, offset) as FinalModelValueType<T>;
+
2110 case BaseTypes.INT32:
+
2111 return new FinalModelInt32(buffer, offset) as FinalModelValueType<T>;
+
2112 case BaseTypes.UINT32:
+
2113 return new FinalModelUInt32(buffer, offset) as FinalModelValueType<T>;
+
2114 case BaseTypes.INT64:
+
2115 return new FinalModelInt64(buffer, offset) as FinalModelValueType<T>;
+
2116 case BaseTypes.UINT64:
+
2117 return new FinalModelUInt64(buffer, offset) as FinalModelValueType<T>;
+
2118 case BaseTypes.FLOAT:
+
2119 return new FinalModelFloat(buffer, offset) as FinalModelValueType<T>;
+
2120 case BaseTypes.DOUBLE:
+
2121 return new FinalModelDouble(buffer, offset) as FinalModelValueType<T>;
+
2122 case BaseTypes.DECIMAL:
+
2123 return new FinalModelDecimal(buffer, offset) as FinalModelValueType<T>;
+
2124 case BaseTypes.UUID:
+
2125 return new FinalModelUUID(buffer, offset) as FinalModelValueType<T>;
+
2126 case BaseTypes.TIMESTAMP:
+
2127 return new FinalModelTimestamp(buffer, offset) as FinalModelValueType<T>;
+
2128 default:
+
2129 Debug.Assert(false, "Unknown type!");
+
2130 return null;
+
2131 }
+
2132 }
+
2133 }
+
2134
+
2135 // Fast Binary Encoding final model reference type
+
2136 public abstract class FinalModelReferenceType<T> : FieldModelBase
+
2137 where T : class
+
2138 {
+
2139 protected FinalModelReferenceType(Buffer buffer, long offset) : base(buffer, offset) {}
+
2140
+
2141 // Get the allocation size
+
2142 public abstract long FBEAllocationSize(T value);
+
2143
+
2144 // Clone the final model
+
2145 public abstract FinalModelReferenceType<T> Clone();
+
2146
+
2147 // Check if the value is valid
+
2148 public abstract long Verify();
+
2149
+
2150 // Get the value
+
2151 public abstract long Get(out T value);
+
2152
+
2153 // Set the value
+
2154 public abstract long Set(T value);
+
2155
+
2156 // Create final model of the given type
+
2157 public static FinalModelReferenceType<T> CreateFinalModel(BaseTypes type, Buffer buffer, long offset)
+
2158 {
+
2159 switch (type)
+
2160 {
+
2161 case BaseTypes.BYTES:
+
2162 return new FinalModelBytes(buffer, offset) as FinalModelReferenceType<T>;
+
2163 case BaseTypes.STRING:
+
2164 return new FinalModelString(buffer, offset) as FinalModelReferenceType<T>;
+
2165 default:
+
2166 Debug.Assert(false, "Unknown type!");
+
2167 return null;
+
2168 }
+
2169 }
+
2170 }
+
2171)CODE";
+
2172
+
2173 // Prepare code template
+
2174 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2175
+
2176 Write(code);
+
2177}
+
2178
+
2179void GeneratorCSharp::GenerateFBEFinalModel(const std::string& name, const std::string& type, const std::string& base, const std::string& size, const std::string& defaults)
+
2180{
+
2181 std::string code = R"CODE(
+
2182 // Fast Binary Encoding _TYPE_ final model
+
2183 public class FinalModel_NAME_ : FinalModelValueType<_TYPE_>
+
2184 {
+
2185 public FinalModel_NAME_(Buffer buffer, long offset) : base(buffer, offset) {}
+
2186
+
2187 // Get the allocation size
+
2188 public override long FBEAllocationSize(_TYPE_ value) { return FBESize; }
+
2189
+
2190 // Get the final size
+
2191 public override long FBESize => _SIZE_;
+
2192
+
2193 // Clone the final model
+
2194 public override FinalModelValueType<_TYPE_> Clone() { return new FinalModel_NAME_(_buffer, _offset); }
+
2195
+
2196 // Check if the value is valid
+
2197 public override long Verify()
+
2198 {
+
2199 if ((_buffer.Offset + FBEOffset + FBESize) > _buffer.Size)
+
2200 return long.MaxValue;
+
2201
+
2202 return FBESize;
+
2203 }
+
2204
+
2205 // Get the value
+
2206 public override long Get(out _TYPE_ value)
+
2207 {
+
2208 if ((_buffer.Offset + FBEOffset + FBESize) > _buffer.Size)
+
2209 {
+
2210 value = _DEFAULTS_;
+
2211 return 0;
+
2212 }
+
2213
+
2214 value = Read_NAME_(FBEOffset);
+
2215 return FBESize;
+
2216 }
+
2217
+
2218 // Set the value
+
2219 public override long Set(_TYPE_ value)
+
2220 {
+
2221 Debug.Assert(((_buffer.Offset + FBEOffset + FBESize) <= _buffer.Size), "Model is broken!");
+
2222 if ((_buffer.Offset + FBEOffset + FBESize) > _buffer.Size)
+
2223 return 0;
+
2224
+
2225 Write(FBEOffset, _BASE_value);
+
2226 return FBESize;
+
2227 }
+
2228 }
+
2229)CODE";
+
2230
+
2231 // Prepare code template
+
2232 code = std::regex_replace(code, std::regex("_NAME_"), name);
+
2233 code = std::regex_replace(code, std::regex("_TYPE_"), type);
+
2234 code = std::regex_replace(code, std::regex("_BASE_"), base);
+
2235 code = std::regex_replace(code, std::regex("_SIZE_"), size);
+
2236 code = std::regex_replace(code, std::regex("_DEFAULTS_"), defaults);
+
2237 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2238
+
2239 Write(code);
+
2240}
+
2241
+
2242void GeneratorCSharp::GenerateFBEFinalModelTimestamp()
+
2243{
+
2244 std::string code = R"CODE(
+
2245 // Fast Binary Encoding timestamp final model
+
2246 public class FinalModelTimestamp : FinalModelValueType<DateTime>
+
2247 {
+
2248 private const long UnixEpoch = 621355968000000000;
+
2249
+
2250 public FinalModelTimestamp(Buffer buffer, long offset) : base(buffer, offset) {}
+
2251
+
2252 // Get the allocation size
+
2253 public override long FBEAllocationSize(DateTime value) { return FBESize; }
+
2254
+
2255 // Get the final size
+
2256 public override long FBESize => 8;
+
2257
+
2258 // Clone the final model
+
2259 public override FinalModelValueType<DateTime> Clone() { return new FinalModelTimestamp(_buffer, _offset); }
+
2260
+
2261 // Check if the temestamp value is valid
+
2262 public override long Verify()
+
2263 {
+
2264 if ((_buffer.Offset + FBEOffset + FBESize) > _buffer.Size)
+
2265 return long.MaxValue;
+
2266
+
2267 return FBESize;
+
2268 }
+
2269
+
2270 // Get the timestamp value
+
2271 public override long Get(out DateTime value)
+
2272 {
+
2273 if ((_buffer.Offset + FBEOffset + FBESize) > _buffer.Size)
+
2274 {
+
2275 value = new DateTime(UnixEpoch, DateTimeKind.Utc);
+
2276 return 0;
+
2277 }
+
2278
+
2279 ulong ticks = ReadUInt64(FBEOffset) / 100;
+
2280 value = new DateTime((long)(UnixEpoch + ticks), DateTimeKind.Utc);
+
2281 return FBESize;
+
2282 }
+
2283
+
2284 // Set the timestamp value
+
2285 public override long Set(DateTime value)
+
2286 {
+
2287 Debug.Assert(((_buffer.Offset + FBEOffset + FBESize) <= _buffer.Size), "Model is broken!");
+
2288 if ((_buffer.Offset + FBEOffset + FBESize) > _buffer.Size)
+
2289 return 0;
+
2290
+
2291 ulong nanoseconds = (ulong)((value.Ticks - UnixEpoch) * 100);
+
2292 Write(FBEOffset, nanoseconds);
+
2293 return FBESize;
+
2294 }
+
2295 }
+
2296)CODE";
+
2297
+
2298 // Prepare code template
+
2299 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2300
+
2301 Write(code);
+
2302}
+
2303
+
2304void GeneratorCSharp::GenerateFBEFinalModelBytes()
+
2305{
+
2306 std::string code = R"CODE(
+
2307 // Fast Binary Encoding bytes final model
+
2308 public class FinalModelBytes : FinalModelReferenceType<MemoryStream>
+
2309 {
+
2310 public FinalModelBytes(Buffer buffer, long offset) : base(buffer, offset) {}
+
2311
+
2312 // Get the allocation size
+
2313 public override long FBEAllocationSize(MemoryStream value) { return 4 + value.Length; }
+
2314
+
2315 // Clone the final model
+
2316 public override FinalModelReferenceType<MemoryStream> Clone() { return new FinalModelBytes(_buffer, _offset); }
+
2317
+
2318 // Check if the bytes value is valid
+
2319 public override long Verify()
+
2320 {
+
2321 if ((_buffer.Offset + FBEOffset + 4) > _buffer.Size)
+
2322 return long.MaxValue;
+
2323
+
2324 uint fbeBytesSize = ReadUInt32(FBEOffset);
+
2325 if ((_buffer.Offset + FBEOffset + 4 + fbeBytesSize) > _buffer.Size)
+
2326 return long.MaxValue;
+
2327
+
2328 return 4 + fbeBytesSize;
+
2329 }
+
2330
+
2331 // Get the bytes value
+
2332 public override long Get(out MemoryStream value)
+
2333 {
+
2334 value = new MemoryStream();
+
2335
+
2336 Debug.Assert(((_buffer.Offset + FBEOffset + 4) <= _buffer.Size), "Model is broken!");
+
2337 if ((_buffer.Offset + FBEOffset + 4) > _buffer.Size)
+
2338 return 0;
+
2339
+
2340 uint fbeBytesSize = ReadUInt32(FBEOffset);
+
2341 Debug.Assert(((_buffer.Offset + FBEOffset + 4 + fbeBytesSize) <= _buffer.Size), "Model is broken!");
+
2342 if ((_buffer.Offset + FBEOffset + 4 + fbeBytesSize) > _buffer.Size)
+
2343 return 4;
+
2344
+
2345 var buffer = ReadBytes(FBEOffset + 4, fbeBytesSize);
+
2346 value.Write(buffer, 0, buffer.Length);
+
2347 return 4 + fbeBytesSize;
+
2348 }
+
2349
+
2350 // Set the bytes value
+
2351 public override long Set(MemoryStream value)
+
2352 {
+
2353 Debug.Assert((value != null), "Invalid bytes value!");
+
2354 if (value == null)
+
2355 throw new ArgumentNullException(nameof(value), "Invalid bytes value!");
+
2356
+
2357 Debug.Assert(((_buffer.Offset + FBEOffset + 4) <= _buffer.Size), "Model is broken!");
+
2358 if ((_buffer.Offset + FBEOffset + 4) > _buffer.Size)
+
2359 return 0;
+
2360
+
2361 uint fbeBytesSize = (uint)value.Length;
+
2362 Debug.Assert(((_buffer.Offset + FBEOffset + 4 + fbeBytesSize) <= _buffer.Size), "Model is broken!");
+
2363 if ((_buffer.Offset + FBEOffset + 4 + fbeBytesSize) > _buffer.Size)
+
2364 return 4;
+
2365
+
2366 Write(FBEOffset, fbeBytesSize);
+
2367 Write(FBEOffset + 4, value.GetBuffer(), 0, fbeBytesSize);
+
2368 return 4 + fbeBytesSize;
+
2369 }
+
2370 }
+
2371)CODE";
+
2372
+
2373 // Prepare code template
+
2374 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2375
+
2376 Write(code);
+
2377}
+
2378
+
2379void GeneratorCSharp::GenerateFBEFinalModelString()
+
2380{
+
2381 std::string code = R"CODE(
+
2382 // Fast Binary Encoding string final model
+
2383 public class FinalModelString : FinalModelReferenceType<string>
+
2384 {
+
2385 public FinalModelString(Buffer buffer, long offset) : base(buffer, offset) {}
+
2386
+
2387 // Get the allocation size
+
2388 public override long FBEAllocationSize(string value) { return 4 + Encoding.UTF8.GetMaxByteCount(value.Length); }
+
2389
+
2390 // Clone the final model
+
2391 public override FinalModelReferenceType<string> Clone() { return new FinalModelString(_buffer, _offset); }
+
2392
+
2393 // Check if the string value is valid
+
2394 public override long Verify()
+
2395 {
+
2396 if ((_buffer.Offset + FBEOffset + 4) > _buffer.Size)
+
2397 return long.MaxValue;
+
2398
+
2399 uint fbeStringSize = ReadUInt32(FBEOffset);
+
2400 if ((_buffer.Offset + FBEOffset + 4 + fbeStringSize) > _buffer.Size)
+
2401 return long.MaxValue;
+
2402
+
2403 return 4 + fbeStringSize;
+
2404 }
+
2405
+
2406 // Get the string value
+
2407 public override long Get(out string value)
+
2408 {
+
2409 Debug.Assert(((_buffer.Offset + FBEOffset + 4) <= _buffer.Size), "Model is broken!");
+
2410 if ((_buffer.Offset + FBEOffset + 4) > _buffer.Size)
+
2411 {
+
2412 value = "";
+
2413 return 0;
+
2414 }
+
2415
+
2416 uint fbeStringSize = ReadUInt32(FBEOffset);
+
2417 Debug.Assert(((_buffer.Offset + FBEOffset + 4 + fbeStringSize) <= _buffer.Size), "Model is broken!");
+
2418 if ((_buffer.Offset + FBEOffset + 4 + fbeStringSize) > _buffer.Size)
+
2419 {
+
2420 value = "";
+
2421 return 4;
+
2422 }
+
2423
+
2424 value = ReadString(FBEOffset + 4, fbeStringSize);
+
2425 return 4 + fbeStringSize;
+
2426 }
+
2427
+
2428 // Set the string value
+
2429 public override long Set(string value)
+
2430 {
+
2431 Debug.Assert((value != null), "Invalid string value!");
+
2432 if (value == null)
+
2433 throw new ArgumentNullException(nameof(value), "Invalid string value!");
+
2434
+
2435 Debug.Assert(((_buffer.Offset + FBEOffset + 4) <= _buffer.Size), "Model is broken!");
+
2436 if ((_buffer.Offset + FBEOffset + 4) > _buffer.Size)
+
2437 return 0;
+
2438
+
2439 uint fbeStringSize = (uint)Write(FBEOffset + 4, value);
+
2440 Debug.Assert(((_buffer.Offset + FBEOffset + 4 + fbeStringSize) <= _buffer.Size), "Model is broken!");
+
2441 if ((_buffer.Offset + FBEOffset + 4 + fbeStringSize) > _buffer.Size)
+
2442 return 4;
+
2443
+
2444 Write(FBEOffset, fbeStringSize);
+
2445 return 4 + fbeStringSize;
+
2446 }
+
2447 }
+
2448)CODE";
+
2449
+
2450 // Prepare code template
+
2451 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2452
+
2453 Write(code);
+
2454}
+
2455
+
2456void GeneratorCSharp::GenerateFBEFinalModelOptional(bool valueType)
+
2457{
+
2458 std::string code = R"CODE(
+
2459 // Fast Binary Encoding final model optional (_NAME_)
+
2460 public class FinalModelOptional_TYPE_<T, TModel> : FieldModelBase
+
2461 where T : _BASE_
+
2462 where TModel : FinalModel_TYPE_<T>
+
2463 {
+
2464 public FinalModelOptional_TYPE_(TModel model, Buffer buffer, long offset) : base(buffer, offset)
+
2465 {
+
2466 Value = model.Clone() as TModel;
+
2467 // Reset the optional model offset
+
2468 if (Value != null)
+
2469 Value.FBEOffset = 0;
+
2470 }
+
2471
+
2472 // Get the allocation size
+
2473 public long FBEAllocationSize(_ARGS_ optional) { return 1 + ((optional_HAS_VALUE_) ? Value.FBEAllocationSize(optional_VALUE_) : 0); }
+
2474
+
2475 // Clone the final model
+
2476 public FinalModelOptional_TYPE_<T, TModel> Clone() { return new FinalModelOptional_TYPE_<T, TModel>(Value, _buffer, _offset); }
+
2477
+
2479 public static implicit operator bool(FinalModelOptional_TYPE_<T, TModel> optional) { return !ReferenceEquals(optional, null) && optional.HasValue; }
+
2480
+
2481 // Checks if the object contains a value
+
2482 public bool HasValue
+
2483 {
+
2484 get
+
2485 {
+
2486 if ((_buffer.Offset + FBEOffset + 1) > _buffer.Size)
+
2487 return false;
+
2488
+
2489 byte fbeHasValue = ReadUInt8(FBEOffset);
+
2490 return (fbeHasValue != 0);
+
2491 }
+
2492 }
+
2493
+
2494 // Base final model value
+
2495 public TModel Value { get; }
+
2496
+
2497 // Check if the optional value is valid
+
2498 public virtual long Verify()
+
2499 {
+
2500 if ((_buffer.Offset + FBEOffset + 1) > _buffer.Size)
+
2501 return long.MaxValue;
+
2502
+
2503 byte fbeHasValue = ReadUInt8(FBEOffset);
+
2504 if (fbeHasValue == 0)
+
2505 return 1;
+
2506
+
2507 _buffer.Shift(FBEOffset + 1);
+
2508 long fbeResult = Value.Verify();
+
2509 _buffer.Unshift(FBEOffset + 1);
+
2510 return 1 + fbeResult;
+
2511 }
+
2512
+
2513 // Get the optional value
+
2514 public long Get(out _ARGS_ optional)
+
2515 {
+
2516 optional = null;
+
2517
+
2518 Debug.Assert(((_buffer.Offset + FBEOffset + 1) <= _buffer.Size), "Model is broken!");
+
2519 if ((_buffer.Offset + FBEOffset + 1) > _buffer.Size)
+
2520 return 0;
+
2521
+
2522 if (!HasValue)
+
2523 return 1;
+
2524
+
2525 _buffer.Shift(FBEOffset + 1);
+
2526 long size = Value.Get(out var temp);
+
2527 optional = temp;
+
2528 _buffer.Unshift(FBEOffset + 1);
+
2529 return 1 + size;
+
2530 }
+
2531
+
2532 // Set the optional value
+
2533 public long Set(_ARGS_ optional)
+
2534 {
+
2535 Debug.Assert(((_buffer.Offset + FBEOffset + 1) <= _buffer.Size), "Model is broken!");
+
2536 if ((_buffer.Offset + FBEOffset + 1) > _buffer.Size)
+
2537 return 0;
+
2538
+
2539 byte fbeHasValue = (byte)((optional_HAS_VALUE_) ? 1 : 0);
+
2540 Write(FBEOffset, fbeHasValue);
+
2541 if (fbeHasValue == 0)
+
2542 return 1;
+
2543
+
2544 _buffer.Shift(FBEOffset + 1);
+
2545 long size = 0;
+
2546 if (optional_HAS_VALUE_)
+
2547 size = Value.Set(optional_VALUE_);
+
2548 _buffer.Unshift(FBEOffset + 1);
+
2549 return 1 + size;
+
2550 }
+
2551 }
+
2552)CODE";
+
2553
+
2554 // Prepare code template
+
2555 code = std::regex_replace(code, std::regex("_NAME_"), (valueType ? "value type" : "reference type"));
+
2556 code = std::regex_replace(code, std::regex("_TYPE_"), (valueType ? "ValueType" : "ReferenceType"));
+
2557 code = std::regex_replace(code, std::regex("_BASE_"), (valueType ? "struct" : "class"));
+
2558 code = std::regex_replace(code, std::regex("_ARGS_"), (valueType ? "T?" : "T"));
+
2559 code = std::regex_replace(code, std::regex("_HAS_VALUE_"), (valueType ? ".HasValue" : " != null"));
+
2560 code = std::regex_replace(code, std::regex("_VALUE_"), (valueType ? ".Value" : ""));
+
2561 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2562
+
2563 Write(code);
+
2564}
+
2565
+
2566void GeneratorCSharp::GenerateFBEFinalModelArray(bool valueType, bool optional)
+
2567{
+
2568 std::string code = R"CODE(
+
2569 // Fast Binary Encoding final model array (_NAME_)
+
2570 public class FinalModelArray_TYPE_<T, TModel> : FieldModelBase
+
2571 where T : _BASE_
+
2572 where TModel : FinalModel_MODEL_REF_<T>
+
2573 {
+
2574 private readonly _MODEL_DECL_ _model;
+
2575 private readonly long _size;
+
2576
+
2577 public FinalModelArray_TYPE_(TModel model, Buffer buffer, long offset, long size) : base(buffer, offset)
+
2578 {
+
2579 _model = _MODEL_CLONE_;
+
2580 _size = size;
+
2581 }
+
2582
+
2583 // Get the allocation size
+
2584 public long FBEAllocationSize(_ARGS_[] values)
+
2585 {
+
2586 long size = 0;
+
2587 for (long i = 0; (i < values.Length) && (i < _size); i++)
+
2588 size += _model.FBEAllocationSize(values[i]);
+
2589 return size;
+
2590 }
+
2591 public long FBEAllocationSize(List<_ARGS_> values)
+
2592 {
+
2593 long size = 0;
+
2594 for (long i = 0; (i < values.Count) && (i < _size); i++)
+
2595 size += _model.FBEAllocationSize(values[(int)i]);
+
2596 return size;
+
2597 }
+
2598
+
2599 // Clone the final model
+
2600 public FinalModelArray_TYPE_<T, TModel> Clone() { return new FinalModelArray_TYPE_<T, TModel>(_model_MODEL_VALUE_, _buffer, _offset, _size); }
+
2601
+
2602 // Check if the array is valid
+
2603 public virtual long Verify()
+
2604 {
+
2605 if ((_buffer.Offset + FBEOffset) > _buffer.Size)
+
2606 return long.MaxValue;
+
2607
+
2608 long size = 0;
+
2609 _model.FBEOffset = FBEOffset;
+
2610 for (long i = _size; i-- > 0;)
+
2611 {
+
2612 long offset = _model.Verify();
+
2613 if (offset == long.MaxValue)
+
2614 return long.MaxValue;
+
2615 _model.FBEShift(offset);
+
2616 size += offset;
+
2617 }
+
2618 return size;
+
2619 }
+
2620
+
2621 // Get the array
+
2622 public long Get(out _ARGS_[] values)
+
2623 {
+
2624 values = new _ARGS_[_size];
+
2625
+
2626 Debug.Assert(((_buffer.Offset + FBEOffset) <= _buffer.Size), "Model is broken!");
+
2627 if ((_buffer.Offset + FBEOffset) > _buffer.Size)
+
2628 return 0;
+
2629
+
2630 long size = 0;
+
2631 _model.FBEOffset = FBEOffset;
+
2632 for (long i = 0; i < _size; i++)
+
2633 {
+
2634 long offset = _model.Get(out values[i]);
+
2635 _model.FBEShift(offset);
+
2636 size += offset;
+
2637 }
+
2638 return size;
+
2639 }
+
2640
+
2641 // Get the array as List
+
2642 public long Get(out List<_ARGS_> values)
+
2643 {
+
2644 values = new List<_ARGS_>((int)_size);
+
2645
+
2646 Debug.Assert(((_buffer.Offset + FBEOffset) <= _buffer.Size), "Model is broken!");
+
2647 if ((_buffer.Offset + FBEOffset) > _buffer.Size)
+
2648 return 0;
+
2649
+
2650 long size = 0;
+
2651 _model.FBEOffset = FBEOffset;
+
2652 for (long i = _size; i-- > 0;)
+
2653 {
+
2654 long offset = _model.Get(out var value);
+
2655 values.Add(value);
+
2656 _model.FBEShift(offset);
+
2657 size += offset;
+
2658 }
+
2659 return size;
+
2660 }
+
2661
+
2662 // Set the array
+
2663 public long Set(_ARGS_[] values)
+
2664 {
+
2665 Debug.Assert((values != null), "Invalid values parameter!");
+
2666 if (values == null)
+
2667 throw new ArgumentNullException(nameof(values), "Invalid values parameter!");
+
2668
+
2669 Debug.Assert(((_buffer.Offset + FBEOffset) <= _buffer.Size), "Model is broken!");
+
2670 if ((_buffer.Offset + FBEOffset) > _buffer.Size)
+
2671 return 0;
+
2672
+
2673 long size = 0;
+
2674 _model.FBEOffset = FBEOffset;
+
2675 for (long i = 0; (i < values.Length) && (i < _size); i++)
+
2676 {
+
2677 long offset = _model.Set(values[i]);
+
2678 _model.FBEShift(offset);
+
2679 size += offset;
+
2680 }
+
2681 return size;
+
2682 }
+
2683
+
2684 // Set the array as List
+
2685 public long Set(List<_ARGS_> values)
+
2686 {
+
2687 Debug.Assert((values != null), "Invalid values parameter!");
+
2688 if (values == null)
+
2689 throw new ArgumentNullException(nameof(values), "Invalid values parameter!");
+
2690
+
2691 Debug.Assert(((_buffer.Offset + FBEOffset) <= _buffer.Size), "Model is broken!");
+
2692 if ((_buffer.Offset + FBEOffset) > _buffer.Size)
+
2693 return 0;
+
2694
+
2695 long size = 0;
+
2696 _model.FBEOffset = FBEOffset;
+
2697 for (long i = 0; (i < values.Count) && (i < _size); i++)
+
2698 {
+
2699 long offset = _model.Set(values[(int)i]);
+
2700 _model.FBEShift(offset);
+
2701 size += offset;
+
2702 }
+
2703 return size;
+
2704 }
+
2705 }
+
2706)CODE";
+
2707
+
2708 // Prepare code template
+
2709 code = std::regex_replace(code, std::regex("_NAME_"), (optional ? (valueType ? "optional value type" : "optional reference type") : (valueType ? "value type" : "reference type")));
+
2710 code = std::regex_replace(code, std::regex("_TYPE_"), (optional ? (valueType ? "OptionalValueType" : "OptionalReferenceType") : (valueType ? "ValueType" : "ReferenceType")));
+
2711 code = std::regex_replace(code, std::regex("_BASE_"), (valueType ? "struct" : "class"));
+
2712 code = std::regex_replace(code, std::regex("_ARGS_"), ((optional && valueType) ? "T?" : "T"));
+
2713 code = std::regex_replace(code, std::regex("_MODEL_CLONE_"), (optional ? "new FinalModelOptional_MODEL_REF_<T, TModel>(model, buffer, offset)" : "model.Clone() as TModel"));
+
2714 code = std::regex_replace(code, std::regex("_MODEL_DECL_"), (optional ? "FinalModelOptional_MODEL_REF_<T, TModel>" : "TModel"));
+
2715 code = std::regex_replace(code, std::regex("_MODEL_REF_"), (valueType ? "ValueType" : "ReferenceType"));
+
2716 code = std::regex_replace(code, std::regex("_MODEL_VALUE_"), (optional ? ".Value" : ""));
+
2717 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2718
+
2719 Write(code);
+
2720}
+
2721
+
2722void GeneratorCSharp::GenerateFBEFinalModelVector(bool valueType, bool optional)
+
2723{
+
2724 std::string code = R"CODE(
+
2725 // Fast Binary Encoding final model vector (_NAME_)
+
2726 public class FinalModelVector_TYPE_<T, TModel> : FieldModelBase
+
2727 where T : _BASE_
+
2728 where TModel : FinalModel_MODEL_REF_<T>
+
2729 {
+
2730 private readonly _MODEL_DECL_ _model;
+
2731
+
2732 public FinalModelVector_TYPE_(TModel model, Buffer buffer, long offset) : base(buffer, offset)
+
2733 {
+
2734 _model = _MODEL_CLONE_;
+
2735 }
+
2736
+
2737 // Get the allocation size
+
2738 public long FBEAllocationSize(List<_ARGS_> values)
+
2739 {
+
2740 long size = 4;
+
2741 foreach (var value in values)
+
2742 size += _model.FBEAllocationSize(value);
+
2743 return size;
+
2744 }
+
2745 public long FBEAllocationSize(LinkedList<_ARGS_> values)
+
2746 {
+
2747 long size = 4;
+
2748 foreach (var value in values)
+
2749 size += _model.FBEAllocationSize(value);
+
2750 return size;
+
2751 }
+
2752 public long FBEAllocationSize(HashSet<_ARGS_> values)
+
2753 {
+
2754 long size = 4;
+
2755 foreach (var value in values)
+
2756 size += _model.FBEAllocationSize(value);
+
2757 return size;
+
2758 }
+
2759
+
2760 // Clone the final model
+
2761 public FinalModelVector_TYPE_<T, TModel> Clone() { return new FinalModelVector_TYPE_<T, TModel>(_model_MODEL_VALUE_, _buffer, _offset); }
+
2762
+
2763 // Check if the vector is valid
+
2764 public virtual long Verify()
+
2765 {
+
2766 if ((_buffer.Offset + FBEOffset + 4) > _buffer.Size)
+
2767 return long.MaxValue;
+
2768
+
2769 uint fbeVectorSize = ReadUInt32(FBEOffset);
+
2770
+
2771 long size = 4;
+
2772 _model.FBEOffset = FBEOffset + 4;
+
2773 for (uint i = fbeVectorSize; i-- > 0;)
+
2774 {
+
2775 long offset = _model.Verify();
+
2776 if (offset == long.MaxValue)
+
2777 return long.MaxValue;
+
2778 _model.FBEShift(offset);
+
2779 size += offset;
+
2780 }
+
2781 return size;
+
2782 }
+
2783
+
2784 // Get the vector as List
+
2785 public long Get(out List<_ARGS_> values)
+
2786 {
+
2787 Debug.Assert(((_buffer.Offset + FBEOffset + 4) <= _buffer.Size), "Model is broken!");
+
2788 if ((_buffer.Offset + FBEOffset + 4) > _buffer.Size)
+
2789 {
+
2790 values = new List<_ARGS_>();
+
2791 return 0;
+
2792 }
+
2793
+
2794 long fbeVectorSize = ReadUInt32(FBEOffset);
+
2795 if (fbeVectorSize == 0)
+
2796 {
+
2797 values = new List<_ARGS_>();
+
2798 return 4;
+
2799 }
+
2800
+
2801 values = new List<_ARGS_>((int)fbeVectorSize);
+
2802
+
2803 long size = 4;
+
2804 _model.FBEOffset = FBEOffset + 4;
+
2805 for (long i = fbeVectorSize; i-- > 0;)
+
2806 {
+
2807 long offset = _model.Get(out var value);
+
2808 values.Add(value);
+
2809 _model.FBEShift(offset);
+
2810 size += offset;
+
2811 }
+
2812 return size;
+
2813 }
+
2814
+
2815 // Get the vector as LinkedList
+
2816 public long Get(out LinkedList<_ARGS_> values)
+
2817 {
+
2818 values = new LinkedList<_ARGS_>();
+
2819
+
2820 Debug.Assert(((_buffer.Offset + FBEOffset + 4) <= _buffer.Size), "Model is broken!");
+
2821 if ((_buffer.Offset + FBEOffset + 4) > _buffer.Size)
+
2822 return 0;
+
2823
+
2824 long fbeVectorSize = ReadUInt32(FBEOffset);
+
2825 if (fbeVectorSize == 0)
+
2826 return 4;
+
2827
+
2828 long size = 4;
+
2829 _model.FBEOffset = FBEOffset + 4;
+
2830 for (long i = fbeVectorSize; i-- > 0;)
+
2831 {
+
2832 long offset = _model.Get(out var value);
+
2833 values.AddLast(value);
+
2834 _model.FBEShift(offset);
+
2835 size += offset;
+
2836 }
+
2837 return size;
+
2838 }
+
2839
+
2840 // Get the vector as HashSet
+
2841 public long Get(out HashSet<_ARGS_> values)
+
2842 {
+
2843 Debug.Assert(((_buffer.Offset + FBEOffset + 4) <= _buffer.Size), "Model is broken!");
+
2844 if ((_buffer.Offset + FBEOffset + 4) > _buffer.Size)
+
2845 {
+
2846 values = new HashSet<_ARGS_>();
+
2847 return 0;
+
2848 }
+
2849
+
2850 long fbeVectorSize = ReadUInt32(FBEOffset);
+
2851 if (fbeVectorSize == 0)
+
2852 {
+
2853 values = new HashSet<_ARGS_>();
+
2854 return 4;
+
2855 }
+
2856
+
2857 values = new HashSet<_ARGS_>((int)fbeVectorSize);
+
2858
+
2859 long size = 4;
+
2860 _model.FBEOffset = FBEOffset + 4;
+
2861 for (long i = fbeVectorSize; i-- > 0;)
+
2862 {
+
2863 long offset = _model.Get(out var value);
+
2864 values.Add(value);
+
2865 _model.FBEShift(offset);
+
2866 size += offset;
+
2867 }
+
2868 return size;
+
2869 }
+
2870
+
2871 // Set the vector as List
+
2872 public long Set(List<_ARGS_> values)
+
2873 {
+
2874 Debug.Assert((values != null), "Invalid values parameter!");
+
2875 if (values == null)
+
2876 throw new ArgumentNullException(nameof(values), "Invalid values parameter!");
+
2877
+
2878 Debug.Assert(((_buffer.Offset + FBEOffset + 4) <= _buffer.Size), "Model is broken!");
+
2879 if ((_buffer.Offset + FBEOffset + 4) > _buffer.Size)
+
2880 return 0;
+
2881
+
2882 Write(FBEOffset, (uint)values.Count);
+
2883
+
2884 long size = 4;
+
2885 _model.FBEOffset = FBEOffset + 4;
+
2886 foreach (var value in values)
+
2887 {
+
2888 long offset = _model.Set(value);
+
2889 _model.FBEShift(offset);
+
2890 size += offset;
+
2891 }
+
2892 return size;
+
2893 }
+
2894
+
2895 // Set the vector as LinkedList
+
2896 public long Set(LinkedList<_ARGS_> values)
+
2897 {
+
2898 Debug.Assert((values != null), "Invalid values parameter!");
+
2899 if (values == null)
+
2900 throw new ArgumentNullException(nameof(values), "Invalid values parameter!");
+
2901
+
2902 Debug.Assert(((_buffer.Offset + FBEOffset + 4) <= _buffer.Size), "Model is broken!");
+
2903 if ((_buffer.Offset + FBEOffset + 4) > _buffer.Size)
+
2904 return 0;
+
2905
+
2906 Write(FBEOffset, (uint)values.Count);
+
2907
+
2908 long size = 4;
+
2909 _model.FBEOffset = FBEOffset + 4;
+
2910 foreach (var value in values)
+
2911 {
+
2912 long offset = _model.Set(value);
+
2913 _model.FBEShift(offset);
+
2914 size += offset;
+
2915 }
+
2916 return size;
+
2917 }
+
2918
+
2919 // Set the vector as HashSet
+
2920 public long Set(HashSet<_ARGS_> values)
+
2921 {
+
2922 Debug.Assert((values != null), "Invalid values parameter!");
+
2923 if (values == null)
+
2924 throw new ArgumentNullException(nameof(values), "Invalid values parameter!");
+
2925
+
2926 Debug.Assert(((_buffer.Offset + FBEOffset + FBESize) <= _buffer.Size), "Model is broken!");
+
2927 if ((_buffer.Offset + FBEOffset + FBESize) > _buffer.Size)
+
2928 return 0;
+
2929
+
2930 Write(FBEOffset, (uint)values.Count);
+
2931
+
2932 long size = 4;
+
2933 _model.FBEOffset = FBEOffset + 4;
+
2934 foreach (var value in values)
+
2935 {
+
2936 long offset = _model.Set(value);
+
2937 _model.FBEShift(offset);
+
2938 size += offset;
+
2939 }
+
2940 return size;
+
2941 }
+
2942 }
+
2943)CODE";
+
2944
+
2945 // Prepare code template
+
2946 code = std::regex_replace(code, std::regex("_NAME_"), (optional ? (valueType ? "optional value type" : "optional reference type") : (valueType ? "value type" : "reference type")));
+
2947 code = std::regex_replace(code, std::regex("_TYPE_"), (optional ? (valueType ? "OptionalValueType" : "OptionalReferenceType") : (valueType ? "ValueType" : "ReferenceType")));
+
2948 code = std::regex_replace(code, std::regex("_BASE_"), (valueType ? "struct" : "class"));
+
2949 code = std::regex_replace(code, std::regex("_ARGS_"), ((optional && valueType) ? "T?" : "T"));
+
2950 code = std::regex_replace(code, std::regex("_MODEL_CLONE_"), (optional ? "new FinalModelOptional_MODEL_REF_<T, TModel>(model, buffer, offset)" : "model.Clone() as TModel"));
+
2951 code = std::regex_replace(code, std::regex("_MODEL_DECL_"), (optional ? "FinalModelOptional_MODEL_REF_<T, TModel>" : "TModel"));
+
2952 code = std::regex_replace(code, std::regex("_MODEL_REF_"), (valueType ? "ValueType" : "ReferenceType"));
+
2953 code = std::regex_replace(code, std::regex("_MODEL_VALUE_"), (optional ? ".Value" : ""));
+
2954 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2955
+
2956 Write(code);
+
2957}
+
2958
+
2959void GeneratorCSharp::GenerateFBEFinalModelMap(bool valueTypeKey, bool valueTypeValue, bool optional)
+
2960{
+
2961 std::string code = R"CODE(
+
2962 // Fast Binary Encoding final model map (_NAME_KEY_, _NAME_VALUE_)
+
2963 public class FinalModelMap_TYPE_KEY__TYPE_VALUE_<TKey, TKeyModel, TValue, TValueModel> : FieldModelBase
+
2964 where TKey : _BASE_KEY_
+
2965 where TKeyModel : FinalModel_MODEL_KEY_REF_<TKey>
+
2966 where TValue : _BASE_VALUE_
+
2967 where TValueModel : FinalModel_MODEL_VALUE_REF_<TValue>
+
2968 {
+
2969 private readonly _MODEL_KEY_DECL_ _modelKey;
+
2970 private readonly _MODEL_VALUE_DECL_ _modelValue;
+
2971
+
2972 public FinalModelMap_TYPE_KEY__TYPE_VALUE_(TKeyModel modelKey, TValueModel modelValue, Buffer buffer, long offset) : base(buffer, offset)
+
2973 {
+
2974 _modelKey = _MODEL_KEY_CLONE_;
+
2975 _modelValue = _MODEL_VALUE_CLONE_;
+
2976 }
+
2977
+
2978 // Get the allocation size
+
2979 public long FBEAllocationSize(Dictionary<_ARGS_KEY_, _ARGS_VALUE_> values)
+
2980 {
+
2981 long size = 4;
+
2982 foreach (var value in values)
+
2983 {
+
2984 size += _modelKey.FBEAllocationSize(value.Key);
+
2985 size += _modelValue.FBEAllocationSize(value.Value);
+
2986 }
+
2987 return size;
+
2988 }
+
2989 public long FBEAllocationSize(SortedDictionary<_ARGS_KEY_, _ARGS_VALUE_> values)
+
2990 {
+
2991 long size = 4;
+
2992 foreach (var value in values)
+
2993 {
+
2994 size += _modelKey.FBEAllocationSize(value.Key);
+
2995 size += _modelValue.FBEAllocationSize(value.Value);
+
2996 }
+
2997 return size;
+
2998 }
+
2999
+
3000 // Clone the final model
+
3001 public FinalModelMap_TYPE_KEY__TYPE_VALUE_<TKey, TKeyModel, TValue, TValueModel> Clone() { return new FinalModelMap_TYPE_KEY__TYPE_VALUE_<TKey, TKeyModel, TValue, TValueModel>(_modelKey_MODEL_KEY_VALUE_, _modelValue_MODEL_VALUE_VALUE_, _buffer, _offset); }
+
3002
+
3003 // Check if the map is valid
+
3004 public virtual long Verify()
+
3005 {
+
3006 if ((_buffer.Offset + FBEOffset + 4) > _buffer.Size)
+
3007 return long.MaxValue;
+
3008
+
3009 uint fbeMapSize = ReadUInt32(FBEOffset);
+
3010
+
3011 long size = 4;
+
3012 _modelKey.FBEOffset = FBEOffset + 4;
+
3013 _modelValue.FBEOffset = FBEOffset + 4;
+
3014 for (uint i = fbeMapSize; i-- > 0;)
+
3015 {
+
3016 long offsetKey = _modelKey.Verify();
+
3017 if (offsetKey == long.MaxValue)
+
3018 return long.MaxValue;
+
3019 _modelKey.FBEShift(offsetKey);
+
3020 _modelValue.FBEShift(offsetKey);
+
3021 size += offsetKey;
+
3022 long offsetValue = _modelValue.Verify();
+
3023 if (offsetValue == long.MaxValue)
+
3024 return long.MaxValue;
+
3025 _modelKey.FBEShift(offsetValue);
+
3026 _modelValue.FBEShift(offsetValue);
+
3027 size += offsetValue;
+
3028 }
+
3029 return size;
+
3030 }
+
3031
+
3032 // Get the map as Dictionary
+
3033 public long Get(out Dictionary<_ARGS_KEY_, _ARGS_VALUE_> values)
+
3034 {
+
3035 Debug.Assert(((_buffer.Offset + FBEOffset + 4) <= _buffer.Size), "Model is broken!");
+
3036 if ((_buffer.Offset + FBEOffset + 4) > _buffer.Size)
+
3037 {
+
3038 values = new Dictionary<_ARGS_KEY_, _ARGS_VALUE_>();
+
3039 return 0;
+
3040 }
+
3041
+
3042 long fbeMapSize = ReadUInt32(FBEOffset);
+
3043 if (fbeMapSize == 0)
+
3044 {
+
3045 values = new Dictionary<_ARGS_KEY_, _ARGS_VALUE_>();
+
3046 return 4;
+
3047 }
+
3048
+
3049 values = new Dictionary<_ARGS_KEY_, _ARGS_VALUE_>((int)fbeMapSize);
+
3050
+
3051 long size = 4;
+
3052 _modelKey.FBEOffset = FBEOffset + 4;
+
3053 _modelValue.FBEOffset = FBEOffset + 4;
+
3054 for (long i = fbeMapSize; i-- > 0;)
+
3055 {
+
3056 long offsetKey = _modelKey.Get(out var key);
+
3057 _modelKey.FBEShift(offsetKey);
+
3058 _modelValue.FBEShift(offsetKey);
+
3059 long offsetValue = _modelValue.Get(out var value);
+
3060 _modelKey.FBEShift(offsetValue);
+
3061 _modelValue.FBEShift(offsetValue);
+
3062 values.Add(key, value);
+
3063 size += offsetKey + offsetValue;
+
3064 }
+
3065 return size;
+
3066 }
+
3067
+
3068 // Get the map as SortedDictionary
+
3069 public long Get(out SortedDictionary<_ARGS_KEY_, _ARGS_VALUE_> values)
+
3070 {
+
3071 values = new SortedDictionary<_ARGS_KEY_, _ARGS_VALUE_>();
+
3072
+
3073 Debug.Assert(((_buffer.Offset + FBEOffset + 4) <= _buffer.Size), "Model is broken!");
+
3074 if ((_buffer.Offset + FBEOffset + 4) > _buffer.Size)
+
3075 return 0;
+
3076
+
3077 long fbeMapSize = ReadUInt32(FBEOffset);
+
3078 if (fbeMapSize == 0)
+
3079 return 4;
+
3080
+
3081 long size = 4;
+
3082 _modelKey.FBEOffset = FBEOffset + 4;
+
3083 _modelValue.FBEOffset = FBEOffset + 4;
+
3084 for (long i = fbeMapSize; i-- > 0;)
+
3085 {
+
3086 long offsetKey = _modelKey.Get(out var key);
+
3087 _modelKey.FBEShift(offsetKey);
+
3088 _modelValue.FBEShift(offsetKey);
+
3089 long offsetValue = _modelValue.Get(out var value);
+
3090 _modelKey.FBEShift(offsetValue);
+
3091 _modelValue.FBEShift(offsetValue);
+
3092 values.Add(key, value);
+
3093 size += offsetKey + offsetValue;
+
3094 }
+
3095 return size;
+
3096 }
+
3097
+
3098 // Set the map as Dictionary
+
3099 public long Set(Dictionary<_ARGS_KEY_, _ARGS_VALUE_> values)
+
3100 {
+
3101 Debug.Assert((values != null), "Invalid values parameter!");
+
3102 if (values == null)
+
3103 throw new ArgumentNullException(nameof(values), "Invalid values parameter!");
+
3104
+
3105 Debug.Assert(((_buffer.Offset + FBEOffset + 4) <= _buffer.Size), "Model is broken!");
+
3106 if ((_buffer.Offset + FBEOffset + 4) > _buffer.Size)
+
3107 return 0;
+
3108
+
3109 Write(FBEOffset, (uint)values.Count);
+
3110
+
3111 long size = 4;
+
3112 _modelKey.FBEOffset = FBEOffset + 4;
+
3113 _modelValue.FBEOffset = FBEOffset + 4;
+
3114 foreach (var value in values)
+
3115 {
+
3116 long offsetKey = _modelKey.Set(value.Key);
+
3117 _modelKey.FBEShift(offsetKey);
+
3118 _modelValue.FBEShift(offsetKey);
+
3119 long offsetValue = _modelValue.Set(value.Value);
+
3120 _modelKey.FBEShift(offsetValue);
+
3121 _modelValue.FBEShift(offsetValue);
+
3122 size += offsetKey + offsetValue;
+
3123 }
+
3124 return size;
+
3125 }
+
3126
+
3127 // Set the map as SortedDictionary
+
3128 public long Set(SortedDictionary<_ARGS_KEY_, _ARGS_VALUE_> values)
+
3129 {
+
3130 Debug.Assert((values != null), "Invalid values parameter!");
+
3131 if (values == null)
+
3132 throw new ArgumentNullException(nameof(values), "Invalid values parameter!");
+
3133
+
3134 Debug.Assert(((_buffer.Offset + FBEOffset + 4) <= _buffer.Size), "Model is broken!");
+
3135 if ((_buffer.Offset + FBEOffset + 4) > _buffer.Size)
+
3136 return 0;
+
3137
+
3138 Write(FBEOffset, (uint)values.Count);
+
3139
+
3140 long size = 4;
+
3141 _modelKey.FBEOffset = FBEOffset + 4;
+
3142 _modelValue.FBEOffset = FBEOffset + 4;
+
3143 foreach (var value in values)
+
3144 {
+
3145 long offsetKey = _modelKey.Set(value.Key);
+
3146 _modelKey.FBEShift(offsetKey);
+
3147 _modelValue.FBEShift(offsetKey);
+
3148 long offsetValue = _modelValue.Set(value.Value);
+
3149 _modelKey.FBEShift(offsetValue);
+
3150 _modelValue.FBEShift(offsetValue);
+
3151 size += offsetKey + offsetValue;
+
3152 }
+
3153 return size;
+
3154 }
+
3155 }
+
3156)CODE";
+
3157
+
3158 // Prepare code template
+
3159 code = std::regex_replace(code, std::regex("_NAME_KEY_"), (valueTypeKey ? "value type key" : "reference type key"));
+
3160 code = std::regex_replace(code, std::regex("_NAME_VALUE_"), (optional ? (valueTypeValue ? "optional value type value" : "optional reference type value") : (valueTypeValue ? "value type value" : "reference type value")));
+
3161 code = std::regex_replace(code, std::regex("_TYPE_KEY_"), (valueTypeKey ? "ValueTypeKey" : "ReferenceTypeKey"));
+
3162 code = std::regex_replace(code, std::regex("_TYPE_VALUE_"), (optional ? (valueTypeValue ? "OptionalValueTypeValue" : "OptionalReferenceTypeValue") : (valueTypeValue ? "ValueTypeValue" : "ReferenceTypeValue")));
+
3163 code = std::regex_replace(code, std::regex("_BASE_KEY_"), (valueTypeKey ? "struct" : "class"));
+
3164 code = std::regex_replace(code, std::regex("_BASE_VALUE_"), (valueTypeValue ? "struct" : "class"));
+
3165 code = std::regex_replace(code, std::regex("_ARGS_KEY_"), "TKey");
+
3166 code = std::regex_replace(code, std::regex("_ARGS_VALUE_"), ((optional && valueTypeValue) ? "TValue?" : "TValue"));
+
3167 code = std::regex_replace(code, std::regex("_MODEL_KEY_CLONE_"), "modelKey.Clone() as TKeyModel");
+
3168 code = std::regex_replace(code, std::regex("_MODEL_KEY_DECL_"), "TKeyModel");
+
3169 code = std::regex_replace(code, std::regex("_MODEL_KEY_REF_"), (valueTypeKey ? "ValueType" : "ReferenceType"));
+
3170 code = std::regex_replace(code, std::regex("_MODEL_KEY_VALUE_"), "");
+
3171 code = std::regex_replace(code, std::regex("_MODEL_VALUE_CLONE_"), (optional ? "new FinalModelOptional_MODEL_VALUE_REF_<TValue, TValueModel>(modelValue, buffer, offset)" : "modelValue.Clone() as TValueModel"));
+
3172 code = std::regex_replace(code, std::regex("_MODEL_VALUE_DECL_"), (optional ? "FinalModelOptional_MODEL_VALUE_REF_<TValue, TValueModel>" : "TValueModel"));
+
3173 code = std::regex_replace(code, std::regex("_MODEL_VALUE_REF_"), (valueTypeValue ? "ValueType" : "ReferenceType"));
+
3174 code = std::regex_replace(code, std::regex("_MODEL_VALUE_VALUE_"), (optional ? ".Value" : ""));
+
3175 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
3176
+
3177 Write(code);
+
3178}
+
3179
+
3180void GeneratorCSharp::GenerateFBESender()
+
3181{
+
3182 std::string code = R"CODE(
+
3183 // Fast Binary Encoding base sender listener interface
+
3184 public interface ISenderListener
+
3185 {
+
3186 // Send message handler
+
3187 long OnSend(byte[] buffer, long offset, long size) { return size; }
+
3188 // Send log message handler
+
3189 void OnSendLog(string message) {}
+
3190 }
+
3191
+
3192 // Fast Binary Encoding base sender
+
3193 public abstract class Sender : ISenderListener
+
3194 {
+
3195 // Bytes buffer
+
3196 public Buffer Buffer { get; }
+
3197 // Logging flag
+
3198 public bool Logging { get; set; }
+
3199 // Final protocol flag
+
3200 public bool Final { get; }
+
3201
+
3202 protected Sender(bool final) { Buffer = new Buffer(); Final = final; }
+
3203 protected Sender(Buffer buffer, bool final) { Buffer = buffer; Final = final; }
+
3204
+
3205 // Reset the sender buffer
+
3206 public void Reset() { Buffer.Reset(); }
+
3207
+
3208 // Send serialized buffer.
+
3209 // Direct call of the method requires knowledge about internals of FBE models serialization.
+
3210 // Use it with care!
+
3211 public long SendSerialized(ISenderListener listener, long serialized)
+
3212 {
+
3213 Debug.Assert((serialized > 0), "Invalid size of the serialized buffer!");
+
3214 if (serialized == 0)
+
3215 return 0;
+
3216
+
3217 // Shift the send buffer
+
3218 Buffer.Shift(serialized);
+
3219
+
3220 // Send the value
+
3221 long sent = listener.OnSend(Buffer.Data, 0, Buffer.Size);
+
3222 Buffer.Remove(0, sent);
+
3223 return sent;
+
3224 }
+
3225 }
+
3226)CODE";
+
3227
+
3228 // Prepare code template
+
3229 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
3230
+
3231 Write(code);
+
3232}
+
3233
+
3234void GeneratorCSharp::GenerateFBEReceiver()
+
3235{
+
3236 std::string code = R"CODE(
+
3237 // Fast Binary Encoding base receiver listener interface
+
3238 public interface IReceiverListener
+
3239 {
+
3240 // Receive log message handler
+
3241 void OnReceiveLog(string message) {}
+
3242 }
+
3243
+
3244 // Fast Binary Encoding base receiver
+
3245 public abstract class Receiver : IReceiverListener
+
3246 {
+
3247 // Bytes buffer
+
3248 public Buffer Buffer { get; private set; }
+
3249 // Logging flag
+
3250 public bool Logging { get; set; }
+
3251 // Final protocol flag
+
3252 public bool Final { get; }
+
3253
+
3254 protected Receiver(bool final) { Buffer = new Buffer(); Final = final; }
+
3255 protected Receiver(Buffer buffer, bool final) { Buffer = buffer; Final = final; }
+
3256
+
3257 // Reset the receiver buffer
+
3258 public void Reset() { Buffer.Reset(); }
+
3259
+
3260 // Receive data
+
3261 public void Receive(Buffer buffer) { Receive(buffer.Data, 0, buffer.Size); }
+
3262 public void Receive(byte[] buffer) { Receive(buffer, 0, buffer.Length); }
+
3263 public void Receive(byte[] buffer, long offset, long size)
+
3264 {
+
3265 Debug.Assert((buffer != null), "Invalid buffer!");
+
3266 if (buffer == null)
+
3267 throw new ArgumentException("Invalid buffer!", nameof(buffer));
+
3268 Debug.Assert(((offset + size) <= buffer.Length), "Invalid offset & size!");
+
3269 if ((offset + size) > buffer.Length)
+
3270 throw new ArgumentException("Invalid offset & size!", nameof(offset));
+
3271
+
3272 if (size == 0)
+
3273 return;
+
3274
+
3275 // Storage buffer
+
3276 long offset0 = Buffer.Offset;
+
3277 long offset1 = Buffer.Size;
+
3278 long size1 = Buffer.Size;
+
3279
+
3280 // Receive buffer
+
3281 long offset2 = 0;
+
3282 long size2 = size;
+
3283
+
3284 // While receive buffer is available to handle...
+
3285 while (offset2 < size2)
+
3286 {
+
3287 byte[] messageBuffer = null;
+
3288 long messageOffset = 0;
+
3289 long messageSize = 0;
+
3290
+
3291 // Try to receive message size
+
3292 bool messageSizeCopied = false;
+
3293 bool messageSizeFound = false;
+
3294 while (!messageSizeFound)
+
3295 {
+
3296 // Look into the storage buffer
+
3297 if (offset0 < size1)
+
3298 {
+
3299 long count = Math.Min(size1 - offset0, 4);
+
3300 if (count == 4)
+
3301 {
+
3302 messageSizeCopied = true;
+
3303 messageSizeFound = true;
+
3304 messageSize = Buffer.ReadUInt32(Buffer.Data, offset0);
+
3305 offset0 += 4;
+
3306 break;
+
3307 }
+
3308 else
+
3309 {
+
3310 // Fill remaining data from the receive buffer
+
3311 if (offset2 < size2)
+
3312 {
+
3313 count = Math.Min(size2 - offset2, 4 - count);
+
3314
+
3315 // Allocate and refresh the storage buffer
+
3316 Buffer.Allocate(count);
+
3317 size1 += count;
+
3318
+
3319 Array.Copy(buffer, offset + offset2, Buffer.Data, offset1, count);
+
3320 offset1 += count;
+
3321 offset2 += count;
+
3322 continue;
+
3323 }
+
3324 else
+
3325 break;
+
3326 }
+
3327 }
+
3328
+
3329 // Look into the receive buffer
+
3330 if (offset2 < size2)
+
3331 {
+
3332 long count = Math.Min(size2 - offset2, 4);
+
3333 if (count == 4)
+
3334 {
+
3335 messageSizeFound = true;
+
3336 messageSize = Buffer.ReadUInt32(buffer, offset + offset2);
+
3337 offset2 += 4;
+
3338 break;
+
3339 }
+
3340 else
+
3341 {
+
3342 // Allocate and refresh the storage buffer
+
3343 Buffer.Allocate(count);
+
3344 size1 += count;
+
3345
+
3346 Array.Copy(buffer, offset + offset2, Buffer.Data, offset1, count);
+
3347 offset1 += count;
+
3348 offset2 += count;
+
3349 continue;
+
3350 }
+
3351 }
+
3352 else
+
3353 break;
+
3354 }
+
3355
+
3356 if (!messageSizeFound)
+
3357 return;
+
3358
+
3359 // Check the message full size
+
3360 long minSize = Final ? (4 + 4) : (4 + 4 + 4 + 4);
+
3361 Debug.Assert((messageSize >= minSize), "Invalid receive data!");
+
3362 if (messageSize < minSize)
+
3363 return;
+
3364
+
3365 // Try to receive message body
+
3366 bool messageFound = false;
+
3367 while (!messageFound)
+
3368 {
+
3369 // Look into the storage buffer
+
3370 if (offset0 < size1)
+
3371 {
+
3372 long count = Math.Min(size1 - offset0, messageSize - 4);
+
3373 if (count == (messageSize - 4))
+
3374 {
+
3375 messageFound = true;
+
3376 messageBuffer = Buffer.Data;
+
3377 messageOffset = offset0 - 4;
+
3378 offset0 += messageSize - 4;
+
3379 break;
+
3380 }
+
3381 else
+
3382 {
+
3383 // Fill remaining data from the receive buffer
+
3384 if (offset2 < size2)
+
3385 {
+
3386 // Copy message size into the storage buffer
+
3387 if (!messageSizeCopied)
+
3388 {
+
3389 // Allocate and refresh the storage buffer
+
3390 Buffer.Allocate(4);
+
3391 size1 += 4;
+
3392
+
3393 Buffer.Write(Buffer.Data, offset0, (uint)messageSize);
+
3394 offset0 += 4;
+
3395 offset1 += 4;
+
3396
+
3397 messageSizeCopied = true;
+
3398 }
+
3399
+
3400 count = Math.Min(size2 - offset2, messageSize - 4 - count);
+
3401
+
3402 // Allocate and refresh the storage buffer
+
3403 Buffer.Allocate(count);
+
3404 size1 += count;
+
3405
+
3406 Array.Copy(buffer, offset + offset2, Buffer.Data, offset1, count);
+
3407 offset1 += count;
+
3408 offset2 += count;
+
3409 continue;
+
3410 }
+
3411 else
+
3412 break;
+
3413 }
+
3414 }
+
3415
+
3416 // Look into the receive buffer
+
3417 if (offset2 < size2)
+
3418 {
+
3419 long count = Math.Min(size2 - offset2, messageSize - 4);
+
3420 if (!messageSizeCopied && (count == (messageSize - 4)))
+
3421 {
+
3422 messageFound = true;
+
3423 messageBuffer = buffer;
+
3424 messageOffset = offset + offset2 - 4;
+
3425 offset2 += messageSize - 4;
+
3426 break;
+
3427 }
+
3428 else
+
3429 {
+
3430 // Copy message size into the storage buffer
+
3431 if (!messageSizeCopied)
+
3432 {
+
3433 // Allocate and refresh the storage buffer
+
3434 Buffer.Allocate(4);
+
3435 size1 += 4;
+
3436
+
3437 Buffer.Write(Buffer.Data, offset0, (uint)messageSize);
+
3438 offset0 += 4;
+
3439 offset1 += 4;
+
3440
+
3441 messageSizeCopied = true;
+
3442 }
+
3443
+
3444 // Allocate and refresh the storage buffer
+
3445 Buffer.Allocate(count);
+
3446 size1 += count;
+
3447
+
3448 Array.Copy(buffer, offset + offset2, Buffer.Data, offset1, count);
+
3449 offset1 += count;
+
3450 offset2 += count;
+
3451 continue;
+
3452 }
+
3453 }
+
3454 else
+
3455 break;
+
3456 }
+
3457
+
3458 if (!messageFound)
+
3459 {
+
3460 // Copy message size into the storage buffer
+
3461 if (!messageSizeCopied)
+
3462 {
+
3463 // Allocate and refresh the storage buffer
+
3464 Buffer.Allocate(4);
+
3465 size1 += 4;
+
3466
+
3467 Buffer.Write(Buffer.Data, offset0, (uint)messageSize);
+
3468 offset0 += 4;
+
3469 offset1 += 4;
+
3470
+
3471 messageSizeCopied = true;
+
3472 }
+
3473 return;
+
3474 }
+
3475
+
3476 uint fbeStructSize;
+
3477 uint fbeStructType;
+
3478
+
3479 // Read the message parameters
+
3480 if (Final)
+
3481 {
+
3482 fbeStructSize = Buffer.ReadUInt32(messageBuffer, messageOffset);
+
3483 fbeStructType = Buffer.ReadUInt32(messageBuffer, messageOffset + 4);
+
3484 }
+
3485 else
+
3486 {
+
3487 uint fbeStructOffset = Buffer.ReadUInt32(messageBuffer, messageOffset + 4);
+
3488 fbeStructSize = Buffer.ReadUInt32(messageBuffer, messageOffset + fbeStructOffset);
+
3489 fbeStructType = Buffer.ReadUInt32(messageBuffer, messageOffset + fbeStructOffset + 4);
+
3490 }
+
3491
+
3492 // Handle the message
+
3493 OnReceive(fbeStructType, messageBuffer, messageOffset, messageSize);
+
3494
+
3495 // Reset the storage buffer
+
3496 Buffer.Reset();
+
3497
+
3498 // Refresh the storage buffer
+
3499 offset0 = Buffer.Offset;
+
3500 offset1 = Buffer.Size;
+
3501 size1 = Buffer.Size;
+
3502 }
+
3503 }
+
3504
+
3505 // Receive message handler
+
3506 internal abstract bool OnReceive(long type, byte[] buffer, long offset, long size);
+
3507 }
+
3508)CODE";
+
3509
+
3510 // Prepare code template
+
3511 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
3512
+
3513 Write(code);
+
3514}
+
3515
+
3516void GeneratorCSharp::GenerateFBEClient()
+
3517{
+
3518 std::string code = R"CODE(
+
3519 // Fast Binary Encoding base client listener interface
+
3520 public interface IClientListener : ISenderListener, IReceiverListener
+
3521 {
+
3522 }
+
3523
+
3524 // Fast Binary Encoding base client
+
3525 public abstract class Client : IClientListener
+
3526 {
+
3527 // Send bytes buffer
+
3528 public Buffer SendBuffer { get; }
+
3529 // Receive bytes buffer
+
3530 public Buffer ReceiveBuffer { get; }
+
3531 // Logging flag
+
3532 public bool Logging { get; set; }
+
3533 // Final protocol flag
+
3534 public bool Final { get; }
+
3535
+
3536 // Client mutex lock
+
3537 protected Mutex Lock { get; }
+
3538 // Client timestamp
+
3539 protected DateTime Timestamp { get; set; }
+
3540
+
3541 protected Client(bool final) : this(new Buffer(), new Buffer(), final) {}
+
3542 protected Client(Buffer sendBuffer, Buffer receiveBuffer, bool final) { SendBuffer = sendBuffer; ReceiveBuffer = receiveBuffer; Final = final; Lock = new Mutex(); Timestamp = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); }
+
3543
+
3544 // Reset the client buffers
+
3545 public void Reset()
+
3546 {
+
3547 lock (Lock)
+
3548 {
+
3549 ResetRequests();
+
3550 }
+
3551 }
+
3552
+
3553 // Reset client requests
+
3554 internal virtual void ResetRequests()
+
3555 {
+
3556 SendBuffer.Reset();
+
3557 ReceiveBuffer.Reset();
+
3558 }
+
3559
+
3560 // Watchdog for timeouts
+
3561 public void Watchdog(DateTime utc)
+
3562 {
+
3563 lock (Lock)
+
3564 {
+
3565 WatchdogRequests(utc);
+
3566 }
+
3567 }
+
3568
+
3569 // Watchdog client requests for timeouts
+
3570 internal virtual void WatchdogRequests(DateTime utc)
+
3571 {
+
3572 }
+
3573
+
3574 // Send serialized buffer.
+
3575 // Direct call of the method requires knowledge about internals of FBE models serialization.
+
3576 // Use it with care!
+
3577 public long SendSerialized(ISenderListener listener, long serialized)
+
3578 {
+
3579 Debug.Assert((serialized > 0), "Invalid size of the serialized buffer!");
+
3580 if (serialized == 0)
+
3581 return 0;
+
3582
+
3583 // Shift the send buffer
+
3584 SendBuffer.Shift(serialized);
+
3585
+
3586 // Send the value
+
3587 long sent = listener.OnSend(SendBuffer.Data, 0, SendBuffer.Size);
+
3588 SendBuffer.Remove(0, sent);
+
3589 return sent;
+
3590 }
+
3591
+
3592 // Receive data
+
3593 public void Receive(Buffer buffer) { Receive(buffer.Data, 0, buffer.Size); }
+
3594 public void Receive(byte[] buffer) { Receive(buffer, 0, buffer.Length); }
+
3595 public void Receive(byte[] buffer, long offset, long size)
+
3596 {
+
3597 Debug.Assert((buffer != null), "Invalid buffer!");
+
3598 if (buffer == null)
+
3599 throw new ArgumentException("Invalid buffer!", nameof(buffer));
+
3600 Debug.Assert(((offset + size) <= buffer.Length), "Invalid offset & size!");
+
3601 if ((offset + size) > buffer.Length)
+
3602 throw new ArgumentException("Invalid offset & size!", nameof(offset));
+
3603
+
3604 if (size == 0)
+
3605 return;
+
3606
+
3607 // Storage buffer
+
3608 long offset0 = ReceiveBuffer.Offset;
+
3609 long offset1 = ReceiveBuffer.Size;
+
3610 long size1 = ReceiveBuffer.Size;
+
3611
+
3612 // Receive buffer
+
3613 long offset2 = 0;
+
3614 long size2 = size;
+
3615
+
3616 // While receive buffer is available to handle...
+
3617 while (offset2 < size2)
+
3618 {
+
3619 byte[] messageBuffer = null;
+
3620 long messageOffset = 0;
+
3621 long messageSize = 0;
+
3622
+
3623 // Try to receive message size
+
3624 bool messageSizeCopied = false;
+
3625 bool messageSizeFound = false;
+
3626 while (!messageSizeFound)
+
3627 {
+
3628 // Look into the storage buffer
+
3629 if (offset0 < size1)
+
3630 {
+
3631 long count = Math.Min(size1 - offset0, 4);
+
3632 if (count == 4)
+
3633 {
+
3634 messageSizeCopied = true;
+
3635 messageSizeFound = true;
+
3636 messageSize = Buffer.ReadUInt32(ReceiveBuffer.Data, offset0);
+
3637 offset0 += 4;
+
3638 break;
+
3639 }
+
3640 else
+
3641 {
+
3642 // Fill remaining data from the receive buffer
+
3643 if (offset2 < size2)
+
3644 {
+
3645 count = Math.Min(size2 - offset2, 4 - count);
+
3646
+
3647 // Allocate and refresh the storage buffer
+
3648 ReceiveBuffer.Allocate(count);
+
3649 size1 += count;
+
3650
+
3651 Array.Copy(buffer, offset + offset2, ReceiveBuffer.Data, offset1, count);
+
3652 offset1 += count;
+
3653 offset2 += count;
+
3654 continue;
+
3655 }
+
3656 else
+
3657 break;
+
3658 }
+
3659 }
+
3660
+
3661 // Look into the receive buffer
+
3662 if (offset2 < size2)
+
3663 {
+
3664 long count = Math.Min(size2 - offset2, 4);
+
3665 if (count == 4)
+
3666 {
+
3667 messageSizeFound = true;
+
3668 messageSize = Buffer.ReadUInt32(buffer, offset + offset2);
+
3669 offset2 += 4;
+
3670 break;
+
3671 }
+
3672 else
+
3673 {
+
3674 // Allocate and refresh the storage buffer
+
3675 ReceiveBuffer.Allocate(count);
+
3676 size1 += count;
+
3677
+
3678 Array.Copy(buffer, offset + offset2, ReceiveBuffer.Data, offset1, count);
+
3679 offset1 += count;
+
3680 offset2 += count;
+
3681 continue;
+
3682 }
+
3683 }
+
3684 else
+
3685 break;
+
3686 }
+
3687
+
3688 if (!messageSizeFound)
+
3689 return;
+
3690
+
3691 // Check the message full size
+
3692 long minSize = Final ? (4 + 4) : (4 + 4 + 4 + 4);
+
3693 Debug.Assert((messageSize >= minSize), "Invalid receive data!");
+
3694 if (messageSize < minSize)
+
3695 return;
+
3696
+
3697 // Try to receive message body
+
3698 bool messageFound = false;
+
3699 while (!messageFound)
+
3700 {
+
3701 // Look into the storage buffer
+
3702 if (offset0 < size1)
+
3703 {
+
3704 long count = Math.Min(size1 - offset0, messageSize - 4);
+
3705 if (count == (messageSize - 4))
+
3706 {
+
3707 messageFound = true;
+
3708 messageBuffer = ReceiveBuffer.Data;
+
3709 messageOffset = offset0 - 4;
+
3710 offset0 += messageSize - 4;
+
3711 break;
+
3712 }
+
3713 else
+
3714 {
+
3715 // Fill remaining data from the receive buffer
+
3716 if (offset2 < size2)
+
3717 {
+
3718 // Copy message size into the storage buffer
+
3719 if (!messageSizeCopied)
+
3720 {
+
3721 // Allocate and refresh the storage buffer
+
3722 ReceiveBuffer.Allocate(4);
+
3723 size1 += 4;
+
3724
+
3725 Buffer.Write(ReceiveBuffer.Data, offset0, (uint)messageSize);
+
3726 offset0 += 4;
+
3727 offset1 += 4;
+
3728
+
3729 messageSizeCopied = true;
+
3730 }
+
3731
+
3732 count = Math.Min(size2 - offset2, messageSize - 4 - count);
+
3733
+
3734 // Allocate and refresh the storage buffer
+
3735 ReceiveBuffer.Allocate(count);
+
3736 size1 += count;
+
3737
+
3738 Array.Copy(buffer, offset + offset2, ReceiveBuffer.Data, offset1, count);
+
3739 offset1 += count;
+
3740 offset2 += count;
+
3741 continue;
+
3742 }
+
3743 else
+
3744 break;
+
3745 }
+
3746 }
+
3747
+
3748 // Look into the receive buffer
+
3749 if (offset2 < size2)
+
3750 {
+
3751 long count = Math.Min(size2 - offset2, messageSize - 4);
+
3752 if (!messageSizeCopied && (count == (messageSize - 4)))
+
3753 {
+
3754 messageFound = true;
+
3755 messageBuffer = buffer;
+
3756 messageOffset = offset + offset2 - 4;
+
3757 offset2 += messageSize - 4;
+
3758 break;
+
3759 }
+
3760 else
+
3761 {
+
3762 // Copy message size into the storage buffer
+
3763 if (!messageSizeCopied)
+
3764 {
+
3765 // Allocate and refresh the storage buffer
+
3766 ReceiveBuffer.Allocate(4);
+
3767 size1 += 4;
+
3768
+
3769 Buffer.Write(ReceiveBuffer.Data, offset0, (uint)messageSize);
+
3770 offset0 += 4;
+
3771 offset1 += 4;
+
3772
+
3773 messageSizeCopied = true;
+
3774 }
+
3775
+
3776 // Allocate and refresh the storage buffer
+
3777 ReceiveBuffer.Allocate(count);
+
3778 size1 += count;
+
3779
+
3780 Array.Copy(buffer, offset + offset2, ReceiveBuffer.Data, offset1, count);
+
3781 offset1 += count;
+
3782 offset2 += count;
+
3783 continue;
+
3784 }
+
3785 }
+
3786 else
+
3787 break;
+
3788 }
+
3789
+
3790 if (!messageFound)
+
3791 {
+
3792 // Copy message size into the storage buffer
+
3793 if (!messageSizeCopied)
+
3794 {
+
3795 // Allocate and refresh the storage buffer
+
3796 ReceiveBuffer.Allocate(4);
+
3797 size1 += 4;
+
3798
+
3799 Buffer.Write(ReceiveBuffer.Data, offset0, (uint)messageSize);
+
3800 offset0 += 4;
+
3801 offset1 += 4;
+
3802
+
3803 messageSizeCopied = true;
+
3804 }
+
3805 return;
+
3806 }
+
3807
+
3808 uint fbeStructSize;
+
3809 uint fbeStructType;
+
3810
+
3811 // Read the message parameters
+
3812 if (Final)
+
3813 {
+
3814 fbeStructSize = Buffer.ReadUInt32(messageBuffer, messageOffset);
+
3815 fbeStructType = Buffer.ReadUInt32(messageBuffer, messageOffset + 4);
+
3816 }
+
3817 else
+
3818 {
+
3819 uint fbeStructOffset = Buffer.ReadUInt32(messageBuffer, messageOffset + 4);
+
3820 fbeStructSize = Buffer.ReadUInt32(messageBuffer, messageOffset + fbeStructOffset);
+
3821 fbeStructType = Buffer.ReadUInt32(messageBuffer, messageOffset + fbeStructOffset + 4);
+
3822 }
+
3823
+
3824 // Handle the message
+
3825 OnReceive(fbeStructType, messageBuffer, messageOffset, messageSize);
+
3826
+
3827 // Reset the storage buffer
+
3828 ReceiveBuffer.Reset();
+
3829
+
3830 // Refresh the storage buffer
+
3831 offset0 = ReceiveBuffer.Offset;
+
3832 offset1 = ReceiveBuffer.Size;
+
3833 size1 = ReceiveBuffer.Size;
+
3834 }
+
3835 }
+
3836
+
3837 // Receive message handler
+
3838 internal abstract bool OnReceive(long type, byte[] buffer, long offset, long size);
+
3839 }
+
3840)CODE";
+
3841
+
3842 // Prepare code template
+
3843 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
3844
+
3845 Write(code);
+
3846}
+
3847
+
3848void GeneratorCSharp::GenerateFBEJson()
+
3849{
+
3850 std::string code = R"CODE(
+
3851#if UTF8JSON
+
3852 public sealed class ByteArrayFormatter : IJsonFormatter<byte[]>
+
3853 {
+
3854 public void Serialize(ref JsonWriter writer, byte[] value, IJsonFormatterResolver formatterResolver)
+
3855 {
+
3856 if (value == null)
+
3857 {
+
3858 writer.WriteNull();
+
3859 return;
+
3860 }
+
3861
+
3862 writer.WriteBeginArray();
+
3863
+
3864 if (value.Length != 0)
+
3865 writer.WriteByte(value[0]);
+
3866 for (int i = 1; i < value.Length; i++)
+
3867 {
+
3868 writer.WriteValueSeparator();
+
3869 writer.WriteByte(value[i]);
+
3870 }
+
3871
+
3872 writer.WriteEndArray();
+
3873 }
+
3874
+
3875 public byte[] Deserialize(ref JsonReader reader, IJsonFormatterResolver formatterResolver)
+
3876 {
+
3877 if (reader.ReadIsNull())
+
3878 return null;
+
3879
+
3880 reader.ReadIsBeginArrayWithVerify();
+
3881 var array = new byte[4];
+
3882 var count = 0;
+
3883 while (!reader.ReadIsEndArrayWithSkipValueSeparator(ref count))
+
3884 {
+
3885 if (array.Length < count)
+
3886 Array.Resize(ref array, count * 2);
+
3887 array[count - 1] = reader.ReadByte();
+
3888 }
+
3889
+
3890 Array.Resize(ref array, count);
+
3891 return array;
+
3892 }
+
3893 }
+
3894
+
3895 public class BytesFormatter : IJsonFormatter<MemoryStream>
+
3896 {
+
3897 public void Serialize(ref JsonWriter writer, MemoryStream value, IJsonFormatterResolver jsonFormatterResolver)
+
3898 {
+
3899 if (value == null)
+
3900 {
+
3901 writer.WriteNull();
+
3902 return;
+
3903 }
+
3904
+
3905 writer.WriteString(System.Convert.ToBase64String(value.GetBuffer()));
+
3906 }
+
3907
+
3908 public MemoryStream Deserialize(ref JsonReader reader, IJsonFormatterResolver jsonFormatterResolver)
+
3909 {
+
3910 if (reader.ReadIsNull())
+
3911 return null;
+
3912
+
3913 var buffer = System.Convert.FromBase64String(reader.ReadString());
+
3914 return new MemoryStream(buffer, 0, buffer.Length, true, true);
+
3915 }
+
3916 }
+
3917
+
3918 public class CharFormatter : IJsonFormatter<Char>
+
3919 {
+
3920 public void Serialize(ref JsonWriter writer, Char value, IJsonFormatterResolver jsonFormatterResolver)
+
3921 {
+
3922 writer.WriteUInt32(value);
+
3923 }
+
3924
+
3925 public Char Deserialize(ref JsonReader reader, IJsonFormatterResolver jsonFormatterResolver)
+
3926 {
+
3927 return (char)reader.ReadUInt32();
+
3928 }
+
3929 }
+
3930
+
3931 public class CharNullableFormatter : IJsonFormatter<Char?>
+
3932 {
+
3933 public void Serialize(ref JsonWriter writer, Char? value, IJsonFormatterResolver jsonFormatterResolver)
+
3934 {
+
3935 if (!value.HasValue)
+
3936 {
+
3937 writer.WriteNull();
+
3938 return;
+
3939 }
+
3940
+
3941 writer.WriteUInt32(value.Value);
+
3942 }
+
3943
+
3944 public Char? Deserialize(ref JsonReader reader, IJsonFormatterResolver jsonFormatterResolver)
+
3945 {
+
3946 if (reader.ReadIsNull())
+
3947 return null;
+
3948
+
3949 return (char)reader.ReadUInt32();
+
3950 }
+
3951 }
+
3952
+
3953 public class DateTimeFormatter : IJsonFormatter<DateTime>
+
3954 {
+
3955 private const long UnixEpoch = 621355968000000000;
+
3956
+
3957 public void Serialize(ref JsonWriter writer, DateTime value, IJsonFormatterResolver jsonFormatterResolver)
+
3958 {
+
3959 ulong nanoseconds = (ulong)((value.Ticks - UnixEpoch) * 100);
+
3960 writer.WriteUInt64(nanoseconds);
+
3961 }
+
3962
+
3963 public DateTime Deserialize(ref JsonReader reader, IJsonFormatterResolver jsonFormatterResolver)
+
3964 {
+
3965 ulong ticks = (ulong)(long)reader.ReadUInt64() / 100;
+
3966 return new DateTime((long)(UnixEpoch + ticks), DateTimeKind.Utc);
+
3967 }
+
3968 }
+
3969
+
3970 public class DateTimeNullableFormatter : IJsonFormatter<DateTime?>
+
3971 {
+
3972 private const long UnixEpoch = 621355968000000000;
+
3973
+
3974 public void Serialize(ref JsonWriter writer, DateTime? value, IJsonFormatterResolver jsonFormatterResolver)
+
3975 {
+
3976 if (!value.HasValue)
+
3977 {
+
3978 writer.WriteNull();
+
3979 return;
+
3980 }
+
3981
+
3982 ulong nanoseconds = (ulong)((value.Value.Ticks - UnixEpoch) * 100);
+
3983 writer.WriteUInt64(nanoseconds);
+
3984 }
+
3985
+
3986 public DateTime? Deserialize(ref JsonReader reader, IJsonFormatterResolver jsonFormatterResolver)
+
3987 {
+
3988 if (reader.ReadIsNull())
+
3989 return null;
+
3990
+
3991 ulong ticks = (ulong)(long)reader.ReadUInt64() / 100;
+
3992 return new DateTime((long)(UnixEpoch + ticks), DateTimeKind.Utc);
+
3993 }
+
3994 }
+
3995
+
3996 public class DecimalFormatter : IJsonFormatter<Decimal>
+
3997 {
+
3998 public void Serialize(ref JsonWriter writer, Decimal value, IJsonFormatterResolver jsonFormatterResolver)
+
3999 {
+
4000 writer.WriteString(value.ToString(CultureInfo.InvariantCulture));
+
4001 }
+
4002
+
4003 public Decimal Deserialize(ref JsonReader reader, IJsonFormatterResolver jsonFormatterResolver)
+
4004 {
+
4005 return Decimal.Parse(reader.ReadString(), CultureInfo.InvariantCulture);
+
4006 }
+
4007 }
+
4008
+
4009 public class GuidFormatter : IJsonFormatter<Guid>
+
4010 {
+
4011 public void Serialize(ref JsonWriter writer, Guid value, IJsonFormatterResolver jsonFormatterResolver)
+
4012 {
+
4013 writer.WriteString(value.ToString());
+
4014 }
+
4015
+
4016 public Guid Deserialize(ref JsonReader reader, IJsonFormatterResolver jsonFormatterResolver)
+
4017 {
+
4018 return Guid.Parse(reader.ReadString());
+
4019 }
+
4020 }
+
4021
+
4022 // Fast Binary Encoding base JSON converter
+
4023 public static class Json
+
4024 {
+
4025 static Json()
+
4026 {
+
4027 CompositeResolver.RegisterAndSetAsDefault(new IJsonFormatter[]
+
4028 {
+
4029 new ByteArrayFormatter(),
+
4030 new BytesFormatter(),
+
4031 new CharFormatter(),
+
4032 new CharNullableFormatter(),
+
4033 new DateTimeFormatter(),
+
4034 new DateTimeNullableFormatter(),
+
4035 new DecimalFormatter(),
+
4036 new GuidFormatter()
+
4037 }, new[] { StandardResolver.Default });
+
4038 }
+
4039
+
4040 public static string ToJson<T>(T value) { return Encoding.UTF8.GetString(JsonSerializer.Serialize(value)); }
+
4041 public static T FromJson<T>(string json) { return JsonSerializer.Deserialize<T>(json); }
+
4042 }
+
4043#elif NEWTONSOFTJSON
+
4044 public class BytesConverter : JsonConverter
+
4045 {
+
4046 public override bool CanConvert(Type objectType)
+
4047 {
+
4048 return (objectType == typeof(MemoryStream));
+
4049 }
+
4050
+
4051 public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
+
4052 {
+
4053 writer.WriteValue(System.Convert.ToBase64String(((MemoryStream)value).GetBuffer()));
+
4054 }
+
4055
+
4056 public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
+
4057 {
+
4058 if (reader.Value == null)
+
4059 return null;
+
4060
+
4061 var buffer = System.Convert.FromBase64String((string)reader.Value);
+
4062 return new MemoryStream(buffer, 0, buffer.Length, true, true);
+
4063 }
+
4064 }
+
4065
+
4066 public class CharConverter : JsonConverter
+
4067 {
+
4068 public override bool CanConvert(Type objectType)
+
4069 {
+
4070 return (objectType == typeof(Char)) || (objectType == typeof(Char?));
+
4071 }
+
4072
+
4073 public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
+
4074 {
+
4075 writer.WriteValue((long)(char)value);
+
4076 }
+
4077
+
4078 public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
+
4079 {
+
4080 if (reader.Value == null)
+
4081 return null;
+
4082
+
4083 return (char)(long)reader.Value;
+
4084 }
+
4085 }
+
4086
+
4087 public class DateTimeConverter : JsonConverter
+
4088 {
+
4089 private const long UnixEpoch = 621355968000000000;
+
4090
+
4091 public override bool CanConvert(Type objectType)
+
4092 {
+
4093 return (objectType == typeof(DateTime)) || (objectType == typeof(DateTime?));
+
4094 }
+
4095
+
4096 public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
+
4097 {
+
4098 ulong nanoseconds = (ulong)((((DateTime)value).Ticks - UnixEpoch) * 100);
+
4099 writer.WriteValue(nanoseconds);
+
4100 }
+
4101
+
4102 public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
+
4103 {
+
4104 if (reader.Value == null)
+
4105 return null;
+
4106
+
4107 ulong ticks = (ulong)(long)reader.Value / 100;
+
4108 return new DateTime((long)(UnixEpoch + ticks), DateTimeKind.Utc);
+
4109 }
+
4110 }
+
4111
+
4112 public class DecimalConverter : JsonConverter
+
4113 {
+
4114 public override bool CanConvert(Type objectType)
+
4115 {
+
4116 return (objectType == typeof(Decimal)) || (objectType == typeof(Decimal?));
+
4117 }
+
4118
+
4119 public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
+
4120 {
+
4121 writer.WriteValue(((Decimal)value).ToString(CultureInfo.InvariantCulture));
+
4122 }
+
4123
+
4124 public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
+
4125 {
+
4126 if (reader.Value == null)
+
4127 return null;
+
4128
+
4129 return Decimal.Parse((string)reader.Value, CultureInfo.InvariantCulture);
+
4130 }
+
4131 }
+
4132
+
4133 public class GuidConverter : JsonConverter
+
4134 {
+
4135 public override bool CanConvert(Type objectType)
+
4136 {
+
4137 return (objectType == typeof(Guid)) || (objectType == typeof(Guid?));
+
4138 }
+
4139
+
4140 public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
+
4141 {
+
4142 writer.WriteValue(((Guid)value).ToString());
+
4143 }
+
4144
+
4145 public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
+
4146 {
+
4147 if (reader.Value == null)
+
4148 return null;
+
4149
+
4150 return Guid.Parse((string)reader.Value);
+
4151 }
+
4152 }
+
4153
+
4154 // Fast Binary Encoding base JSON converter
+
4155 public static class Json
+
4156 {
+
4157 static Json()
+
4158 {
+
4159 JsonConvert.DefaultSettings = () => new JsonSerializerSettings
+
4160 {
+
4161 Converters = new List<JsonConverter>
+
4162 {
+
4163 new BytesConverter(),
+
4164 new CharConverter(),
+
4165 new DateTimeConverter(),
+
4166 new DecimalConverter(),
+
4167 new GuidConverter()
+
4168 }
+
4169 };
+
4170 }
+
4171
+
4172 public static string ToJson<T>(T value) { return JsonConvert.SerializeObject(value); }
+
4173 public static T FromJson<T>(string json) { return JsonConvert.DeserializeObject<T>(json); }
+
4174 }
+
4175#else
+
4176 public class ByteArrayConverter : JsonConverter<byte[]>
+
4177 {
+
4178 public override void Write(Utf8JsonWriter writer, byte[] value, JsonSerializerOptions options)
+
4179 {
+
4180 writer.WriteStartArray();
+
4181
+
4182 if (value.Length != 0)
+
4183 writer.WriteNumberValue(value[0]);
+
4184 for (int i = 1; i < value.Length; i++)
+
4185 writer.WriteNumberValue(value[i]);
+
4186
+
4187 writer.WriteEndArray();
+
4188 }
+
4189
+
4190 public override byte[] Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
+
4191 {
+
4192 if (reader.TokenType != JsonTokenType.StartArray)
+
4193 throw new JsonException("Expected start array token!");
+
4194
+
4195 var array = new byte[4];
+
4196 var count = 0;
+
4197 while (reader.Read())
+
4198 {
+
4199 if (reader.TokenType == JsonTokenType.EndArray)
+
4200 break;
+
4201 count++;
+
4202 if (array.Length < count)
+
4203 Array.Resize(ref array, count * 2);
+
4204 array[count - 1] = reader.GetByte();
+
4205 }
+
4206
+
4207 Array.Resize(ref array, count);
+
4208 return array;
+
4209 }
+
4210 }
+
4211
+
4212 public class BytesConverter : JsonConverter<MemoryStream>
+
4213 {
+
4214 public override void Write(Utf8JsonWriter writer, MemoryStream value, JsonSerializerOptions options) => writer.WriteStringValue(System.Convert.ToBase64String(value.GetBuffer()));
+
4215
+
4216 public override MemoryStream Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
+
4217 {
+
4218 var buffer = System.Convert.FromBase64String(reader.GetString());
+
4219 return new MemoryStream(buffer, 0, buffer.Length, true, true);
+
4220 }
+
4221 }
+
4222
+
4223 public class CharConverter : JsonConverter<Char>
+
4224 {
+
4225 public override void Write(Utf8JsonWriter writer, Char value, JsonSerializerOptions options) => writer.WriteNumberValue(value);
+
4226 public override Char Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) => (Char)reader.GetInt64();
+
4227 }
+
4228
+
4229 public class DateTimeConverter : JsonConverter<DateTime>
+
4230 {
+
4231 private const long UnixEpoch = 621355968000000000;
+
4232
+
4233 public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
+
4234 {
+
4235 ulong nanoseconds = (ulong)((value.Ticks - UnixEpoch) * 100);
+
4236 writer.WriteNumberValue(nanoseconds);
+
4237 }
+
4238
+
4239 public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
+
4240 {
+
4241 ulong ticks = reader.GetUInt64() / 100;
+
4242 return new DateTime((long)(UnixEpoch + ticks), DateTimeKind.Utc);
+
4243 }
+
4244 }
+
4245
+
4246 public class DecimalConverter : JsonConverter<Decimal>
+
4247 {
+
4248 public override void Write(Utf8JsonWriter writer, Decimal value, JsonSerializerOptions options) => writer.WriteStringValue(value.ToString(CultureInfo.InvariantCulture));
+
4249 public override Decimal Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) => Decimal.Parse(reader.GetString(), CultureInfo.InvariantCulture);
+
4250 }
+
4251
+
4252 // Fast Binary Encoding base JSON converter
+
4253 public static class Json
+
4254 {
+
4255 private static readonly JsonSerializerOptions DefaultOptions;
+
4256
+
4257 static Json()
+
4258 {
+
4259 DefaultOptions = new JsonSerializerOptions(JsonSerializerDefaults.General)
+
4260 {
+
4261 IncludeFields = true
+
4262 };
+
4263 DefaultOptions.Converters.Add(new ByteArrayConverter());
+
4264 DefaultOptions.Converters.Add(new BytesConverter());
+
4265 DefaultOptions.Converters.Add(new CharConverter());
+
4266 DefaultOptions.Converters.Add(new DateTimeConverter());
+
4267 DefaultOptions.Converters.Add(new DecimalConverter());
+
4268 }
+
4269
+
4270 public static string ToJson<T>(T value) { return JsonSerializer.Serialize(value, DefaultOptions); }
+
4271 public static T FromJson<T>(string json) { return JsonSerializer.Deserialize<T>(json, DefaultOptions); }
+
4272 }
+
4273#endif
+
4274)CODE";
+
4275
+
4276 // Prepare code template
+
4277 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
4278
+
4279 Write(code);
+
4280}
+
4281
+
4282void GeneratorCSharp::GenerateFBE(const std::string& domain, const CppCommon::Path& path)
+
4283{
+
4284 // Generate the common file
+
4285 CppCommon::Path common = path / (domain + "fbe.cs");
+
4286 WriteBegin();
+
4287
+
4288 // Generate common header
+
4289 GenerateHeader("FBE");
+
4290 GenerateImports();
+
4291
+
4292 // Generate namespace begin
+
4293 WriteLine();
+
4294 WriteLineIndent("namespace " + domain + "FBE {");
+
4295 Indent(1);
+
4296
+
4297 // Generate common models
+
4298 GenerateFBEUuidGenerator();
+
4299 GenerateFBEBuffer();
+
4300 GenerateFBEBaseModel();
+
4301 GenerateFBEFieldModelBase();
+
4302 GenerateFBEFieldModel("Bool", "bool", "", "1", "false");
+
4303 GenerateFBEFieldModel("Byte", "byte", "", "1", "(byte)0");
+
4304 GenerateFBEFieldModel("Char", "char", "(byte)", "1", "'\\0'");
+
4305 GenerateFBEFieldModel("WChar", "char", "(uint)", "4", "'\\0'");
+
4306 GenerateFBEFieldModel("Int8", "sbyte", "", "1", "0");
+
4307 GenerateFBEFieldModel("UInt8", "byte", "", "1", "(byte)0");
+
4308 GenerateFBEFieldModel("Int16", "short", "", "2", "0");
+
4309 GenerateFBEFieldModel("UInt16", "ushort", "", "2", "(ushort)0");
+
4310 GenerateFBEFieldModel("Int32", "int", "", "4", "0");
+
4311 GenerateFBEFieldModel("UInt32", "uint", "", "4", "0U");
+
4312 GenerateFBEFieldModel("Int64", "long", "", "8", "0L");
+
4313 GenerateFBEFieldModel("UInt64", "ulong", "", "8", "0UL");
+
4314 GenerateFBEFieldModel("Float", "float", "", "4", "0.0F");
+
4315 GenerateFBEFieldModel("Double", "double", "", "8", "0.0D");
+
4316 GenerateFBEFieldModel("Decimal", "decimal", "", "16", "0.0M");
+
4317 GenerateFBEFieldModel("UUID", "Guid", "", "16", "UuidGenerator.Nil()");
+
4318 GenerateFBEFieldModelTimestamp();
+
4319 GenerateFBEFieldModelBytes();
+
4320 GenerateFBEFieldModelString();
+
4321 GenerateFBEFieldModelOptional(true);
+
4322 GenerateFBEFieldModelOptional(false);
+
4323 GenerateFBEFieldModelArray(true, false);
+
4324 GenerateFBEFieldModelArray(false, false);
+
4325 GenerateFBEFieldModelArray(true, true);
+
4326 GenerateFBEFieldModelArray(false, true);
+
4327 GenerateFBEFieldModelVector(true, false);
+
4328 GenerateFBEFieldModelVector(false, false);
+
4329 GenerateFBEFieldModelVector(true, true);
+
4330 GenerateFBEFieldModelVector(false, true);
+
4331 GenerateFBEFieldModelMap(true, true, false);
+
4332 GenerateFBEFieldModelMap(true, false, false);
+
4333 GenerateFBEFieldModelMap(true, true, true);
+
4334 GenerateFBEFieldModelMap(true, false, true);
+
4335 GenerateFBEFieldModelMap(false, true, false);
+
4336 GenerateFBEFieldModelMap(false, false, false);
+
4337 GenerateFBEFieldModelMap(false, true, true);
+
4338 GenerateFBEFieldModelMap(false, false, true);
+
4339 if (Final())
+
4340 {
+
4341 GenerateFBEFinalModelBase();
+
4342 GenerateFBEFinalModel("Bool", "bool", "", "1", "false");
+
4343 GenerateFBEFinalModel("Byte", "byte", "", "1", "(byte)0");
+
4344 GenerateFBEFinalModel("Char", "char", "(byte)", "1", "'\\0'");
+
4345 GenerateFBEFinalModel("WChar", "char", "(uint)", "4", "'\\0'");
+
4346 GenerateFBEFinalModel("Int8", "sbyte", "", "1", "0");
+
4347 GenerateFBEFinalModel("UInt8", "byte", "", "1", "(byte)0");
+
4348 GenerateFBEFinalModel("Int16", "short", "", "2", "0");
+
4349 GenerateFBEFinalModel("UInt16", "ushort", "", "2", "(ushort)0");
+
4350 GenerateFBEFinalModel("Int32", "int", "", "4", "0");
+
4351 GenerateFBEFinalModel("UInt32", "uint", "", "4", "0U");
+
4352 GenerateFBEFinalModel("Int64", "long", "", "8", "0L");
+
4353 GenerateFBEFinalModel("UInt64", "ulong", "", "8", "0UL");
+
4354 GenerateFBEFinalModel("Float", "float", "", "4", "0.0F");
+
4355 GenerateFBEFinalModel("Double", "double", "", "8", "0.0D");
+
4356 GenerateFBEFinalModel("Decimal", "decimal", "", "16", "0.0M");
+
4357 GenerateFBEFinalModel("UUID", "Guid", "", "16", "UuidGenerator.Nil()");
+
4358 GenerateFBEFinalModelTimestamp();
+
4359 GenerateFBEFinalModelBytes();
+
4360 GenerateFBEFinalModelString();
+
4361 GenerateFBEFinalModelOptional(true);
+
4362 GenerateFBEFinalModelOptional(false);
+
4363 GenerateFBEFinalModelArray(true, false);
+
4364 GenerateFBEFinalModelArray(false, false);
+
4365 GenerateFBEFinalModelArray(true, true);
+
4366 GenerateFBEFinalModelArray(false, true);
+
4367 GenerateFBEFinalModelVector(true, false);
+
4368 GenerateFBEFinalModelVector(false, false);
+
4369 GenerateFBEFinalModelVector(true, true);
+
4370 GenerateFBEFinalModelVector(false, true);
+
4371 GenerateFBEFinalModelMap(true, true, false);
+
4372 GenerateFBEFinalModelMap(true, false, false);
+
4373 GenerateFBEFinalModelMap(true, true, true);
+
4374 GenerateFBEFinalModelMap(true, false, true);
+
4375 GenerateFBEFinalModelMap(false, true, false);
+
4376 GenerateFBEFinalModelMap(false, false, false);
+
4377 GenerateFBEFinalModelMap(false, true, true);
+
4378 GenerateFBEFinalModelMap(false, false, true);
+
4379 }
+
4380 if (Proto())
+
4381 {
+
4382 GenerateFBESender();
+
4383 GenerateFBEReceiver();
+
4384 GenerateFBEClient();
+
4385 }
+
4386 if (JSON())
+
4387 GenerateFBEJson();
+
4388
+
4389 // Generate namespace end
+
4390 Indent(-1);
+
4391 WriteLine();
+
4392 WriteLineIndent("} // namespace " + domain + "FBE");
+
4393
+
4394 // Generate common footer
+
4395 GenerateFooter();
+
4396
+
4397 // Store the common file
+
4398 WriteEnd();
+
4399 Store(common);
+
4400}
+
4401
+
4402void GeneratorCSharp::GeneratePackage(const std::string& domain, const std::shared_ptr<Package>& p)
+
4403{
+
4404 CppCommon::Path output = _output;
+
4405
+
4406 // Create package path
+
4407 CppCommon::Directory::CreateTree(output);
+
4408
+
4409 // Generate common file
+
4410 GenerateFBE(domain, output);
+
4411
+
4412 // Generate the output file
+
4413 output /= domain + *p->name + ".cs";
+
4414 WriteBegin();
+
4415
+
4416 // Generate package header
+
4417 GenerateHeader(CppCommon::Path(_input).filename().string());
+
4418 GenerateImports(domain, p);
+
4419
+
4420 // Generate namespace body
+
4421 if (p->body)
+
4422 {
+
4423 // Generate child enums
+
4424 for (const auto& child_e : p->body->enums)
+
4425 GenerateEnum(domain, p, child_e);
+
4426
+
4427 // Generate child flags
+
4428 for (const auto& child_f : p->body->flags)
+
4429 GenerateFlags(domain, p, child_f);
+
4430
+
4431 // Generate child structs
+
4432 for (const auto& child_s : p->body->structs)
+
4433 GenerateStruct(domain, p, child_s);
+
4434 }
+
4435
+
4436 // Generate protocol
+
4437 if (Proto())
+
4438 {
+
4439 // Generate protocol version
+
4440 GenerateProtocolVersion(domain, p);
+
4441
+
4442 // Generate sender & receiver
+
4443 GenerateSender(domain, p, false);
+
4444 GenerateReceiver(domain, p, false);
+
4445 GenerateProxy(domain, p, false);
+
4446 GenerateClient(domain, p, false);
+
4447 if (Final())
+
4448 {
+
4449 GenerateSender(domain, p, true);
+
4450 GenerateReceiver(domain, p, true);
+
4451 GenerateClient(domain, p, true);
+
4452 }
+
4453 }
+
4454
+
4455 // Generate package footer
+
4456 GenerateFooter();
+
4457
+
4458 // Store the output file
+
4459 WriteEnd();
+
4460 Store(output);
+
4461}
+
4462
+
4463void GeneratorCSharp::GenerateEnum(const std::string& domain, const std::shared_ptr<Package>& p, const std::shared_ptr<EnumType>& e)
+
4464{
+
4465 // Generate namespace begin
+
4466 WriteLine();
+
4467 WriteLineIndent("namespace " + domain + *p->name + " {");
+
4468 Indent(1);
+
4469
+
4470 std::string json = R"CODE(
+
4471#if UTF8JSON
+
4472 public class _ENUM_NAME_Converter : IJsonFormatter<_ENUM_NAME_>
+
4473 {
+
4474 public void Serialize(ref JsonWriter writer, _ENUM_NAME_ value, IJsonFormatterResolver jsonFormatterResolver)
+
4475 {
+
4476 writer.Write_ENUM_UTF8JSON_TYPE_(value.Value);
+
4477 }
+
4478
+
4479 public _ENUM_NAME_ Deserialize(ref JsonReader reader, IJsonFormatterResolver jsonFormatterResolver)
+
4480 {
+
4481 return new _ENUM_NAME_(reader.Read_ENUM_UTF8JSON_TYPE_());
+
4482 }
+
4483 }
+
4484
+
4485 [JsonFormatter(typeof(_ENUM_NAME_Converter))]
+
4486#elif NEWTONSOFTJSON
+
4487 public class _ENUM_NAME_Converter : JsonConverter
+
4488 {
+
4489 public override bool CanConvert(Type objectType)
+
4490 {
+
4491 return objectType == typeof(_ENUM_NAME_);
+
4492 }
+
4493
+
4494 public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
+
4495 {
+
4496 writer.WriteValue(((_ENUM_NAME_)value).Value);
+
4497 }
+
4498
+
4499 public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
+
4500 {
+
4501 if (reader.Value == null)
+
4502 return null;
+
4503
+
4504 switch (reader.Value)
+
4505 {
+
4506 case long longValue:
+
4507 return new _ENUM_NAME_((_ENUM_TYPE_)longValue);
+
4508 case BigInteger bigValue:
+
4509 return new _ENUM_NAME_((_ENUM_TYPE_)bigValue);
+
4510 default:
+
4511 return null;
+
4512 }
+
4513 }
+
4514 }
+
4515
+
4516 [JsonConverter(typeof(_ENUM_NAME_Converter))]
+
4517#else
+
4518 public class _ENUM_NAME_Converter : JsonConverter<_ENUM_NAME_>
+
4519 {
+
4520 public override void Write(Utf8JsonWriter writer, _ENUM_NAME_ value, JsonSerializerOptions options) => writer.WriteNumberValue(value.Value);
+
4521 public override _ENUM_NAME_ Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) => new _ENUM_NAME_(reader.Get_ENUM_UTF8JSON_TYPE_());
+
4522 }
+
4523
+
4524 [JsonConverter(typeof(_ENUM_NAME_Converter))]
+
4525#endif)CODE";
+
4526
+
4527 std::string code = R"CODE(
+
4528 public struct _ENUM_NAME_ : IComparable, IComparable<_ENUM_NAME_>, IEquatable<_ENUM_NAME_>
+
4529 {
+
4530 public _ENUM_TYPE_ Value { get; internal set; }
+
4531
+
4532 public _ENUM_NAME_(_ENUM_TYPE_ value) : this()
+
4533 {
+
4534 Value = value;
+
4535 }
+
4536
+
4537 public _ENUM_NAME_(_ENUM_NAME_ value) : this()
+
4538 {
+
4539 Value = value.Value;
+
4540 }
+
4541
+
4542 public int CompareTo(object other)
+
4543 {
+
4544 return Value.CompareTo(((_ENUM_NAME_)other).Value);
+
4545 }
+
4546
+
4547 public int CompareTo(_ENUM_NAME_ other)
+
4548 {
+
4549 return Value.CompareTo(other.Value);
+
4550 }
+
4551
+
4552 public override bool Equals(object other)
+
4553 {
+
4554 return (other is _ENUM_NAME_ value) && Value.Equals(value.Value);
+
4555 }
+
4556
+
4557 public bool Equals(_ENUM_NAME_ other)
+
4558 {
+
4559 return Value.Equals(other.Value);
+
4560 }
+
4561
+
4562 public override int GetHashCode()
+
4563 {
+
4564 return Value.GetHashCode();
+
4565 }
+
4566
+
4567 public static bool operator==(_ENUM_NAME_ value1, _ENUM_NAME_ value2)
+
4568 {
+
4569 return value1.Value == value2.Value;
+
4570 }
+
4571
+
4572 public static bool operator!=(_ENUM_NAME_ value1, _ENUM_NAME_ value2)
+
4573 {
+
4574 return value1.Value != value2.Value;
+
4575 }
+
4576
+
4577 public static _ENUM_NAME_ Default => new _ENUM_NAME_();
+
4578
+
4579 public static _DOMAIN_FBE.FieldModelValueType<_ENUM_NAME_> CreateFieldModel(_DOMAIN_FBE.Buffer buffer, long offset) { return new _PACKAGE_.FBE.FieldModel_ENUM_NAME_(buffer, offset); }
+
4580
+
4581)CODE";
+
4582
+
4583 std::string enum_type = (e->base && !e->base->empty()) ? *e->base : "int32";
+
4584 std::string enum_base_type = ConvertEnumType(enum_type);
+
4585
+
4586 // Prepare enum template
+
4587 json = std::regex_replace(json, std::regex("_ENUM_NAME_"), *e->name);
+
4588 json = std::regex_replace(json, std::regex("_ENUM_TYPE_"), enum_base_type);
+
4589 json = std::regex_replace(json, std::regex("_ENUM_UTF8JSON_TYPE_"), ConvertEnumTypeUtf8Json(enum_type));
+
4590 json = std::regex_replace(json, std::regex("\n"), EndLine());
+
4591 code = std::regex_replace(code, std::regex("_DOMAIN_"), domain);
+
4592 code = std::regex_replace(code, std::regex("_PACKAGE_"), *p->name);
+
4593 code = std::regex_replace(code, std::regex("_ENUM_NAME_"), *e->name);
+
4594 code = std::regex_replace(code, std::regex("_ENUM_TYPE_"), enum_base_type);
+
4595 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
4596
+
4597 // Generate enum begin
+
4598 if (JSON())
+
4599 Write(json);
+
4600 Write(code);
+
4601 Indent(1);
+
4602
+
4603 // Generate enum constants
+
4604 if (e->body)
+
4605 {
+
4606 int index = 0;
+
4607 std::string last = ConvertEnumConstant(enum_type, "0");
+
4608 for (auto it = e->body->values.begin(); it != e->body->values.end(); ++it)
+
4609 {
+
4610 WriteIndent("public const " + enum_base_type + " _" + *(*it)->name + "_ = ");
+
4611 if ((*it)->value)
+
4612 {
+
4613 if ((*it)->value->constant && !(*it)->value->constant->empty())
+
4614 {
+
4615 index = 0;
+
4616 last = ConvertEnumConstant(enum_type, *(*it)->value->constant);
+
4617 Write(last + " + " + std::to_string(index++));
+
4618 }
+
4619 else if ((*it)->value->reference && !(*it)->value->reference->empty())
+
4620 {
+
4621 index = 0;
+
4622 last = ConvertEnumConstant("", *(*it)->value->reference);
+
4623 Write("_" + last + "_");
+
4624 }
+
4625 }
+
4626 else
+
4627 Write(last + " + " + std::to_string(index++));
+
4628 WriteLine(";");
+
4629 }
+
4630 WriteLine();
+
4631 }
+
4632
+
4633 // Generate enum body
+
4634 if (e->body)
+
4635 {
+
4636 for (auto it = e->body->values.begin(); it != e->body->values.end(); ++it)
+
4637 WriteLineIndent("public static " + *e->name + " " + *(*it)->name + " = new " + *e->name + "(_" + *(*it)->name + "_);");
+
4638 WriteLine();
+
4639 }
+
4640
+
4641 // Generate enum ToString() method
+
4642 WriteLineIndent("public override string ToString()");
+
4643 WriteLineIndent("{");
+
4644 Indent(1);
+
4645 if (e->body && !e->body->values.empty())
+
4646 {
+
4647 for (const auto& value : e->body->values)
+
4648 WriteLineIndent("if (this == " + *value->name + ")" + " return \"" + *value->name + "\";");
+
4649 WriteLineIndent("return \"<unknown>\";");
+
4650 }
+
4651 else
+
4652 WriteLineIndent("return \"<empty>\";");
+
4653 Indent(-1);
+
4654 WriteLineIndent("}");
+
4655
+
4656 // Generate enum end
+
4657 Indent(-1);
+
4658 WriteLineIndent("}");
+
4659
+
4660 // Generate namespace end
+
4661 Indent(-1);
+
4662 WriteLine();
+
4663 WriteLineIndent("} // namespace " + domain + *p->name);
+
4664
+
4665 // Generate enum field model
+
4666 GenerateEnumFieldModel(domain, p, e);
+
4667
+
4668 // Generate enum final model
+
4669 if (Final())
+
4670 GenerateEnumFinalModel(domain, p, e);
+
4671}
+
4672
+
4673void GeneratorCSharp::GenerateEnumFieldModel(const std::string& domain, const std::shared_ptr<Package>& p, const std::shared_ptr<EnumType>& e)
+
4674{
+
4675 // Generate namespace begin
+
4676 WriteLine();
+
4677 WriteLineIndent("namespace " + domain + *p->name + ".FBE {");
+
4678 Indent(1);
+
4679
+
4680 std::string code = R"CODE(
+
4681 using global::_DOMAIN__PACKAGE_;
+
4682
+
4683 // Fast Binary Encoding _ENUM_NAME_ field model
+
4684 public class FieldModel_ENUM_NAME_ : _DOMAIN_FBE.FieldModelValueType<_ENUM_NAME_>
+
4685 {
+
4686 public FieldModel_ENUM_NAME_(_DOMAIN_FBE.Buffer buffer, long offset) : base(buffer, offset) {}
+
4687
+
4688 // Get the field size
+
4689 public override long FBESize => _ENUM_SIZE_;
+
4690
+
4691 // Clone the field model
+
4692 public override _DOMAIN_FBE.FieldModelValueType<_ENUM_NAME_> Clone() { return new FieldModel_ENUM_NAME_(_buffer, _offset); }
+
4693
+
4694 // Get the value
+
4695 public override void Get(out _ENUM_NAME_ value) { Get(out value, _ENUM_NAME_.Default); }
+
4696 public override void Get(out _ENUM_NAME_ value, _ENUM_NAME_ defaults)
+
4697 {
+
4698 if ((_buffer.Offset + FBEOffset + FBESize) > _buffer.Size)
+
4699 {
+
4700 value = defaults;
+
4701 return;
+
4702 }
+
4703
+
4704 value = new _ENUM_NAME_((_ENUM_TYPE_)_ENUM_READ_(FBEOffset));
+
4705 }
+
4706
+
4707 // Set the value
+
4708 public override void Set(_ENUM_NAME_ value)
+
4709 {
+
4710 Debug.Assert(((_buffer.Offset + FBEOffset + FBESize) <= _buffer.Size), "Model is broken!");
+
4711 if ((_buffer.Offset + FBEOffset + FBESize) > _buffer.Size)
+
4712 return;
+
4713
+
4714 Write(FBEOffset, value.Value);
+
4715 }
+
4716 }
+
4717)CODE";
+
4718
+
4719 std::string enum_type = (e->base && !e->base->empty()) ? *e->base : "int32";
+
4720 std::string enum_base_type = ConvertEnumType(enum_type);
+
4721
+
4722 // Prepare enum model template
+
4723 code = std::regex_replace(code, std::regex("_DOMAIN_"), domain);
+
4724 code = std::regex_replace(code, std::regex("_PACKAGE_"), *p->name);
+
4725 code = std::regex_replace(code, std::regex("_ENUM_NAME_"), *e->name);
+
4726 code = std::regex_replace(code, std::regex("_ENUM_TYPE_"), enum_base_type);
+
4727 code = std::regex_replace(code, std::regex("_ENUM_SIZE_"), ConvertEnumSize(enum_type));
+
4728 code = std::regex_replace(code, std::regex("_ENUM_READ_"), ConvertEnumRead(enum_type));
+
4729 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
4730
+
4731 // Generate enum model
+
4732 Write(code);
+
4733
+
4734 // Generate namespace end
+
4735 Indent(-1);
+
4736 WriteLine();
+
4737 WriteLineIndent("} // namespace " + domain + *p->name + ".FBE");
+
4738}
+
4739
+
4740void GeneratorCSharp::GenerateEnumFinalModel(const std::string& domain, const std::shared_ptr<Package>& p, const std::shared_ptr<EnumType>& e)
+
4741{
+
4742 // Generate namespace begin
+
4743 WriteLine();
+
4744 WriteLineIndent("namespace " + domain + *p->name + ".FBE {");
+
4745 Indent(1);
+
4746
+
4747 std::string code = R"CODE(
+
4748 using global::_DOMAIN__PACKAGE_;
+
4749
+
4750 // Fast Binary Encoding _ENUM_NAME_ final model
+
4751 public class FinalModel_ENUM_NAME_ : _DOMAIN_FBE.FinalModelValueType<_ENUM_NAME_>
+
4752 {
+
4753 public FinalModel_ENUM_NAME_(_DOMAIN_FBE.Buffer buffer, long offset) : base(buffer, offset) {}
+
4754
+
4755 // Get the allocation size
+
4756 public override long FBEAllocationSize(_ENUM_NAME_ value) { return FBESize; }
+
4757
+
4758 // Get the final size
+
4759 public override long FBESize => _ENUM_SIZE_;
+
4760
+
4761 // Clone the final model
+
4762 public override _DOMAIN_FBE.FinalModelValueType<_ENUM_NAME_> Clone() { return new FinalModel_ENUM_NAME_(_buffer, _offset); }
+
4763
+
4764 // Check if the value is valid
+
4765 public override long Verify()
+
4766 {
+
4767 if ((_buffer.Offset + FBEOffset + FBESize) > _buffer.Size)
+
4768 return long.MaxValue;
+
4769
+
4770 return FBESize;
+
4771 }
+
4772
+
4773 // Get the value
+
4774 public override long Get(out _ENUM_NAME_ value)
+
4775 {
+
4776 if ((_buffer.Offset + FBEOffset + FBESize) > _buffer.Size)
+
4777 {
+
4778 value = _ENUM_NAME_.Default;
+
4779 return 0;
+
4780 }
+
4781
+
4782 value = new _ENUM_NAME_((_ENUM_TYPE_)_ENUM_READ_(FBEOffset));
+
4783 return FBESize;
+
4784 }
+
4785
+
4786 // Set the value
+
4787 public override long Set(_ENUM_NAME_ value)
+
4788 {
+
4789 Debug.Assert(((_buffer.Offset + FBEOffset + FBESize) <= _buffer.Size), "Model is broken!");
+
4790 if ((_buffer.Offset + FBEOffset + FBESize) > _buffer.Size)
+
4791 return 0;
+
4792
+
4793 Write(FBEOffset, value.Value);
+
4794 return FBESize;
+
4795 }
+
4796 }
+
4797)CODE";
+
4798
+
4799 std::string enum_type = (e->base && !e->base->empty()) ? *e->base : "int32";
+
4800 std::string enum_base_type = ConvertEnumType(enum_type);
+
4801
+
4802 // Prepare enum model template
+
4803 code = std::regex_replace(code, std::regex("_DOMAIN_"), domain);
+
4804 code = std::regex_replace(code, std::regex("_PACKAGE_"), *p->name);
+
4805 code = std::regex_replace(code, std::regex("_ENUM_NAME_"), *e->name);
+
4806 code = std::regex_replace(code, std::regex("_ENUM_TYPE_"), enum_base_type);
+
4807 code = std::regex_replace(code, std::regex("_ENUM_SIZE_"), ConvertEnumSize(enum_type));
+
4808 code = std::regex_replace(code, std::regex("_ENUM_READ_"), ConvertEnumRead(enum_type));
+
4809 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
4810
+
4811 // Generate enum model
+
4812 Write(code);
+
4813
+
4814 // Generate namespace end
+
4815 Indent(-1);
+
4816 WriteLine();
+
4817 WriteLineIndent("} // namespace " + domain + *p->name + ".FBE");
+
4818}
+
4819
+
4820void GeneratorCSharp::GenerateFlags(const std::string& domain, const std::shared_ptr<Package>& p, const std::shared_ptr<FlagsType>& f)
+
4821{
+
4822 // Generate namespace begin
+
4823 WriteLine();
+
4824 WriteLineIndent("namespace " + domain + *p->name + " {");
+
4825 Indent(1);
+
4826
+
4827 std::string json = R"CODE(
+
4828#if UTF8JSON
+
4829 public class _FLAGS_NAME_Converter : IJsonFormatter<_FLAGS_NAME_>
+
4830 {
+
4831 public void Serialize(ref JsonWriter writer, _FLAGS_NAME_ value, IJsonFormatterResolver jsonFormatterResolver)
+
4832 {
+
4833 writer.Write_FLAGS_UTF8JSON_TYPE_(value.Value);
+
4834 }
+
4835
+
4836 public _FLAGS_NAME_ Deserialize(ref JsonReader reader, IJsonFormatterResolver jsonFormatterResolver)
+
4837 {
+
4838 return new _FLAGS_NAME_(reader.Read_FLAGS_UTF8JSON_TYPE_());
+
4839 }
+
4840 }
+
4841
+
4842 [JsonFormatter(typeof(_FLAGS_NAME_Converter))]
+
4843#elif NEWTONSOFTJSON
+
4844 public class _FLAGS_NAME_Converter : JsonConverter
+
4845 {
+
4846 public override bool CanConvert(Type objectType)
+
4847 {
+
4848 return objectType == typeof(_FLAGS_NAME_);
+
4849 }
+
4850
+
4851 public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
+
4852 {
+
4853 writer.WriteValue(((_FLAGS_NAME_)value).Value);
+
4854 }
+
4855
+
4856 public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
+
4857 {
+
4858 if (reader.Value == null)
+
4859 return null;
+
4860
+
4861 switch (reader.Value)
+
4862 {
+
4863 case long longValue:
+
4864 return new _FLAGS_NAME_((_FLAGS_TYPE_)longValue);
+
4865 case BigInteger bigValue:
+
4866 return new _FLAGS_NAME_((_FLAGS_TYPE_)bigValue);
+
4867 default:
+
4868 return null;
+
4869 }
+
4870 }
+
4871 }
+
4872
+
4873 [JsonConverter(typeof(_FLAGS_NAME_Converter))]
+
4874#else
+
4875 public class _FLAGS_NAME_Converter : JsonConverter<_FLAGS_NAME_>
+
4876 {
+
4877 public override void Write(Utf8JsonWriter writer, _FLAGS_NAME_ value, JsonSerializerOptions options) => writer.WriteNumberValue(value.Value);
+
4878 public override _FLAGS_NAME_ Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) => new _FLAGS_NAME_(reader.Get_FLAGS_UTF8JSON_TYPE_());
+
4879 }
+
4880
+
4881 [JsonConverter(typeof(_FLAGS_NAME_Converter))]
+
4882#endif)CODE";
+
4883
+
4884 std::string code = R"CODE(
+
4885 public struct _FLAGS_NAME_ : IComparable, IComparable<_FLAGS_NAME_>, IEquatable<_FLAGS_NAME_>
+
4886 {
+
4887 public _FLAGS_TYPE_ Value { get; internal set; }
+
4888
+
4889 public _FLAGS_NAME_(_FLAGS_TYPE_ value) : this()
+
4890 {
+
4891 Value = value;
+
4892 }
+
4893
+
4894 public _FLAGS_NAME_(_FLAGS_NAME_ value) : this()
+
4895 {
+
4896 Value = value.Value;
+
4897 }
+
4898
+
4899 public bool HasFlags(_FLAGS_NAME_ flags)
+
4900 {
+
4901 return (((Value & flags.Value) != 0) && ((Value & flags.Value) == flags.Value));
+
4902 }
+
4903
+
4904 public _FLAGS_NAME_ SetFlags(_FLAGS_NAME_ flags)
+
4905 {
+
4906 Value |= flags.Value;
+
4907 return this;
+
4908 }
+
4909
+
4910 public _FLAGS_NAME_ RemoveFlags(_FLAGS_NAME_ flags)
+
4911 {
+
4912 Value &= (_FLAGS_TYPE_)~flags.Value;
+
4913 return this;
+
4914 }
+
4915
+
4916 public int CompareTo(object other)
+
4917 {
+
4918 return Value.CompareTo(((_FLAGS_NAME_)other).Value);
+
4919 }
+
4920
+
4921 public int CompareTo(_FLAGS_NAME_ other)
+
4922 {
+
4923 return Value.CompareTo(other.Value);
+
4924 }
+
4925
+
4926 public override bool Equals(object other)
+
4927 {
+
4928 return (other is _FLAGS_NAME_ value) && Value.Equals(value.Value);
+
4929 }
+
4930
+
4931 public bool Equals(_FLAGS_NAME_ other)
+
4932 {
+
4933 return Value.Equals(other.Value);
+
4934 }
+
4935
+
4936 public override int GetHashCode()
+
4937 {
+
4938 return Value.GetHashCode();
+
4939 }
+
4940
+
4941 public static bool operator==(_FLAGS_NAME_ flags1, _FLAGS_NAME_ flags2)
+
4942 {
+
4943 return flags1.Value == flags2.Value;
+
4944 }
+
4945
+
4946 public static bool operator!=(_FLAGS_NAME_ flags1, _FLAGS_NAME_ flags2)
+
4947 {
+
4948 return flags1.Value != flags2.Value;
+
4949 }
+
4950
+
4951 public static _FLAGS_NAME_ operator&(_FLAGS_NAME_ flags1, _FLAGS_NAME_ flags2)
+
4952 {
+
4953 return new _FLAGS_NAME_((_FLAGS_TYPE_)(flags1.Value & flags2.Value));
+
4954 }
+
4955
+
4956 public static _FLAGS_NAME_ operator|(_FLAGS_NAME_ flags1, _FLAGS_NAME_ flags2)
+
4957 {
+
4958 return new _FLAGS_NAME_((_FLAGS_TYPE_)(flags1.Value | flags2.Value));
+
4959 }
+
4960
+
4961 public static _FLAGS_NAME_ operator^(_FLAGS_NAME_ flags1, _FLAGS_NAME_ flags2)
+
4962 {
+
4963 return new _FLAGS_NAME_((_FLAGS_TYPE_)(flags1.Value ^ flags2.Value));
+
4964 }
+
4965
+
4966 public static _FLAGS_NAME_ Default => new _FLAGS_NAME_();
+
4967
+
4968 public static _DOMAIN_FBE.FieldModelValueType<_FLAGS_NAME_> CreateFieldModel(_DOMAIN_FBE.Buffer buffer, long offset) { return new _PACKAGE_.FBE.FieldModel_FLAGS_NAME_(buffer, offset); }
+
4969
+
4970)CODE";
+
4971
+
4972 std::string flags_type = (f->base && !f->base->empty()) ? *f->base : "int32";
+
4973 std::string flags_base_type = ConvertEnumType(flags_type);
+
4974
+
4975 // Prepare flags template
+
4976 json = std::regex_replace(json, std::regex("_FLAGS_NAME_"), *f->name);
+
4977 json = std::regex_replace(json, std::regex("_FLAGS_TYPE_"), flags_base_type);
+
4978 json = std::regex_replace(json, std::regex("_FLAGS_UTF8JSON_TYPE_"), ConvertEnumTypeUtf8Json(flags_type));
+
4979 json = std::regex_replace(json, std::regex("\n"), EndLine());
+
4980 code = std::regex_replace(code, std::regex("_DOMAIN_"), domain);
+
4981 code = std::regex_replace(code, std::regex("_PACKAGE_"), *p->name);
+
4982 code = std::regex_replace(code, std::regex("_FLAGS_NAME_"), *f->name);
+
4983 code = std::regex_replace(code, std::regex("_FLAGS_TYPE_"), flags_base_type);
+
4984 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
4985
+
4986 // Generate flags begin
+
4987 if (JSON())
+
4988 Write(json);
+
4989 Write(code);
+
4990 Indent(1);
+
4991
+
4992 // Generate flags constants
+
4993 if (f->body)
+
4994 {
+
4995 for (auto it = f->body->values.begin(); it != f->body->values.end(); ++it)
+
4996 {
+
4997 if ((*it)->value)
+
4998 {
+
4999 if ((*it)->value->constant && !(*it)->value->constant->empty())
+
5000 WriteLineIndent("public const " + flags_base_type + " _" + *(*it)->name + "_ = " + ConvertEnumConstant(flags_type, *(*it)->value->constant) + ";");
+
5001 else if ((*it)->value->reference && !(*it)->value->reference->empty())
+
5002 WriteLineIndent("public const " + flags_base_type + " _" + *(*it)->name + "_ = _" + ConvertEnumConstant("", *(*it)->value->reference) + "_;");
+
5003 }
+
5004 }
+
5005 WriteLine();
+
5006 }
+
5007
+
5008 // Generate flags body
+
5009 if (f->body)
+
5010 {
+
5011 for (auto it = f->body->values.begin(); it != f->body->values.end(); ++it)
+
5012 if ((*it)->value)
+
5013 WriteLineIndent("public static " + *f->name + " " + *(*it)->name + " = new " + *f->name + "(_" + *(*it)->name + "_);");
+
5014 WriteLine();
+
5015 }
+
5016
+
5017 // Generate flags ToString() method
+
5018 WriteLineIndent("public override string ToString()");
+
5019 WriteLineIndent("{");
+
5020 Indent(1);
+
5021 WriteLineIndent("var value = new " + *f->name + "(Value);");
+
5022 WriteLineIndent("var sb = new StringBuilder();");
+
5023 if (f->body && !f->body->values.empty())
+
5024 {
+
5025 WriteLineIndent("bool first = true;");
+
5026 for (const auto& value : f->body->values)
+
5027 {
+
5028 WriteLineIndent("if (HasFlags(" + *value->name + "))");
+
5029 WriteLineIndent("{");
+
5030 Indent(1);
+
5031 WriteLineIndent("sb.Append(first ? \"\" : \"|\").Append(\"" + *value->name + "\");");
+
5032 WriteLineIndent("first = false;");
+
5033 Indent(-1);
+
5034 WriteLineIndent("}");
+
5035 }
+
5036 }
+
5037 WriteLineIndent("return sb.ToString();");
+
5038 Indent(-1);
+
5039 WriteLineIndent("}");
+
5040
+
5041 // Generate flags end
+
5042 Indent(-1);
+
5043 WriteLineIndent("}");
+
5044
+
5045 // Generate namespace end
+
5046 Indent(-1);
+
5047 WriteLine();
+
5048 WriteLineIndent("} // namespace " + domain + *p->name);
+
5049
+
5050 // Generate flags field model
+
5051 GenerateFlagsFieldModel(domain, p, f);
+
5052
+
5053 // Generate flags final model
+
5054 if (Final())
+
5055 GenerateFlagsFinalModel(domain, p, f);
+
5056}
+
5057
+
5058void GeneratorCSharp::GenerateFlagsFieldModel(const std::string& domain, const std::shared_ptr<Package>& p, const std::shared_ptr<FlagsType>& f)
+
5059{
+
5060 // Generate namespace begin
+
5061 WriteLine();
+
5062 WriteLineIndent("namespace " + domain + *p->name + ".FBE {");
+
5063 Indent(1);
+
5064
+
5065 std::string code = R"CODE(
+
5066 using global::_DOMAIN__PACKAGE_;
+
5067
+
5068 // Fast Binary Encoding _FLAGS_NAME_ field model
+
5069 public class FieldModel_FLAGS_NAME_ : _DOMAIN_FBE.FieldModelValueType<_FLAGS_NAME_>
+
5070 {
+
5071 public FieldModel_FLAGS_NAME_(_DOMAIN_FBE.Buffer buffer, long offset) : base(buffer, offset) {}
+
5072
+
5073 // Get the field size
+
5074 public override long FBESize => _FLAGS_SIZE_;
+
5075
+
5076 // Clone the field model
+
5077 public override _DOMAIN_FBE.FieldModelValueType<_FLAGS_NAME_> Clone() { return new FieldModel_FLAGS_NAME_(_buffer, _offset); }
+
5078
+
5079 // Get the value
+
5080 public override void Get(out _FLAGS_NAME_ value) { Get(out value, _FLAGS_NAME_.Default); }
+
5081 public override void Get(out _FLAGS_NAME_ value, _FLAGS_NAME_ defaults)
+
5082 {
+
5083 if ((_buffer.Offset + FBEOffset + FBESize) > _buffer.Size)
+
5084 {
+
5085 value = defaults;
+
5086 return;
+
5087 }
+
5088
+
5089 value = new _FLAGS_NAME_((_FLAGS_TYPE_)_FLAGS_READ_(FBEOffset));
+
5090 }
+
5091
+
5092 // Set the value
+
5093 public override void Set(_FLAGS_NAME_ value)
+
5094 {
+
5095 Debug.Assert(((_buffer.Offset + FBEOffset + FBESize) <= _buffer.Size), "Model is broken!");
+
5096 if ((_buffer.Offset + FBEOffset + FBESize) > _buffer.Size)
+
5097 return;
+
5098
+
5099 Write(FBEOffset, value.Value);
+
5100 }
+
5101 }
+
5102)CODE";
+
5103
+
5104 std::string flags_type = (f->base && !f->base->empty()) ? *f->base : "int32";
+
5105 std::string flags_base_type = ConvertEnumType(flags_type);
+
5106
+
5107 // Prepare flags model template
+
5108 code = std::regex_replace(code, std::regex("_DOMAIN_"), domain);
+
5109 code = std::regex_replace(code, std::regex("_PACKAGE_"), *p->name);
+
5110 code = std::regex_replace(code, std::regex("_FLAGS_NAME_"), *f->name);
+
5111 code = std::regex_replace(code, std::regex("_FLAGS_TYPE_"), flags_base_type);
+
5112 code = std::regex_replace(code, std::regex("_FLAGS_SIZE_"), ConvertEnumSize(flags_type));
+
5113 code = std::regex_replace(code, std::regex("_FLAGS_READ_"), ConvertEnumRead(flags_type));
+
5114 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
5115
+
5116 // Generate flags model
+
5117 Write(code);
+
5118
+
5119 // Generate namespace end
+
5120 Indent(-1);
+
5121 WriteLine();
+
5122 WriteLineIndent("} // namespace " + domain + *p->name + ".FBE");
+
5123}
+
5124
+
5125void GeneratorCSharp::GenerateFlagsFinalModel(const std::string& domain, const std::shared_ptr<Package>& p, const std::shared_ptr<FlagsType>& f)
+
5126{
+
5127 // Generate namespace begin
+
5128 WriteLine();
+
5129 WriteLineIndent("namespace " + domain + *p->name + ".FBE {");
+
5130 Indent(1);
+
5131
+
5132 std::string code = R"CODE(
+
5133 using global::_DOMAIN__PACKAGE_;
+
5134
+
5135 // Fast Binary Encoding _FLAGS_NAME_ final model
+
5136 public class FinalModel_FLAGS_NAME_ : _DOMAIN_FBE.FinalModelValueType<_FLAGS_NAME_>
+
5137 {
+
5138 public FinalModel_FLAGS_NAME_(_DOMAIN_FBE.Buffer buffer, long offset) : base(buffer, offset) {}
+
5139
+
5140 // Get the allocation size
+
5141 public override long FBEAllocationSize(_FLAGS_NAME_ value) { return FBESize; }
+
5142
+
5143 // Get the final size
+
5144 public override long FBESize => _FLAGS_SIZE_;
+
5145
+
5146 // Clone the final model
+
5147 public override _DOMAIN_FBE.FinalModelValueType<_FLAGS_NAME_> Clone() { return new FinalModel_FLAGS_NAME_(_buffer, _offset); }
+
5148
+
5149 // Check if the value is valid
+
5150 public override long Verify()
+
5151 {
+
5152 if ((_buffer.Offset + FBEOffset + FBESize) > _buffer.Size)
+
5153 return long.MaxValue;
+
5154
+
5155 return FBESize;
+
5156 }
+
5157
+
5158 // Get the value
+
5159 public override long Get(out _FLAGS_NAME_ value)
+
5160 {
+
5161 if ((_buffer.Offset + FBEOffset + FBESize) > _buffer.Size)
+
5162 {
+
5163 value = _FLAGS_NAME_.Default;
+
5164 return 0;
+
5165 }
+
5166
+
5167 value = new _FLAGS_NAME_((_FLAGS_TYPE_)_FLAGS_READ_(FBEOffset));
+
5168 return FBESize;
+
5169 }
+
5170
+
5171 // Set the value
+
5172 public override long Set(_FLAGS_NAME_ value)
+
5173 {
+
5174 Debug.Assert(((_buffer.Offset + FBEOffset + FBESize) <= _buffer.Size), "Model is broken!");
+
5175 if ((_buffer.Offset + FBEOffset + FBESize) > _buffer.Size)
+
5176 return 0;
+
5177
+
5178 Write(FBEOffset, value.Value);
+
5179 return FBESize;
+
5180 }
+
5181 }
+
5182)CODE";
+
5183
+
5184 std::string flags_type = (f->base && !f->base->empty()) ? *f->base : "int32";
+
5185 std::string flags_base_type = ConvertEnumType(flags_type);
+
5186
+
5187 // Prepare flags model template
+
5188 code = std::regex_replace(code, std::regex("_DOMAIN_"), domain);
+
5189 code = std::regex_replace(code, std::regex("_PACKAGE_"), *p->name);
+
5190 code = std::regex_replace(code, std::regex("_FLAGS_NAME_"), *f->name);
+
5191 code = std::regex_replace(code, std::regex("_FLAGS_TYPE_"), flags_base_type);
+
5192 code = std::regex_replace(code, std::regex("_FLAGS_SIZE_"), ConvertEnumSize(flags_type));
+
5193 code = std::regex_replace(code, std::regex("_FLAGS_READ_"), ConvertEnumRead(flags_type));
+
5194 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
5195
+
5196 // Generate flags model
+
5197 Write(code);
+
5198
+
5199 // Generate namespace end
+
5200 Indent(-1);
+
5201 WriteLine();
+
5202 WriteLineIndent("} // namespace " + domain + *p->name + ".FBE");
+
5203}
+
5204
+
5205void GeneratorCSharp::GenerateStruct(const std::string& domain, const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s)
+
5206{
+
5207 // Generate namespace begin
+
5208 WriteLine();
+
5209 WriteLineIndent("namespace " + domain + *p->name + " {");
+
5210 Indent(1);
+
5211
+
5212 // Generate struct begin
+
5213 WriteLine();
+
5214 WriteIndent("public struct " + *s->name + " : IComparable, IComparable<" + *s->name + ">, IEquatable<" + *s->name + ">");
+
5215 WriteLine();
+
5216 WriteLineIndent("{");
+
5217 Indent(1);
+
5218
+
5219 // Generate struct body
+
5220 bool id = false;
+
5221 if (s->base && !s->base->empty())
+
5222 {
+
5223 if (JSON())
+
5224 {
+
5225 WriteLineIndent("#if UTF8JSON");
+
5226 WriteLineIndent("[IgnoreDataMember]");
+
5227 WriteLineIndent("#else");
+
5228 WriteLineIndent("[JsonIgnore]");
+
5229 WriteLineIndent("#endif");
+
5230 }
+
5231 WriteLineIndent("public " + ConvertTypeName(*s->base, false) + " parent;");
+
5232 if (s->message)
+
5233 {
+
5234 id = true;
+
5235 WriteLineIndent("public Guid id => parent.id;");
+
5236 }
+
5237 }
+
5238 if (s->body)
+
5239 {
+
5240 for (const auto& field : s->body->fields)
+
5241 {
+
5242 if (field->id)
+
5243 id = true;
+
5244 WriteLineIndent("public " + ConvertTypeName(*field) + " " + *field->name + ";");
+
5245 }
+
5246 }
+
5247 if (s->message && !id)
+
5248 WriteLineIndent("public Guid id => Guid.Empty;");
+
5249
+
5250 // Generate struct FBE type property
+
5251 WriteLine();
+
5252 if (s->base && !s->base->empty() && (s->type == 0))
+
5253 WriteLineIndent("public const long FBETypeConst = " + ConvertTypeName(*s->base, false) + ".FBETypeConst;");
+
5254 else
+
5255 WriteLineIndent("public const long FBETypeConst = " + std::to_string(s->type) + ";");
+
5256 if (JSON())
+
5257 {
+
5258 WriteLineIndent("#if UTF8JSON");
+
5259 WriteLineIndent("[IgnoreDataMember]");
+
5260 WriteLineIndent("#else");
+
5261 WriteLineIndent("[JsonIgnore]");
+
5262 WriteLineIndent("#endif");
+
5263 }
+
5264 WriteLineIndent("public long FBEType => FBETypeConst;");
+
5265
+
5266 // Generate struct initialization property
+
5267 WriteLine();
+
5268 WriteLineIndent("public static " + *s->name + " Default => new " + *s->name);
+
5269 WriteLineIndent("{");
+
5270 Indent(1);
+
5271 bool first = true;
+
5272 if (s->base && !s->base->empty())
+
5273 {
+
5274 WriteLineIndent(std::string(first ? "" : ", ") + "parent = " + ConvertTypeName(*s->base, false) + ".Default");
+
5275 first = false;
+
5276 }
+
5277 if (s->body)
+
5278 {
+
5279 for (const auto& field : s->body->fields)
+
5280 {
+
5281 WriteLineIndent(std::string(first ? "" : ", ") + *field->name + " = " + ConvertDefault(domain, *p->name, *field));
+
5282 first = false;
+
5283 }
+
5284 }
+
5285 Indent(-1);
+
5286 WriteLineIndent("};");
+
5287
+
5288 // Generate struct initialization constructor
+
5289 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
5290 {
+
5291 first = true;
+
5292 WriteLine();
+
5293 WriteIndent("public " + *s->name + "(");
+
5294 if (s->base && !s->base->empty())
+
5295 {
+
5296 Write(ConvertTypeName(*s->base, false) + " parent");
+
5297 first = false;
+
5298 }
+
5299 if (s->body)
+
5300 {
+
5301 for (const auto& field : s->body->fields)
+
5302 {
+
5303 Write(std::string(first ? "" : ", ") + ConvertTypeName(*field) + " " + *field->name);
+
5304 first = false;
+
5305 }
+
5306 }
+
5307 WriteLine(")");
+
5308 WriteLineIndent("{");
+
5309 Indent(1);
+
5310 if (s->base && !s->base->empty())
+
5311 WriteLineIndent("this.parent = parent;");
+
5312 if (s->body)
+
5313 for (const auto& field : s->body->fields)
+
5314 WriteLineIndent("this." + *field->name + " = " + *field->name + ";");
+
5315 Indent(-1);
+
5316 WriteLineIndent("}");
+
5317 }
+
5318
+
5319 // Generate struct Clone() method
+
5320 WriteLine();
+
5321 WriteLineIndent("public " + *s->name + " Clone()");
+
5322 WriteLineIndent("{");
+
5323 Indent(1);
+
5324 WriteLineIndent("// Serialize the struct to the FBE stream");
+
5325 WriteLineIndent("var writer = new " + domain + *p->name + ".FBE." + *s->name + "Model();");
+
5326 WriteLineIndent("writer.Serialize(this);");
+
5327 WriteLine();
+
5328 WriteLineIndent("// Deserialize the struct from the FBE stream");
+
5329 WriteLineIndent("var reader = new " + domain + *p->name + ".FBE." + *s->name + "Model();");
+
5330 WriteLineIndent("reader.Attach(writer.Buffer);");
+
5331 WriteLineIndent("reader.Deserialize(out var result);");
+
5332 WriteLineIndent("return result;");
+
5333 Indent(-1);
+
5334 WriteLineIndent("}");
+
5335
+
5336 // Generate struct CompareTo() methods
+
5337 WriteLine();
+
5338 WriteLineIndent("public int CompareTo(object other)");
+
5339 WriteLineIndent("{");
+
5340 Indent(1);
+
5341 WriteLineIndent("int result = 0;");
+
5342 if (s->base && !s->base->empty())
+
5343 {
+
5344 WriteLineIndent("result = parent.CompareTo(other);");
+
5345 WriteLineIndent("if (result != 0)");
+
5346 Indent(1);
+
5347 WriteLineIndent("return result;");
+
5348 Indent(-1);
+
5349 }
+
5350 if (s->body)
+
5351 {
+
5352 for (const auto& field : s->body->fields)
+
5353 {
+
5354 if (field->keys)
+
5355 {
+
5356 WriteLineIndent("result = " + *field->name + ".CompareTo(((" + *s->name + ")other)." + *field->name + ");");
+
5357 WriteLineIndent("if (result != 0)");
+
5358 Indent(1);
+
5359 WriteLineIndent("return result;");
+
5360 Indent(-1);
+
5361 }
+
5362 }
+
5363 }
+
5364 WriteLineIndent("return result;");
+
5365 Indent(-1);
+
5366 WriteLineIndent("}");
+
5367 WriteLine();
+
5368 WriteLineIndent("public int CompareTo(" + *s->name + " other)");
+
5369 WriteLineIndent("{");
+
5370 Indent(1);
+
5371 WriteLineIndent("int result = 0;");
+
5372 if (s->base && !s->base->empty())
+
5373 {
+
5374 WriteLineIndent("result = parent.CompareTo(other);");
+
5375 WriteLineIndent("if (result != 0)");
+
5376 Indent(1);
+
5377 WriteLineIndent("return result;");
+
5378 Indent(-1);
+
5379 }
+
5380 if (s->body)
+
5381 {
+
5382 for (const auto& field : s->body->fields)
+
5383 {
+
5384 if (field->keys)
+
5385 {
+
5386 WriteLineIndent("result = " + *field->name + ".CompareTo(other." + *field->name + ");");
+
5387 WriteLineIndent("if (result != 0)");
+
5388 Indent(1);
+
5389 WriteLineIndent("return result;");
+
5390 Indent(-1);
+
5391 }
+
5392 }
+
5393 }
+
5394 WriteLineIndent("return result;");
+
5395 Indent(-1);
+
5396 WriteLineIndent("}");
+
5397
+
5398 // Generate struct Equals() methods
+
5399 WriteLine();
+
5400 WriteLineIndent("public override bool Equals(object other)");
+
5401 WriteLineIndent("{");
+
5402 Indent(1);
+
5403 WriteLineIndent("if (!(other is " + *s->name + "))");
+
5404 Indent(1);
+
5405 WriteLineIndent("return false;");
+
5406 Indent(-1);
+
5407 if (s->base && !s->base->empty())
+
5408 {
+
5409 WriteLineIndent("if (!parent.Equals(other))");
+
5410 Indent(1);
+
5411 WriteLineIndent("return false;");
+
5412 Indent(-1);
+
5413 }
+
5414 if (s->body)
+
5415 {
+
5416 for (const auto& field : s->body->fields)
+
5417 {
+
5418 if (field->keys)
+
5419 {
+
5420 WriteLineIndent("if (!" + *field->name + ".Equals(((" + *s->name + ")other)." + *field->name + "))");
+
5421 Indent(1);
+
5422 WriteLineIndent("return false;");
+
5423 Indent(-1);
+
5424 }
+
5425 }
+
5426 }
+
5427 WriteLineIndent("return true;");
+
5428 Indent(-1);
+
5429 WriteLineIndent("}");
+
5430 WriteLine();
+
5431 WriteLineIndent("public bool Equals(" + *s->name + " other)");
+
5432 WriteLineIndent("{");
+
5433 Indent(1);
+
5434 if (s->base && !s->base->empty())
+
5435 {
+
5436 WriteLineIndent("if (!parent.Equals(other))");
+
5437 Indent(1);
+
5438 WriteLineIndent("return false;");
+
5439 Indent(-1);
+
5440 }
+
5441 if (s->body)
+
5442 {
+
5443 for (const auto& field : s->body->fields)
+
5444 {
+
5445 if (field->keys)
+
5446 {
+
5447 WriteLineIndent("if (!" + *field->name + ".Equals(other." + *field->name + "))");
+
5448 Indent(1);
+
5449 WriteLineIndent("return false;");
+
5450 Indent(-1);
+
5451 }
+
5452 }
+
5453 }
+
5454 WriteLineIndent("return true;");
+
5455 Indent(-1);
+
5456 WriteLineIndent("}");
+
5457
+
5458 // Generate struct GetHashCode() method
+
5459 WriteLine();
+
5460 WriteLineIndent("public override int GetHashCode()");
+
5461 WriteLineIndent("{");
+
5462 Indent(1);
+
5463 WriteLineIndent("int hash = 17;");
+
5464 if (s->base && !s->base->empty())
+
5465 WriteLineIndent("hash = hash * 31 + parent.GetHashCode();");
+
5466 if (s->body)
+
5467 for (const auto& field : s->body->fields)
+
5468 if (field->keys)
+
5469 WriteLineIndent("hash = hash * 31 + " + *field->name + ".GetHashCode();");
+
5470 WriteLineIndent("return hash;");
+
5471 Indent(-1);
+
5472 WriteLineIndent("}");
+
5473
+
5474 // Generate struct operator== and operator!=
+
5475 WriteLine();
+
5476 WriteLineIndent("public static bool operator==(" + *s->name + " lhs, " + *s->name + " rhs) => lhs.Equals(rhs);");
+
5477 WriteLineIndent("public static bool operator!=(" + *s->name + " lhs, " + *s->name + " rhs) => !(lhs == rhs);");
+
5478
+
5479 // Generate struct ToString() method
+
5480 WriteLine();
+
5481 WriteLineIndent("public override string ToString()");
+
5482 WriteLineIndent("{");
+
5483 Indent(1);
+
5484 WriteLineIndent("var sb = new StringBuilder();");
+
5485 WriteLineIndent("sb.Append(\"" + *s->name + "(\");");
+
5486 first = true;
+
5487 if (s->base && !s->base->empty())
+
5488 {
+
5489 WriteLineIndent("sb.Append(parent.ToString());");
+
5490 first = false;
+
5491 }
+
5492 if (s->body)
+
5493 {
+
5494 for (const auto& field : s->body->fields)
+
5495 {
+
5496 if (field->attributes && field->attributes->hidden)
+
5497 WriteLineIndent("sb.Append(\"" + std::string(first ? "" : ",") + *field->name + "=***\");");
+
5498 else if (field->array)
+
5499 {
+
5500 WriteLineIndent("if (" + *field->name + " != null)");
+
5501 WriteLineIndent("{");
+
5502 Indent(1);
+
5503 WriteLineIndent("bool first = true;");
+
5504 WriteLineIndent("sb.Append(\"" + std::string(first ? "" : ",") + *field->name + "=[\").Append(" + *field->name + ".Length" + ").Append(\"][\");");
+
5505 WriteLineIndent("foreach (var item in " + *field->name + ")");
+
5506 WriteLineIndent("{");
+
5507 Indent(1);
+
5508 WriteLineIndent(ConvertOutputStreamValue(*field->type, "item", field->optional, true));
+
5509 WriteLineIndent("first = false;");
+
5510 Indent(-1);
+
5511 WriteLineIndent("}");
+
5512 WriteLineIndent("sb.Append(\"]\");");
+
5513 Indent(-1);
+
5514 WriteLineIndent("}");
+
5515 WriteLineIndent("else");
+
5516 WriteLineIndent("{");
+
5517 Indent(1);
+
5518 WriteLineIndent("sb.Append(\"" + std::string(first ? "" : ",") + *field->name + "=[0][]\");");
+
5519 Indent(-1);
+
5520 WriteLineIndent("}");
+
5521 }
+
5522 else if (field->vector)
+
5523 {
+
5524 WriteLineIndent("if (" + *field->name + " != null)");
+
5525 WriteLineIndent("{");
+
5526 Indent(1);
+
5527 WriteLineIndent("bool first = true;");
+
5528 WriteLineIndent("sb.Append(\"" + std::string(first ? "" : ",") + *field->name + "=[\").Append(" + *field->name + ".Count" + ").Append(\"][\");");
+
5529 WriteLineIndent("foreach (var item in " + *field->name + ")");
+
5530 WriteLineIndent("{");
+
5531 Indent(1);
+
5532 WriteLineIndent(ConvertOutputStreamValue(*field->type, "item", field->optional, true));
+
5533 WriteLineIndent("first = false;");
+
5534 Indent(-1);
+
5535 WriteLineIndent("}");
+
5536 WriteLineIndent("sb.Append(\"]\");");
+
5537 Indent(-1);
+
5538 WriteLineIndent("}");
+
5539 WriteLineIndent("else");
+
5540 WriteLineIndent("{");
+
5541 Indent(1);
+
5542 WriteLineIndent("sb.Append(\"" + std::string(first ? "" : ",") + *field->name + "=[0][]\");");
+
5543 Indent(-1);
+
5544 WriteLineIndent("}");
+
5545 }
+
5546 else if (field->list)
+
5547 {
+
5548 WriteLineIndent("if (" + *field->name + " != null)");
+
5549 WriteLineIndent("{");
+
5550 Indent(1);
+
5551 WriteLineIndent("bool first = true;");
+
5552 WriteLineIndent("sb.Append(\"" + std::string(first ? "" : ",") + *field->name + "=[\").Append(" + *field->name + ".Count" + ").Append(\"]<\");");
+
5553 WriteLineIndent("foreach (var item in " + *field->name + ")");
+
5554 WriteLineIndent("{");
+
5555 Indent(1);
+
5556 WriteLineIndent(ConvertOutputStreamValue(*field->type, "item", field->optional, true));
+
5557 WriteLineIndent("first = false;");
+
5558 Indent(-1);
+
5559 WriteLineIndent("}");
+
5560 WriteLineIndent("sb.Append(\">\");");
+
5561 Indent(-1);
+
5562 WriteLineIndent("}");
+
5563 WriteLineIndent("else");
+
5564 WriteLineIndent("{");
+
5565 Indent(1);
+
5566 WriteLineIndent("sb.Append(\"" + std::string(first ? "" : ",") + *field->name + "=[0]<>\");");
+
5567 Indent(-1);
+
5568 WriteLineIndent("}");
+
5569 }
+
5570 else if (field->set)
+
5571 {
+
5572 WriteLineIndent("if (" + *field->name + " != null)");
+
5573 WriteLineIndent("{");
+
5574 Indent(1);
+
5575 WriteLineIndent("bool first = true;");
+
5576 WriteLineIndent("sb.Append(\"" + std::string(first ? "" : ",") + *field->name + "=[\").Append(" + *field->name + ".Count" + ").Append(\"]{\");");
+
5577 WriteLineIndent("foreach (var item in " + *field->name + ")");
+
5578 WriteLineIndent("{");
+
5579 Indent(1);
+
5580 WriteLineIndent(ConvertOutputStreamValue(*field->type, "item", field->optional, true));
+
5581 WriteLineIndent("first = false;");
+
5582 Indent(-1);
+
5583 WriteLineIndent("}");
+
5584 WriteLineIndent("sb.Append(\"}\");");
+
5585 Indent(-1);
+
5586 WriteLineIndent("}");
+
5587 WriteLineIndent("else");
+
5588 WriteLineIndent("{");
+
5589 Indent(1);
+
5590 WriteLineIndent("sb.Append(\"" + std::string(first ? "" : ",") + *field->name + "=[0]{}\");");
+
5591 Indent(-1);
+
5592 WriteLineIndent("}");
+
5593 }
+
5594 else if (field->map)
+
5595 {
+
5596 WriteLineIndent("if (" + *field->name + " != null)");
+
5597 WriteLineIndent("{");
+
5598 Indent(1);
+
5599 WriteLineIndent("bool first = true;");
+
5600 WriteLineIndent("sb.Append(\"" + std::string(first ? "" : ",") + *field->name + "=[\").Append(" + *field->name + ".Count" + ").Append(\"]<{\");");
+
5601 WriteLineIndent("foreach (var item in " + *field->name + ")");
+
5602 WriteLineIndent("{");
+
5603 Indent(1);
+
5604 WriteLineIndent(ConvertOutputStreamValue(*field->key, "item.Key", false, true));
+
5605 WriteLineIndent("sb.Append(\"->\");");
+
5606 WriteLineIndent(ConvertOutputStreamValue(*field->type, "item.Value", field->optional, false));
+
5607 WriteLineIndent("first = false;");
+
5608 Indent(-1);
+
5609 WriteLineIndent("}");
+
5610 WriteLineIndent("sb.Append(\"}>\");");
+
5611 Indent(-1);
+
5612 WriteLineIndent("}");
+
5613 WriteLineIndent("else");
+
5614 WriteLineIndent("{");
+
5615 Indent(1);
+
5616 WriteLineIndent("sb.Append(\"" + std::string(first ? "" : ",") + *field->name + "=[0]<{}>\");");
+
5617 Indent(-1);
+
5618 WriteLineIndent("}");
+
5619 }
+
5620 else if (field->hash)
+
5621 {
+
5622 WriteLineIndent("if (" + *field->name + " != null)");
+
5623 WriteLineIndent("{");
+
5624 Indent(1);
+
5625 WriteLineIndent("bool first = true;");
+
5626 WriteLineIndent("sb.Append(\"" + std::string(first ? "" : ",") + *field->name + "=[\").Append(" + *field->name + ".Count" + ").Append(\"][{\");");
+
5627 WriteLineIndent("foreach (var item in " + *field->name + ")");
+
5628 WriteLineIndent("{");
+
5629 Indent(1);
+
5630 WriteLineIndent(ConvertOutputStreamValue(*field->key, "item.Key", false, true));
+
5631 WriteLineIndent("sb.Append(\"->\");");
+
5632 WriteLineIndent(ConvertOutputStreamValue(*field->type, "item.Value", field->optional, false));
+
5633 WriteLineIndent("first = false;");
+
5634 Indent(-1);
+
5635 WriteLineIndent("}");
+
5636 WriteLineIndent("sb.Append(\"}]\");");
+
5637 Indent(-1);
+
5638 WriteLineIndent("}");
+
5639 WriteLineIndent("else");
+
5640 WriteLineIndent("{");
+
5641 Indent(1);
+
5642 WriteLineIndent("sb.Append(\"" + std::string(first ? "" : ",") + *field->name + "=[0][{}]\");");
+
5643 Indent(-1);
+
5644 WriteLineIndent("}");
+
5645 }
+
5646 else
+
5647 WriteLineIndent("sb.Append(\"" + std::string(first ? "" : ",") + *field->name + "=\"); " + ConvertOutputStreamValue(*field->type, *field->name, field->optional, false));
+
5648 first = false;
+
5649 }
+
5650 }
+
5651 WriteLineIndent("sb.Append(\")\");");
+
5652 WriteLineIndent("return sb.ToString();");
+
5653 Indent(-1);
+
5654 WriteLineIndent("}");
+
5655
+
5656 // Generate struct JSON methods
+
5657 if (JSON())
+
5658 {
+
5659 WriteLine();
+
5660 WriteLineIndent("public string ToJson()");
+
5661 WriteLineIndent("{");
+
5662 Indent(1);
+
5663 WriteLineIndent("var json = " + domain + "FBE.Json.ToJson(this);");
+
5664 if (s->base && !s->base->empty())
+
5665 {
+
5666 WriteLineIndent("var jsonParent = parent.ToJson();");
+
5667 WriteLineIndent("json = json.Substring(0, json.Length - 1) + \",\" + jsonParent.Substring(1, jsonParent.Length - 2) + \"}\";");
+
5668 }
+
5669 WriteLineIndent("return json;");
+
5670 Indent(-1);
+
5671 WriteLineIndent("}");
+
5672 WriteLine();
+
5673 WriteLineIndent("public static " + *s->name + " FromJson(string json)");
+
5674 WriteLineIndent("{");
+
5675 Indent(1);
+
5676 WriteLineIndent("var result = " + domain + "FBE.Json.FromJson<" + *s->name + ">(json);");
+
5677 if (s->base && !s->base->empty())
+
5678 WriteLineIndent("result.parent = " + ConvertTypeName(*s->base, false) + ".FromJson(json);");
+
5679 WriteLineIndent("return result;");
+
5680 Indent(-1);
+
5681 WriteLineIndent("}");
+
5682 }
+
5683
+
5684 // Generate struct CreateFieldModel() method
+
5685 WriteLine();
+
5686 WriteLineIndent("public static " + domain + "FBE.FieldModelValueType<" + *s->name + "> CreateFieldModel(" + domain + "FBE.Buffer buffer, long offset) { return new " + *p->name + ".FBE.FieldModel" + *s->name + "(buffer, offset); }");
+
5687
+
5688 // Generate struct end
+
5689 Indent(-1);
+
5690 WriteLineIndent("}");
+
5691
+
5692 // Generate namespace end
+
5693 Indent(-1);
+
5694 WriteLine();
+
5695 WriteLineIndent("} // namespace " + domain + *p->name);
+
5696
+
5697 // Generate struct field models
+
5698 GenerateStructFieldModel(domain, p, s);
+
5699 GenerateStructModel(domain, p, s);
+
5700
+
5701 // Generate struct final models
+
5702 if (Final())
+
5703 {
+
5704 GenerateStructFinalModel(domain, p, s);
+
5705 GenerateStructModelFinal(domain, p, s);
+
5706 }
+
5707}
+
5708
+
5709void GeneratorCSharp::GenerateStructFieldModel(const std::string& domain, const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s)
+
5710{
+
5711 // Generate namespace begin
+
5712 WriteLine();
+
5713 WriteLineIndent("namespace " + domain + *p->name + ".FBE {");
+
5714 Indent(1);
+
5715
+
5716 // Generate using package
+
5717 WriteLine();
+
5718 WriteLineIndent("using global::" + domain + *p->name + ";");
+
5719
+
5720 // Generate struct field model begin
+
5721 WriteLine();
+
5722 WriteLineIndent("// Fast Binary Encoding " + *s->name + " field model");
+
5723 WriteLineIndent("public class FieldModel" + *s->name + " : " + domain + "FBE.FieldModelValueType<" + *s->name + ">");
+
5724 WriteLineIndent("{");
+
5725 Indent(1);
+
5726
+
5727 // Generate struct field model accessors
+
5728 if (s->base && !s->base->empty())
+
5729 WriteLineIndent("public readonly " + ConvertTypeFieldName(domain, *p->name, *s->base, false) + " parent;");
+
5730 if (s->body)
+
5731 for (const auto& field : s->body->fields)
+
5732 WriteLineIndent("public readonly " + ConvertTypeFieldDeclaration(domain, *p->name, *field, false) + " " + *field->name + ";");
+
5733
+
5734 // Generate struct field model constructor
+
5735 WriteLine();
+
5736 WriteLineIndent("public FieldModel" + *s->name + "(" + domain + "FBE.Buffer buffer, long offset) : base(buffer, offset)");
+
5737 WriteLineIndent("{");
+
5738 Indent(1);
+
5739 std::string prev_offset("4");
+
5740 std::string prev_size("4");
+
5741 if (s->base && !s->base->empty())
+
5742 {
+
5743 WriteLineIndent("parent = new " + ConvertTypeFieldName(domain, *p->name, *s->base, false) + "(buffer, " + prev_offset + " + " + prev_size + ");");
+
5744 prev_offset = "parent.FBEOffset";
+
5745 prev_size = "parent.FBEBody - 4 - 4";
+
5746 }
+
5747 if (s->body)
+
5748 {
+
5749 for (const auto& field : s->body->fields)
+
5750 {
+
5751 WriteLineIndent(*field->name + " = " + ConvertTypeFieldInitialization(domain, *p->name, *field, prev_offset + " + " + prev_size, false) + ";");
+
5752 prev_offset = *field->name + ".FBEOffset";
+
5753 prev_size = *field->name + ".FBESize";
+
5754 }
+
5755 }
+
5756 Indent(-1);
+
5757 WriteLineIndent("}");
+
5758
+
5759 // Generate struct field model FBE properties
+
5760 WriteLine();
+
5761 WriteLineIndent("// Get the field size");
+
5762 WriteLineIndent("public override long FBESize => 4;");
+
5763 WriteLineIndent("// Get the field body size");
+
5764 WriteLineIndent("public long FBEBody");
+
5765 WriteLineIndent("{");
+
5766 Indent(1);
+
5767 WriteLineIndent("get");
+
5768 WriteLineIndent("{");
+
5769 Indent(1);
+
5770 WriteLineIndent("long fbeResult = 4 + 4");
+
5771 Indent(1);
+
5772 if (s->base && !s->base->empty())
+
5773 WriteLineIndent("+ parent.FBEBody - 4 - 4");
+
5774 if (s->body)
+
5775 for (const auto& field : s->body->fields)
+
5776 WriteLineIndent("+ " + *field->name + ".FBESize");
+
5777 WriteLineIndent(";");
+
5778 Indent(-1);
+
5779 WriteLineIndent("return fbeResult;");
+
5780 Indent(-1);
+
5781 WriteLineIndent("}");
+
5782 Indent(-1);
+
5783 WriteLineIndent("}");
+
5784 WriteLineIndent("// Get the field extra size");
+
5785 WriteLineIndent("public override long FBEExtra");
+
5786 WriteLineIndent("{");
+
5787 Indent(1);
+
5788 WriteLineIndent("get");
+
5789 WriteLineIndent("{");
+
5790 Indent(1);
+
5791 WriteLineIndent("if ((_buffer.Offset + FBEOffset + FBESize) > _buffer.Size)");
+
5792 Indent(1);
+
5793 WriteLineIndent("return 0;");
+
5794 Indent(-1);
+
5795 WriteLine();
+
5796 WriteLineIndent("uint fbeStructOffset = ReadUInt32(FBEOffset);");
+
5797 WriteLineIndent("if ((fbeStructOffset == 0) || ((_buffer.Offset + fbeStructOffset + 4) > _buffer.Size))");
+
5798 Indent(1);
+
5799 WriteLineIndent("return 0;");
+
5800 Indent(-1);
+
5801 WriteLine();
+
5802 WriteLineIndent("_buffer.Shift(fbeStructOffset);");
+
5803 WriteLine();
+
5804 WriteLineIndent("long fbeResult = FBEBody");
+
5805 Indent(1);
+
5806 if (s->base && !s->base->empty())
+
5807 WriteLineIndent("+ parent.FBEExtra");
+
5808 if (s->body)
+
5809 for (const auto& field : s->body->fields)
+
5810 WriteLineIndent("+ " + *field->name + ".FBEExtra");
+
5811 WriteLineIndent(";");
+
5812 Indent(-1);
+
5813 WriteLine();
+
5814 WriteLineIndent("_buffer.Unshift(fbeStructOffset);");
+
5815 WriteLine();
+
5816 WriteLineIndent("return fbeResult;");
+
5817 Indent(-1);
+
5818 WriteLineIndent("}");
+
5819 Indent(-1);
+
5820 WriteLineIndent("}");
+
5821 WriteLineIndent("// Get the field type");
+
5822 if (s->base && !s->base->empty() && (s->type == 0))
+
5823 WriteLineIndent("public const long FBETypeConst = " + ConvertTypeFieldName(domain, *p->name, *s->base, false) + ".FBETypeConst;");
+
5824 else
+
5825 WriteLineIndent("public const long FBETypeConst = " + std::to_string(s->type) + ";");
+
5826 WriteLineIndent("public long FBEType => FBETypeConst;");
+
5827
+
5828 // Generate struct field model Clone() method
+
5829 WriteLine();
+
5830 WriteLineIndent("// Clone the field model");
+
5831 WriteLineIndent("public override " + domain + "FBE.FieldModelValueType<" + *s->name + "> Clone() { return new FieldModel" + *s->name + "(_buffer, _offset); }");
+
5832
+
5833 // Generate struct field model Verify() methods
+
5834 WriteLine();
+
5835 WriteLineIndent("// Check if the struct value is valid");
+
5836 WriteLineIndent("public override bool Verify() { return Verify(true); }");
+
5837 WriteLineIndent("public bool Verify(bool fbeVerifyType)");
+
5838 WriteLineIndent("{");
+
5839 Indent(1);
+
5840 WriteLineIndent("if ((_buffer.Offset + FBEOffset + FBESize) > _buffer.Size)");
+
5841 Indent(1);
+
5842 WriteLineIndent("return true;");
+
5843 Indent(-1);
+
5844 WriteLine();
+
5845 WriteLineIndent("uint fbeStructOffset = ReadUInt32(FBEOffset);");
+
5846 WriteLineIndent("if ((fbeStructOffset == 0) || ((_buffer.Offset + fbeStructOffset + 4 + 4) > _buffer.Size))");
+
5847 Indent(1);
+
5848 WriteLineIndent("return false;");
+
5849 Indent(-1);
+
5850 WriteLine();
+
5851 WriteLineIndent("uint fbeStructSize = ReadUInt32(fbeStructOffset);");
+
5852 WriteLineIndent("if (fbeStructSize < (4 + 4))");
+
5853 Indent(1);
+
5854 WriteLineIndent("return false;");
+
5855 Indent(-1);
+
5856 WriteLine();
+
5857 WriteLineIndent("uint fbeStructType = ReadUInt32(fbeStructOffset + 4);");
+
5858 WriteLineIndent("if (fbeVerifyType && (fbeStructType != FBEType))");
+
5859 Indent(1);
+
5860 WriteLineIndent("return false;");
+
5861 Indent(-1);
+
5862 WriteLine();
+
5863 WriteLineIndent("_buffer.Shift(fbeStructOffset);");
+
5864 WriteLineIndent("bool fbeResult = VerifyFields(fbeStructSize);");
+
5865 WriteLineIndent("_buffer.Unshift(fbeStructOffset);");
+
5866 WriteLineIndent("return fbeResult;");
+
5867 Indent(-1);
+
5868 WriteLineIndent("}");
+
5869
+
5870 // Generate struct field model VerifyFields() method
+
5871 WriteLine();
+
5872 WriteLineIndent("// Check if the struct fields are valid");
+
5873 WriteLineIndent("public bool VerifyFields(long fbeStructSize)");
+
5874 WriteLineIndent("{");
+
5875 Indent(1);
+
5876 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
5877 {
+
5878 WriteLineIndent("long fbeCurrentSize = 4 + 4;");
+
5879 if (s->base && !s->base->empty())
+
5880 {
+
5881 WriteLine();
+
5882 WriteLineIndent("if ((fbeCurrentSize + parent.FBEBody - 4 - 4) > fbeStructSize)");
+
5883 Indent(1);
+
5884 WriteLineIndent("return true;");
+
5885 Indent(-1);
+
5886 WriteLineIndent("if (!parent.VerifyFields(fbeStructSize))");
+
5887 Indent(1);
+
5888 WriteLineIndent("return false;");
+
5889 Indent(-1);
+
5890 WriteLineIndent("fbeCurrentSize += parent.FBEBody - 4 - 4;");
+
5891 }
+
5892 if (s->body)
+
5893 {
+
5894 for (const auto& field : s->body->fields)
+
5895 {
+
5896 WriteLine();
+
5897 WriteLineIndent("if ((fbeCurrentSize + " + *field->name + ".FBESize) > fbeStructSize)");
+
5898 Indent(1);
+
5899 WriteLineIndent("return true;");
+
5900 Indent(-1);
+
5901 WriteLineIndent("if (!" + *field->name + ".Verify())");
+
5902 Indent(1);
+
5903 WriteLineIndent("return false;");
+
5904 Indent(-1);
+
5905 WriteLineIndent("fbeCurrentSize += " + *field->name + ".FBESize;");
+
5906 }
+
5907 }
+
5908 WriteLine();
+
5909 }
+
5910 WriteLineIndent("return true;");
+
5911 Indent(-1);
+
5912 WriteLineIndent("}");
+
5913
+
5914 // Generate struct field model GetBegin() method
+
5915 WriteLine();
+
5916 WriteLineIndent("// Get the struct value (begin phase)");
+
5917 WriteLineIndent("public long GetBegin()");
+
5918 WriteLineIndent("{");
+
5919 Indent(1);
+
5920 WriteLineIndent("if ((_buffer.Offset + FBEOffset + FBESize) > _buffer.Size)");
+
5921 Indent(1);
+
5922 WriteLineIndent("return 0;");
+
5923 Indent(-1);
+
5924 WriteLine();
+
5925 WriteLineIndent("uint fbeStructOffset = ReadUInt32(FBEOffset);");
+
5926 WriteLineIndent("Debug.Assert(((fbeStructOffset > 0) && ((_buffer.Offset + fbeStructOffset + 4 + 4) <= _buffer.Size)), \"Model is broken!\");");
+
5927 WriteLineIndent("if ((fbeStructOffset == 0) || ((_buffer.Offset + fbeStructOffset + 4 + 4) > _buffer.Size))");
+
5928 Indent(1);
+
5929 WriteLineIndent("return 0;");
+
5930 Indent(-1);
+
5931 WriteLine();
+
5932 WriteLineIndent("uint fbeStructSize = ReadUInt32(fbeStructOffset);");
+
5933 WriteLineIndent("Debug.Assert((fbeStructSize >= (4 + 4)), \"Model is broken!\");");
+
5934 WriteLineIndent("if (fbeStructSize < (4 + 4))");
+
5935 Indent(1);
+
5936 WriteLineIndent("return 0;");
+
5937 Indent(-1);
+
5938 WriteLine();
+
5939 WriteLineIndent("_buffer.Shift(fbeStructOffset);");
+
5940 WriteLineIndent("return fbeStructOffset;");
+
5941 Indent(-1);
+
5942 WriteLineIndent("}");
+
5943
+
5944 // Generate struct field model GetEnd() method
+
5945 WriteLine();
+
5946 WriteLineIndent("// Get the struct value (end phase)");
+
5947 WriteLineIndent("public void GetEnd(long fbeBegin)");
+
5948 WriteLineIndent("{");
+
5949 Indent(1);
+
5950 WriteLineIndent("_buffer.Unshift(fbeBegin);");
+
5951 Indent(-1);
+
5952 WriteLineIndent("}");
+
5953
+
5954 // Generate struct field model Get() methods
+
5955 WriteLine();
+
5956 WriteLineIndent("// Get the struct value");
+
5957 WriteLineIndent("public override void Get(out " + *s->name + " fbeValue) { Get(out fbeValue, " + *s->name + ".Default); }");
+
5958 WriteLineIndent("public override void Get(out " + *s->name + " fbeValue, " + *s->name + " defaults)");
+
5959 WriteLineIndent("{");
+
5960 Indent(1);
+
5961 WriteLineIndent("long fbeBegin = GetBegin();");
+
5962 WriteLineIndent("if (fbeBegin == 0)");
+
5963 WriteLineIndent("{");
+
5964 Indent(1);
+
5965 WriteLineIndent("fbeValue = defaults;");
+
5966 WriteLineIndent("return;");
+
5967 Indent(-1);
+
5968 WriteLineIndent("}");
+
5969 WriteLine();
+
5970 WriteLineIndent("uint fbeStructSize = ReadUInt32(0);");
+
5971 WriteLineIndent("GetFields(out fbeValue, fbeStructSize);");
+
5972 WriteLineIndent("GetEnd(fbeBegin);");
+
5973 Indent(-1);
+
5974 WriteLineIndent("}");
+
5975
+
5976 // Generate struct field model GetFields() method
+
5977 WriteLine();
+
5978 WriteLineIndent("// Get the struct fields values");
+
5979 WriteLineIndent("public void GetFields(out " + *s->name + " fbeValue, long fbeStructSize)");
+
5980 WriteLineIndent("{");
+
5981 Indent(1);
+
5982 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
5983 {
+
5984 WriteLineIndent("long fbeCurrentSize = 4 + 4;");
+
5985 WriteLine();
+
5986 WriteLineIndent("fbeValue = " + *s->name + ".Default;");
+
5987 if (s->base && !s->base->empty())
+
5988 {
+
5989 WriteLine();
+
5990 WriteLineIndent("if ((fbeCurrentSize + parent.FBEBody - 4 - 4) <= fbeStructSize)");
+
5991 Indent(1);
+
5992 WriteLineIndent("parent.GetFields(out fbeValue.parent, fbeStructSize);");
+
5993 Indent(-1);
+
5994 WriteLineIndent("fbeCurrentSize += parent.FBEBody - 4 - 4;");
+
5995 }
+
5996 if (s->body)
+
5997 {
+
5998 for (const auto& field : s->body->fields)
+
5999 {
+
6000 WriteLine();
+
6001 WriteLineIndent("if ((fbeCurrentSize + " + *field->name + ".FBESize) <= fbeStructSize)");
+
6002 Indent(1);
+
6003 if (field->array || field->vector || field->list || field->set || field->map || field->hash)
+
6004 WriteLineIndent(*field->name + ".Get(ref fbeValue." + *field->name + ");");
+
6005 else
+
6006 WriteLineIndent(*field->name + ".Get(out fbeValue." + *field->name + (field->value ? (", " + ConvertConstant(domain, *p->name, *field->type, *field->value, field->optional)) : "") + ");");
+
6007 Indent(-1);
+
6008 WriteLineIndent("else");
+
6009 Indent(1);
+
6010 if (field->vector || field->list || field->set || field->map || field->hash)
+
6011 WriteLineIndent("fbeValue." + *field->name + ".Clear();");
+
6012 else
+
6013 WriteLineIndent("fbeValue." + *field->name + " = " + ConvertDefault(domain, *p->name, *field) + ";");
+
6014 Indent(-1);
+
6015 WriteLineIndent("fbeCurrentSize += " + *field->name + ".FBESize;");
+
6016 }
+
6017 }
+
6018 }
+
6019 Indent(-1);
+
6020 WriteLineIndent("}");
+
6021
+
6022 // Generate struct field model SetBegin() method
+
6023 WriteLine();
+
6024 WriteLineIndent("// Set the struct value (begin phase)");
+
6025 WriteLineIndent("public long SetBegin()");
+
6026 WriteLineIndent("{");
+
6027 Indent(1);
+
6028 WriteLineIndent("Debug.Assert(((_buffer.Offset + FBEOffset + FBESize) <= _buffer.Size), \"Model is broken!\");");
+
6029 WriteLineIndent("if ((_buffer.Offset + FBEOffset + FBESize) > _buffer.Size)");
+
6030 Indent(1);
+
6031 WriteLineIndent("return 0;");
+
6032 Indent(-1);
+
6033 WriteLine();
+
6034 WriteLineIndent("uint fbeStructSize = (uint)FBEBody;");
+
6035 WriteLineIndent("uint fbeStructOffset = (uint)(_buffer.Allocate(fbeStructSize) - _buffer.Offset);");
+
6036 WriteLineIndent("Debug.Assert(((fbeStructOffset > 0) && ((_buffer.Offset + fbeStructOffset + fbeStructSize) <= _buffer.Size)), \"Model is broken!\");");
+
6037 WriteLineIndent("if ((fbeStructOffset == 0) || ((_buffer.Offset + fbeStructOffset + fbeStructSize) > _buffer.Size))");
+
6038 Indent(1);
+
6039 WriteLineIndent("return 0;");
+
6040 Indent(-1);
+
6041 WriteLine();
+
6042 WriteLineIndent("Write(FBEOffset, fbeStructOffset);");
+
6043 WriteLineIndent("Write(fbeStructOffset, fbeStructSize);");
+
6044 WriteLineIndent("Write(fbeStructOffset + 4, (uint)FBEType);");
+
6045 WriteLine();
+
6046 WriteLineIndent("_buffer.Shift(fbeStructOffset);");
+
6047 WriteLineIndent("return fbeStructOffset;");
+
6048 Indent(-1);
+
6049 WriteLineIndent("}");
+
6050
+
6051 // Generate struct field model SetEnd() method
+
6052 WriteLine();
+
6053 WriteLineIndent("// Set the struct value (end phase)");
+
6054 WriteLineIndent("public void SetEnd(long fbeBegin)");
+
6055 WriteLineIndent("{");
+
6056 Indent(1);
+
6057 WriteLineIndent("_buffer.Unshift(fbeBegin);");
+
6058 Indent(-1);
+
6059 WriteLineIndent("}");
+
6060
+
6061 // Generate struct field model Set() method
+
6062 WriteLine();
+
6063 WriteLineIndent("// Set the struct value");
+
6064 WriteLineIndent("public override void Set(" + *s->name + " fbeValue)");
+
6065 WriteLineIndent("{");
+
6066 Indent(1);
+
6067 WriteLineIndent("long fbeBegin = SetBegin();");
+
6068 WriteLineIndent("if (fbeBegin == 0)");
+
6069 Indent(1);
+
6070 WriteLineIndent("return;");
+
6071 Indent(-1);
+
6072 WriteLine();
+
6073 WriteLineIndent("SetFields(fbeValue);");
+
6074 WriteLineIndent("SetEnd(fbeBegin);");
+
6075 Indent(-1);
+
6076 WriteLineIndent("}");
+
6077
+
6078 // Generate struct field model SetFields() method
+
6079 WriteLine();
+
6080 WriteLineIndent("// Set the struct fields values");
+
6081 WriteLineIndent("public void SetFields(" + *s->name + " fbeValue)");
+
6082 WriteLineIndent("{");
+
6083 Indent(1);
+
6084 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
6085 {
+
6086 if (s->base && !s->base->empty())
+
6087 WriteLineIndent("parent.SetFields(fbeValue.parent);");
+
6088 if (s->body)
+
6089 for (const auto& field : s->body->fields)
+
6090 WriteLineIndent(*field->name + ".Set(fbeValue." + *field->name + ");");
+
6091 }
+
6092 Indent(-1);
+
6093 WriteLineIndent("}");
+
6094
+
6095 // Generate struct field model end
+
6096 Indent(-1);
+
6097 WriteLineIndent("}");
+
6098
+
6099 // Generate namespace end
+
6100 Indent(-1);
+
6101 WriteLine();
+
6102 WriteLineIndent("} // namespace " + domain + *p->name + ".FBE");
+
6103}
+
6104
+
6105void GeneratorCSharp::GenerateStructModel(const std::string& domain, const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s)
+
6106{
+
6107 // Generate namespace begin
+
6108 WriteLine();
+
6109 WriteLineIndent("namespace " + domain + *p->name + ".FBE {");
+
6110 Indent(1);
+
6111
+
6112 // Generate using package
+
6113 WriteLine();
+
6114 WriteLineIndent("using global::" + domain + *p->name + ";");
+
6115
+
6116 // Generate struct model begin
+
6117 WriteLine();
+
6118 WriteLineIndent("// Fast Binary Encoding " + *s->name + " model");
+
6119 WriteLineIndent("public class " + *s->name + "Model : " + domain + "FBE.Model");
+
6120 WriteLineIndent("{");
+
6121 Indent(1);
+
6122
+
6123 // Generate struct model accessor
+
6124 WriteLineIndent("public readonly FieldModel" + *s->name + " model;");
+
6125
+
6126 // Generate struct model constructors
+
6127 WriteLine();
+
6128 WriteLineIndent("public " + *s->name + "Model() { model = new FieldModel" + *s->name + "(Buffer, 4); }");
+
6129 WriteLineIndent("public " + *s->name + "Model(" + domain + "FBE.Buffer buffer) : base(buffer) { model = new FieldModel" + *s->name + "(Buffer, 4); }");
+
6130
+
6131 // Generate struct model FBE properties
+
6132 WriteLine();
+
6133 WriteLineIndent("// Get the model size");
+
6134 WriteLineIndent("public long FBESize => model.FBESize + model.FBEExtra;");
+
6135 WriteLineIndent("// Get the model type");
+
6136 WriteLineIndent("public const long FBETypeConst = FieldModel" + *s->name + ".FBETypeConst;");
+
6137 WriteLineIndent("public long FBEType => FBETypeConst;");
+
6138
+
6139 // Generate struct model Verify() method
+
6140 WriteLine();
+
6141 WriteLineIndent("// Check if the struct value is valid");
+
6142 WriteLineIndent("public bool Verify()");
+
6143 WriteLineIndent("{");
+
6144 Indent(1);
+
6145 WriteLineIndent("if ((Buffer.Offset + model.FBEOffset - 4) > Buffer.Size)");
+
6146 Indent(1);
+
6147 WriteLineIndent("return false;");
+
6148 Indent(-1);
+
6149 WriteLine();
+
6150 WriteLineIndent("uint fbeFullSize = ReadUInt32(model.FBEOffset - 4);");
+
6151 WriteLineIndent("if (fbeFullSize < model.FBESize)");
+
6152 Indent(1);
+
6153 WriteLineIndent("return false;");
+
6154 Indent(-1);
+
6155 WriteLine();
+
6156 WriteLineIndent("return model.Verify();");
+
6157 Indent(-1);
+
6158 WriteLineIndent("}");
+
6159
+
6160 // Generate struct model CreateBegin() method
+
6161 WriteLine();
+
6162 WriteLineIndent("// Create a new model (begin phase)");
+
6163 WriteLineIndent("public long CreateBegin()");
+
6164 WriteLineIndent("{");
+
6165 Indent(1);
+
6166 WriteLineIndent("long fbeBegin = Buffer.Allocate(4 + model.FBESize);");
+
6167 WriteLineIndent("return fbeBegin;");
+
6168 Indent(-1);
+
6169 WriteLineIndent("}");
+
6170
+
6171 // Generate struct model CreateEnd() method
+
6172 WriteLine();
+
6173 WriteLineIndent("// Create a new model (end phase)");
+
6174 WriteLineIndent("public long CreateEnd(long fbeBegin)");
+
6175 WriteLineIndent("{");
+
6176 Indent(1);
+
6177 WriteLineIndent("long fbeEnd = Buffer.Size;");
+
6178 WriteLineIndent("uint fbeFullSize = (uint)(fbeEnd - fbeBegin);");
+
6179 WriteLineIndent("Write(model.FBEOffset - 4, fbeFullSize);");
+
6180 WriteLineIndent("return fbeFullSize;");
+
6181 Indent(-1);
+
6182 WriteLineIndent("}");
+
6183
+
6184 // Generate struct model Serialize() method
+
6185 WriteLine();
+
6186 WriteLineIndent("// Serialize the struct value");
+
6187 WriteLineIndent("public long Serialize(" + *s->name + " value)");
+
6188 WriteLineIndent("{");
+
6189 Indent(1);
+
6190 WriteLineIndent("long fbeBegin = CreateBegin();");
+
6191 WriteLineIndent("model.Set(value);");
+
6192 WriteLineIndent("long fbeFullSize = CreateEnd(fbeBegin);");
+
6193 WriteLineIndent("return fbeFullSize;");
+
6194 Indent(-1);
+
6195 WriteLineIndent("}");
+
6196
+
6197 // Generate struct model Deserialize() method
+
6198 WriteLine();
+
6199 WriteLineIndent("// Deserialize the struct value");
+
6200 WriteLineIndent("public long Deserialize(out " + *s->name + " value)");
+
6201 WriteLineIndent("{");
+
6202 Indent(1);
+
6203 WriteLineIndent("if ((Buffer.Offset + model.FBEOffset - 4) > Buffer.Size)");
+
6204 WriteLineIndent("{");
+
6205 Indent(1);
+
6206 WriteLineIndent("value = " + *s->name + ".Default;");
+
6207 WriteLineIndent("return 0;");
+
6208 Indent(-1);
+
6209 WriteLineIndent("}");
+
6210 WriteLine();
+
6211 WriteLineIndent("uint fbeFullSize = ReadUInt32(model.FBEOffset - 4);");
+
6212 WriteLineIndent("Debug.Assert((fbeFullSize >= model.FBESize), \"Model is broken!\");");
+
6213 WriteLineIndent("if (fbeFullSize < model.FBESize)");
+
6214 WriteLineIndent("{");
+
6215 Indent(1);
+
6216 WriteLineIndent("value = " + *s->name + ".Default;");
+
6217 WriteLineIndent("return 0;");
+
6218 Indent(-1);
+
6219 WriteLineIndent("}");
+
6220 WriteLine();
+
6221 WriteLineIndent("model.Get(out value);");
+
6222 WriteLineIndent("return fbeFullSize;");
+
6223 Indent(-1);
+
6224 WriteLineIndent("}");
+
6225
+
6226 // Generate struct model Next() method
+
6227 WriteLine();
+
6228 WriteLineIndent("// Move to the next struct value");
+
6229 WriteLineIndent("public void Next(long prev)");
+
6230 WriteLineIndent("{");
+
6231 Indent(1);
+
6232 WriteLineIndent("model.FBEShift(prev);");
+
6233 Indent(-1);
+
6234 WriteLineIndent("}");
+
6235
+
6236 // Generate struct model end
+
6237 Indent(-1);
+
6238 WriteLineIndent("}");
+
6239
+
6240 // Generate namespace end
+
6241 Indent(-1);
+
6242 WriteLine();
+
6243 WriteLineIndent("} // namespace " + domain + *p->name + ".FBE");
+
6244}
+
6245
+
6246void GeneratorCSharp::GenerateStructFinalModel(const std::string& domain, const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s)
+
6247{
+
6248 // Generate namespace begin
+
6249 WriteLine();
+
6250 WriteLineIndent("namespace " + domain + *p->name + ".FBE {");
+
6251 Indent(1);
+
6252
+
6253 // Generate using package
+
6254 WriteLine();
+
6255 WriteLineIndent("using global::" + domain + *p->name + ";");
+
6256
+
6257 // Generate struct final model begin
+
6258 WriteLine();
+
6259 WriteLineIndent("// Fast Binary Encoding " + *s->name + " final model");
+
6260 WriteLineIndent("public class FinalModel" + *s->name + " : " + domain + "FBE.FinalModelValueType<" + *s->name + ">");
+
6261 WriteLineIndent("{");
+
6262 Indent(1);
+
6263
+
6264 // Generate struct final model accessors
+
6265 if (s->base && !s->base->empty())
+
6266 WriteLineIndent("public readonly " + ConvertTypeFieldName(domain, *p->name, *s->base, true) + " parent;");
+
6267 if (s->body)
+
6268 for (const auto& field : s->body->fields)
+
6269 WriteLineIndent("public readonly " + ConvertTypeFieldDeclaration(domain, *p->name, *field, true) + " " + *field->name + ";");
+
6270
+
6271 // Generate struct final model constructor
+
6272 WriteLine();
+
6273 WriteLineIndent("public FinalModel" + *s->name + "(" + domain + "FBE.Buffer buffer, long offset) : base(buffer, offset)");
+
6274 WriteLineIndent("{");
+
6275 Indent(1);
+
6276 if (s->base && !s->base->empty())
+
6277 WriteLineIndent("parent = new " + ConvertTypeFieldName(domain, *p->name, *s->base, true) + "(buffer, 0);");
+
6278 if (s->body)
+
6279 for (const auto& field : s->body->fields)
+
6280 WriteLineIndent(*field->name + " = " + ConvertTypeFieldInitialization(domain, *p->name, *field, "0", true) + ";");
+
6281 Indent(-1);
+
6282 WriteLineIndent("}");
+
6283
+
6284 // Generate struct final model FBE properties
+
6285 WriteLine();
+
6286 WriteLineIndent("// Get the allocation size");
+
6287 WriteLineIndent("public override long FBEAllocationSize(" + *s->name + " fbeValue)");
+
6288 WriteLineIndent("{");
+
6289 Indent(1);
+
6290 WriteLineIndent("long fbeResult = 0");
+
6291 Indent(1);
+
6292 if (s->base && !s->base->empty())
+
6293 WriteLineIndent("+ parent.FBEAllocationSize(fbeValue.parent)");
+
6294 if (s->body)
+
6295 for (const auto& field : s->body->fields)
+
6296 WriteLineIndent("+ " + *field->name + ".FBEAllocationSize(fbeValue." + *field->name + ")");
+
6297 WriteLineIndent(";");
+
6298 Indent(-1);
+
6299 WriteLineIndent("return fbeResult;");
+
6300 Indent(-1);
+
6301 WriteLineIndent("}");
+
6302 WriteLine();
+
6303 WriteLineIndent("// Get the final type");
+
6304 if (s->base && !s->base->empty() && (s->type == 0))
+
6305 WriteLineIndent("public const long FBETypeConst = " + ConvertTypeFieldName(domain, *p->name, *s->base, true) + ".FBETypeConst;");
+
6306 else
+
6307 WriteLineIndent("public const long FBETypeConst = " + std::to_string(s->type) + ";");
+
6308 WriteLineIndent("public long FBEType => FBETypeConst;");
+
6309
+
6310 // Generate struct final model Clone() method
+
6311 WriteLine();
+
6312 WriteLineIndent("// Clone the final model");
+
6313 WriteLineIndent("public override " + domain + "FBE.FinalModelValueType<" + *s->name + "> Clone() { return new FinalModel" + *s->name + "(_buffer, _offset); }");
+
6314
+
6315 // Generate struct final model Verify() methods
+
6316 WriteLine();
+
6317 WriteLineIndent("// Check if the struct value is valid");
+
6318 WriteLineIndent("public override long Verify()");
+
6319 WriteLineIndent("{");
+
6320 Indent(1);
+
6321 WriteLineIndent("_buffer.Shift(FBEOffset);");
+
6322 WriteLineIndent("long fbeResult = VerifyFields();");
+
6323 WriteLineIndent("_buffer.Unshift(FBEOffset);");
+
6324 WriteLineIndent("return fbeResult;");
+
6325 Indent(-1);
+
6326 WriteLineIndent("}");
+
6327
+
6328 // Generate struct final model VerifyFields() method
+
6329 WriteLine();
+
6330 WriteLineIndent("// Check if the struct fields are valid");
+
6331 WriteLineIndent("public long VerifyFields()");
+
6332 WriteLineIndent("{");
+
6333 Indent(1);
+
6334 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
6335 {
+
6336 WriteLineIndent("long fbeCurrentOffset = 0;");
+
6337 WriteLineIndent("long fbeFieldSize;");
+
6338 if (s->base && !s->base->empty())
+
6339 {
+
6340 WriteLine();
+
6341 WriteLineIndent("parent.FBEOffset = fbeCurrentOffset;");
+
6342 WriteLineIndent("fbeFieldSize = parent.VerifyFields();");
+
6343 WriteLineIndent("if (fbeFieldSize == long.MaxValue)");
+
6344 Indent(1);
+
6345 WriteLineIndent("return long.MaxValue;");
+
6346 Indent(-1);
+
6347 WriteLineIndent("fbeCurrentOffset += fbeFieldSize;");
+
6348 }
+
6349 if (s->body)
+
6350 {
+
6351 for (const auto& field : s->body->fields)
+
6352 {
+
6353 WriteLine();
+
6354 WriteLineIndent(*field->name + ".FBEOffset = fbeCurrentOffset;");
+
6355 WriteLineIndent("fbeFieldSize = " + *field->name + ".Verify();");
+
6356 WriteLineIndent("if (fbeFieldSize == long.MaxValue)");
+
6357 Indent(1);
+
6358 WriteLineIndent("return long.MaxValue;");
+
6359 Indent(-1);
+
6360 WriteLineIndent("fbeCurrentOffset += fbeFieldSize;");
+
6361 }
+
6362 }
+
6363 WriteLine();
+
6364 WriteLineIndent("return fbeCurrentOffset;");
+
6365 }
+
6366 else
+
6367 WriteLineIndent("return 0;");
+
6368 Indent(-1);
+
6369 WriteLineIndent("}");
+
6370
+
6371 // Generate struct final model Get() methods
+
6372 WriteLine();
+
6373 WriteLineIndent("// Get the struct value");
+
6374 WriteLineIndent("public override long Get(out " + *s->name + " fbeValue)");
+
6375 WriteLineIndent("{");
+
6376 Indent(1);
+
6377 WriteLineIndent("_buffer.Shift(FBEOffset);");
+
6378 WriteLineIndent("long fbeSize = GetFields(out fbeValue);");
+
6379 WriteLineIndent("_buffer.Unshift(FBEOffset);");
+
6380 WriteLineIndent("return fbeSize;");
+
6381 Indent(-1);
+
6382 WriteLineIndent("}");
+
6383
+
6384 // Generate struct final model GetFields() method
+
6385 WriteLine();
+
6386 WriteLineIndent("// Get the struct fields values");
+
6387 WriteLineIndent("public long GetFields(out " + *s->name + " fbeValue)");
+
6388 WriteLineIndent("{");
+
6389 Indent(1);
+
6390 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
6391 {
+
6392 WriteLineIndent("long fbeCurrentOffset = 0;");
+
6393 WriteLineIndent("long fbeCurrentSize = 0;");
+
6394 WriteLineIndent("long fbeFieldSize;");
+
6395 WriteLine();
+
6396 WriteLineIndent("fbeValue = " + *s->name + ".Default;");
+
6397 if (s->base && !s->base->empty())
+
6398 {
+
6399 WriteLine();
+
6400 WriteLineIndent("parent.FBEOffset = fbeCurrentOffset;");
+
6401 WriteLineIndent("fbeFieldSize = parent.GetFields(out fbeValue.parent);");
+
6402 WriteLineIndent("fbeCurrentOffset += fbeFieldSize;");
+
6403 WriteLineIndent("fbeCurrentSize += fbeFieldSize;");
+
6404 }
+
6405 if (s->body)
+
6406 {
+
6407 for (const auto& field : s->body->fields)
+
6408 {
+
6409 WriteLine();
+
6410 WriteLineIndent(*field->name + ".FBEOffset = fbeCurrentOffset;");
+
6411 WriteLineIndent("fbeFieldSize = " + *field->name + ".Get(out fbeValue." + *field->name + ");");
+
6412 WriteLineIndent("fbeCurrentOffset += fbeFieldSize;");
+
6413 WriteLineIndent("fbeCurrentSize += fbeFieldSize;");
+
6414 }
+
6415 }
+
6416 WriteLine();
+
6417 WriteLineIndent("return fbeCurrentSize;");
+
6418 }
+
6419 else
+
6420 WriteLineIndent("return 0;");
+
6421 Indent(-1);
+
6422 WriteLineIndent("}");
+
6423
+
6424 // Generate struct final model Set() method
+
6425 WriteLine();
+
6426 WriteLineIndent("// Set the struct value");
+
6427 WriteLineIndent("public override long Set(" + *s->name + " fbeValue)");
+
6428 WriteLineIndent("{");
+
6429 Indent(1);
+
6430 WriteLineIndent("_buffer.Shift(FBEOffset);");
+
6431 WriteLineIndent("long fbeResult = SetFields(fbeValue);");
+
6432 WriteLineIndent("_buffer.Unshift(FBEOffset);");
+
6433 WriteLineIndent("return fbeResult;");
+
6434 Indent(-1);
+
6435 WriteLineIndent("}");
+
6436
+
6437 // Generate struct final model SetFields() method
+
6438 WriteLine();
+
6439 WriteLineIndent("// Set the struct fields values");
+
6440 WriteLineIndent("public long SetFields(" + *s->name + " fbeValue)");
+
6441 WriteLineIndent("{");
+
6442 Indent(1);
+
6443 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
6444 {
+
6445 WriteLineIndent("long fbeCurrentOffset = 0;");
+
6446 WriteLineIndent("long fbeCurrentSize = 0;");
+
6447 WriteLineIndent("long fbeFieldSize;");
+
6448 if (s->base && !s->base->empty())
+
6449 {
+
6450 WriteLine();
+
6451 WriteLineIndent("parent.FBEOffset = fbeCurrentOffset;");
+
6452 WriteLineIndent("fbeFieldSize = parent.SetFields(fbeValue.parent);");
+
6453 WriteLineIndent("fbeCurrentOffset += fbeFieldSize;");
+
6454 WriteLineIndent("fbeCurrentSize += fbeFieldSize;");
+
6455 }
+
6456 if (s->body)
+
6457 {
+
6458 for (const auto& field : s->body->fields)
+
6459 {
+
6460 WriteLine();
+
6461 WriteLineIndent(*field->name + ".FBEOffset = fbeCurrentOffset;");
+
6462 WriteLineIndent("fbeFieldSize = " + *field->name + ".Set(fbeValue." + *field->name + ");");
+
6463 WriteLineIndent("fbeCurrentOffset += fbeFieldSize;");
+
6464 WriteLineIndent("fbeCurrentSize += fbeFieldSize;");
+
6465 }
+
6466 }
+
6467 WriteLine();
+
6468 WriteLineIndent("return fbeCurrentSize;");
+
6469 }
+
6470 else
+
6471 WriteLineIndent("return 0;");
+
6472 Indent(-1);
+
6473 WriteLineIndent("}");
+
6474
+
6475 // Generate struct final model end
+
6476 Indent(-1);
+
6477 WriteLineIndent("}");
+
6478
+
6479 // Generate namespace end
+
6480 Indent(-1);
+
6481 WriteLine();
+
6482 WriteLineIndent("} // namespace " + domain + *p->name + ".FBE");
+
6483}
+
6484
+
6485void GeneratorCSharp::GenerateStructModelFinal(const std::string& domain, const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s)
+
6486{
+
6487 // Generate namespace begin
+
6488 WriteLine();
+
6489 WriteLineIndent("namespace " + domain + *p->name + ".FBE {");
+
6490 Indent(1);
+
6491
+
6492 // Generate using package
+
6493 WriteLine();
+
6494 WriteLineIndent("using global::" + domain + *p->name + ";");
+
6495
+
6496 // Generate struct model final begin
+
6497 WriteLine();
+
6498 WriteLineIndent("// Fast Binary Encoding " + *s->name + " final model");
+
6499 WriteLineIndent("public class " + *s->name + "FinalModel : " + domain + "FBE.Model");
+
6500 WriteLineIndent("{");
+
6501 Indent(1);
+
6502
+
6503 // Generate struct model final accessor
+
6504 WriteLineIndent("private readonly FinalModel" + *s->name + " _model;");
+
6505
+
6506 // Generate struct model final constructors
+
6507 WriteLine();
+
6508 WriteLineIndent("public " + *s->name + "FinalModel() { _model = new FinalModel" + *s->name + "(Buffer, 8); }");
+
6509 WriteLineIndent("public " + *s->name + "FinalModel(" + domain + "FBE.Buffer buffer) : base(buffer) { _model = new FinalModel" + *s->name + "(Buffer, 8); }");
+
6510
+
6511 // Generate struct model final FBE properties
+
6512 WriteLine();
+
6513 WriteLineIndent("// Get the model type");
+
6514 WriteLineIndent("public const long FBETypeConst = FinalModel" + *s->name + ".FBETypeConst;");
+
6515 WriteLineIndent("public long FBEType => FBETypeConst;");
+
6516
+
6517 // Generate struct model final Verify() method
+
6518 WriteLine();
+
6519 WriteLineIndent("// Check if the struct value is valid");
+
6520 WriteLineIndent("public bool Verify()");
+
6521 WriteLineIndent("{");
+
6522 Indent(1);
+
6523 WriteLineIndent("if ((Buffer.Offset + _model.FBEOffset) > Buffer.Size)");
+
6524 Indent(1);
+
6525 WriteLineIndent("return false;");
+
6526 Indent(-1);
+
6527 WriteLine();
+
6528 WriteLineIndent("long fbeStructSize = ReadUInt32(_model.FBEOffset - 8);");
+
6529 WriteLineIndent("long fbeStructType = ReadUInt32(_model.FBEOffset - 4);");
+
6530 WriteLineIndent("if ((fbeStructSize <= 0) || (fbeStructType != FBEType))");
+
6531 Indent(1);
+
6532 WriteLineIndent("return false;");
+
6533 Indent(-1);
+
6534 WriteLine();
+
6535 WriteLineIndent("return ((8 + _model.Verify()) == fbeStructSize);");
+
6536 Indent(-1);
+
6537 WriteLineIndent("}");
+
6538
+
6539 // Generate struct model final Serialize() method
+
6540 WriteLine();
+
6541 WriteLineIndent("// Serialize the struct value");
+
6542 WriteLineIndent("public long Serialize(" + *s->name + " value)");
+
6543 WriteLineIndent("{");
+
6544 Indent(1);
+
6545 WriteLineIndent("long fbeInitialSize = Buffer.Size;");
+
6546 WriteLine();
+
6547 WriteLineIndent("uint fbeStructType = (uint)FBEType;");
+
6548 WriteLineIndent("uint fbeStructSize = (uint)(8 + _model.FBEAllocationSize(value));");
+
6549 WriteLineIndent("uint fbeStructOffset = (uint)(Buffer.Allocate(fbeStructSize) - Buffer.Offset);");
+
6550 WriteLineIndent("Debug.Assert(((Buffer.Offset + fbeStructOffset + fbeStructSize) <= Buffer.Size), \"Model is broken!\");");
+
6551 WriteLineIndent("if ((Buffer.Offset + fbeStructOffset + fbeStructSize) > Buffer.Size)");
+
6552 Indent(1);
+
6553 WriteLineIndent("return 0;");
+
6554 Indent(-1);
+
6555 WriteLine();
+
6556 WriteLineIndent("fbeStructSize = (uint)(8 + _model.Set(value));");
+
6557 WriteLineIndent("Buffer.Resize(fbeInitialSize + fbeStructSize);");
+
6558 WriteLine();
+
6559 WriteLineIndent("Write(_model.FBEOffset - 8, fbeStructSize);");
+
6560 WriteLineIndent("Write(_model.FBEOffset - 4, fbeStructType);");
+
6561 WriteLine();
+
6562 WriteLineIndent("return fbeStructSize;");
+
6563 Indent(-1);
+
6564 WriteLineIndent("}");
+
6565
+
6566 // Generate struct model final Deserialize() method
+
6567 WriteLine();
+
6568 WriteLineIndent("// Deserialize the struct value");
+
6569 WriteLineIndent("public long Deserialize(out " + *s->name + " value)");
+
6570 WriteLineIndent("{");
+
6571 Indent(1);
+
6572 WriteLineIndent("Debug.Assert(((Buffer.Offset + _model.FBEOffset) <= Buffer.Size), \"Model is broken!\");");
+
6573 WriteLineIndent("if ((Buffer.Offset + _model.FBEOffset) > Buffer.Size)");
+
6574 WriteLineIndent("{");
+
6575 Indent(1);
+
6576 WriteLineIndent("value = " + *s->name + ".Default;");
+
6577 WriteLineIndent("return 0;");
+
6578 Indent(-1);
+
6579 WriteLineIndent("}");
+
6580 WriteLine();
+
6581 WriteLineIndent("long fbeStructSize = ReadUInt32(_model.FBEOffset - 8);");
+
6582 WriteLineIndent("long fbeStructType = ReadUInt32(_model.FBEOffset - 4);");
+
6583 WriteLineIndent("Debug.Assert(((fbeStructSize > 0) && (fbeStructType == FBEType)), \"Model is broken!\");");
+
6584 WriteLineIndent("if ((fbeStructSize <= 0) || (fbeStructType != FBEType))");
+
6585 WriteLineIndent("{");
+
6586 Indent(1);
+
6587 WriteLineIndent("value = " + *s->name + ".Default;");
+
6588 WriteLineIndent("return 8;");
+
6589 Indent(-1);
+
6590 WriteLineIndent("}");
+
6591 WriteLine();
+
6592 WriteLineIndent("return 8 + _model.Get(out value);");
+
6593 Indent(-1);
+
6594 WriteLineIndent("}");
+
6595
+
6596 // Generate struct model final Next() method
+
6597 WriteLine();
+
6598 WriteLineIndent("// Move to the next struct value");
+
6599 WriteLineIndent("public void Next(long prev)");
+
6600 WriteLineIndent("{");
+
6601 Indent(1);
+
6602 WriteLineIndent("_model.FBEShift(prev);");
+
6603 Indent(-1);
+
6604 WriteLineIndent("}");
+
6605
+
6606 // Generate struct model final end
+
6607 Indent(-1);
+
6608 WriteLineIndent("}");
+
6609
+
6610 // Generate namespace end
+
6611 Indent(-1);
+
6612 WriteLine();
+
6613 WriteLineIndent("} // namespace " + domain + *p->name + ".FBE");
+
6614}
+
6615
+
6616void GeneratorCSharp::GenerateProtocolVersion(const std::string& domain, const std::shared_ptr<Package>& p)
+
6617{
+
6618 // Generate namespace begin
+
6619 WriteLine();
+
6620 WriteLineIndent("namespace " + domain + *p->name + ".FBE {");
+
6621 Indent(1);
+
6622
+
6623 // Generate protocol version class
+
6624 WriteLine();
+
6625 WriteLineIndent("// Fast Binary Encoding " + domain + *p->name + " protocol version");
+
6626 WriteLineIndent("public static class ProtocolVersion");
+
6627 WriteLineIndent("{");
+
6628 Indent(1);
+
6629 WriteLineIndent("// Protocol major version");
+
6630 WriteLineIndent("public const int Major = " + std::to_string(p->version->major) + ";");
+
6631 WriteLineIndent("// Protocol minor version");
+
6632 WriteLineIndent("public const int Minor = " + std::to_string(p->version->minor) + ";");
+
6633 Indent(-1);
+
6634 WriteLineIndent("}");
+
6635
+
6636 // Generate namespace end
+
6637 Indent(-1);
+
6638 WriteLine();
+
6639 WriteLineIndent("} // namespace " + domain + *p->name + ".FBE");
+
6640}
+
6641
+
6642void GeneratorCSharp::GenerateSender(const std::string& domain, const std::shared_ptr<Package>& p, bool final)
+
6643{
+
6644 // Generate namespace begin
+
6645 WriteLine();
+
6646 WriteLineIndent("namespace " + domain + *p->name + ".FBE {");
+
6647 Indent(1);
+
6648
+
6649 std::string sender = (final ? "FinalSender" : "Sender");
+
6650 std::string model = (final ? "FinalModel" : "Model");
+
6651 std::string listener = "I" + sender + "Listener";
+
6652
+
6653 // Generate sender listener begin
+
6654 WriteLine();
+
6655 if (final)
+
6656 WriteLineIndent("// Fast Binary Encoding " + domain + *p->name + " final sender listener interface");
+
6657 else
+
6658 WriteLineIndent("// Fast Binary Encoding " + domain + *p->name + " sender listener interface");
+
6659 WriteIndent("public interface " + listener);
+
6660 if (p->import)
+
6661 {
+
6662 bool first = true;
+
6663 Write(" : ");
+
6664 for (const auto& import : p->import->imports)
+
6665 {
+
6666 Write(std::string(first ? "" : ", ") + domain + *import + ".FBE." + listener);
+
6667 first = false;
+
6668 }
+
6669 }
+
6670 else
+
6671 Write(" : " + domain + "FBE.ISenderListener");
+
6672 WriteLine();
+
6673 WriteLineIndent("{");
+
6674 Indent(1);
+
6675
+
6676 // Generate sender listener end
+
6677 Indent(-1);
+
6678 WriteLineIndent("}");
+
6679
+
6680 // Generate sender begin
+
6681 WriteLine();
+
6682 if (final)
+
6683 WriteLineIndent("// Fast Binary Encoding " + domain + *p->name + " final sender");
+
6684 else
+
6685 WriteLineIndent("// Fast Binary Encoding " + domain + *p->name + " sender");
+
6686 WriteLineIndent("public class " + sender + " : " + domain + "FBE.Sender, " + listener);
+
6687 WriteLineIndent("{");
+
6688 Indent(1);
+
6689
+
6690 // Generate imported senders accessors
+
6691 if (p->import)
+
6692 {
+
6693 WriteLineIndent("// Imported senders");
+
6694 for (const auto& import : p->import->imports)
+
6695 WriteLineIndent("public readonly " + *import + ".FBE." + sender + " " + *import + "Sender;");
+
6696 WriteLine();
+
6697 }
+
6698
+
6699 // Generate sender models accessors
+
6700 if (p->body)
+
6701 {
+
6702 WriteLineIndent("// Sender models accessors");
+
6703 for (const auto& s : p->body->structs)
+
6704 if (s->message)
+
6705 WriteLineIndent("public readonly " + *s->name + model + " " + *s->name + "Model;");
+
6706 WriteLine();
+
6707 }
+
6708
+
6709 // Generate sender constructors
+
6710 WriteLineIndent("public " + sender + "() : base(" + std::string(final ? "true" : "false") + ")");
+
6711 WriteLineIndent("{");
+
6712 Indent(1);
+
6713 if (p->import)
+
6714 {
+
6715 for (const auto& import : p->import->imports)
+
6716 WriteLineIndent(*import + "Sender = new " + *import + ".FBE." + sender + "(Buffer);");
+
6717 }
+
6718 if (p->body)
+
6719 {
+
6720 for (const auto& s : p->body->structs)
+
6721 if (s->message)
+
6722 WriteLineIndent(*s->name + "Model = new " + *s->name + model + "(Buffer);");
+
6723 }
+
6724 Indent(-1);
+
6725 WriteLineIndent("}");
+
6726 WriteLineIndent("public " + sender + "(" + domain + "FBE.Buffer buffer) : base(buffer, " + std::string(final ? "true" : "false") + ")");
+
6727 WriteLineIndent("{");
+
6728 Indent(1);
+
6729 if (p->import)
+
6730 {
+
6731 for (const auto& import : p->import->imports)
+
6732 WriteLineIndent(*import + "Sender = new " + *import + ".FBE." + sender + "(Buffer);");
+
6733 }
+
6734 if (p->body)
+
6735 {
+
6736 for (const auto& s : p->body->structs)
+
6737 if (s->message)
+
6738 WriteLineIndent(*s->name + "Model = new " + *s->name + model + "(Buffer);");
+
6739 }
+
6740 Indent(-1);
+
6741 WriteLineIndent("}");
+
6742 WriteLine();
+
6743
+
6744 // Generate send method
+
6745 WriteLineIndent("public long Send(object obj) { return SendListener(this, obj); }");
+
6746 WriteLineIndent("public long SendListener(" + listener + " listener, object obj)");
+
6747 WriteLineIndent("{");
+
6748 Indent(1);
+
6749 if (p->body)
+
6750 {
+
6751 WriteLineIndent("switch (obj)");
+
6752 WriteLineIndent("{");
+
6753 Indent(1);
+
6754 for (const auto& s : p->body->structs)
+
6755 {
+
6756 if (s->message)
+
6757 {
+
6758 std::string struct_name = "global::" + domain + *p->name + "." + *s->name;
+
6759 WriteLineIndent("case " + struct_name + " value when value.FBEType == " + struct_name + ".FBETypeConst: return SendListener(listener, value);");
+
6760 }
+
6761 }
+
6762 WriteLineIndent("default: break;");
+
6763 Indent(-1);
+
6764 WriteLineIndent("}");
+
6765 WriteLine();
+
6766 }
+
6767 if (p->import)
+
6768 {
+
6769 WriteLineIndent("long result;");
+
6770 for (const auto& import : p->import->imports)
+
6771 {
+
6772 WriteLineIndent("result = " + *import + "Sender.SendListener(listener, obj);");
+
6773 WriteLineIndent("if (result > 0)");
+
6774 Indent(1);
+
6775 WriteLineIndent("return result;");
+
6776 Indent(-1);
+
6777 }
+
6778 WriteLine();
+
6779 }
+
6780 WriteLineIndent("return 0;");
+
6781 Indent(-1);
+
6782 WriteLineIndent("}");
+
6783 WriteLine();
+
6784
+
6785 // Generate send methods
+
6786 if (p->body)
+
6787 {
+
6788 for (const auto& s : p->body->structs)
+
6789 {
+
6790 if (s->message)
+
6791 {
+
6792 std::string struct_name = "global::" + domain + *p->name + "." + *s->name;
+
6793 WriteLineIndent("public long Send(" + struct_name + " value) { return SendListener(this, value); }");
+
6794 WriteLineIndent("public long SendListener(" + listener + " listener, " + struct_name + " value)");
+
6795 WriteLineIndent("{");
+
6796 Indent(1);
+
6797 WriteLineIndent("// Serialize the value into the FBE stream");
+
6798 WriteLineIndent("long serialized = " + *s->name + "Model.Serialize(value);");
+
6799 WriteLineIndent("Debug.Assert((serialized > 0), \"" + domain + *p->name + "." + *s->name + " serialization failed!\");");
+
6800 WriteLineIndent("Debug.Assert(" + *s->name + "Model.Verify(), \"" + domain + *p->name + "." + *s->name + " validation failed!\");");
+
6801 WriteLine();
+
6802 WriteLineIndent("// Log the value");
+
6803 WriteLineIndent("if (Logging)");
+
6804 WriteLineIndent("{");
+
6805 Indent(1);
+
6806 WriteLineIndent("string message = value.ToString();");
+
6807 WriteLineIndent("listener.OnSendLog(message);");
+
6808 Indent(-1);
+
6809 WriteLineIndent("}");
+
6810 WriteLine();
+
6811 WriteLineIndent("// Send the serialized value");
+
6812 WriteLineIndent("return SendSerialized(listener, serialized);");
+
6813 Indent(-1);
+
6814 WriteLineIndent("}");
+
6815 }
+
6816 }
+
6817 }
+
6818
+
6819 // Generate sender end
+
6820 Indent(-1);
+
6821 WriteLineIndent("}");
+
6822
+
6823 // Generate namespace end
+
6824 Indent(-1);
+
6825 WriteLine();
+
6826 WriteLineIndent("} // namespace " + domain + *p->name + ".FBE");
+
6827}
+
6828
+
6829void GeneratorCSharp::GenerateReceiver(const std::string& domain, const std::shared_ptr<Package>& p, bool final)
+
6830{
+
6831 // Generate namespace begin
+
6832 WriteLine();
+
6833 WriteLineIndent("namespace " + domain + *p->name + ".FBE {");
+
6834 Indent(1);
+
6835
+
6836 std::string receiver = (final ? "FinalReceiver" : "Receiver");
+
6837 std::string model = (final ? "FinalModel" : "Model");
+
6838 std::string listener = "I" + receiver + "Listener";
+
6839
+
6840 // Generate receiver listener begin
+
6841 WriteLine();
+
6842 if (final)
+
6843 WriteLineIndent("// Fast Binary Encoding " + domain + *p->name + " final receiver listener interface");
+
6844 else
+
6845 WriteLineIndent("// Fast Binary Encoding " + domain + *p->name + " receiver listener interface");
+
6846 WriteIndent("public interface " + listener);
+
6847 if (p->import)
+
6848 {
+
6849 bool first = true;
+
6850 Write(" : ");
+
6851 for (const auto& import : p->import->imports)
+
6852 {
+
6853 Write(std::string(first ? "" : ", ") + domain + *import + ".FBE." + listener);
+
6854 first = false;
+
6855 }
+
6856 }
+
6857 else
+
6858 Write(" : " + domain + "FBE.IReceiverListener");
+
6859 WriteLine();
+
6860 WriteLineIndent("{");
+
6861 Indent(1);
+
6862
+
6863 // Generate receiver handlers
+
6864 if (p->body)
+
6865 {
+
6866 WriteLineIndent("// Receive handlers");
+
6867 for (const auto& s : p->body->structs)
+
6868 {
+
6869 if (s->message)
+
6870 {
+
6871 std::string struct_name = ConvertTypeName(domain, *p->name, *s->name, false);
+
6872 WriteLineIndent("void OnReceive(" + struct_name + " value) {}");
+
6873 }
+
6874 }
+
6875 }
+
6876
+
6877 // Generate receiver listener end
+
6878 Indent(-1);
+
6879 WriteLineIndent("}");
+
6880
+
6881 // Generate receiver begin
+
6882 WriteLine();
+
6883 if (final)
+
6884 WriteLineIndent("// Fast Binary Encoding " + domain + *p->name + " final receiver");
+
6885 else
+
6886 WriteLineIndent("// Fast Binary Encoding " + domain + *p->name + " receiver");
+
6887 WriteLineIndent("public class " + receiver + " : " + domain + "FBE.Receiver, " + listener);
+
6888 WriteLineIndent("{");
+
6889 Indent(1);
+
6890
+
6891 // Generate imported receivers accessors
+
6892 if (p->import)
+
6893 {
+
6894 WriteLineIndent("// Imported receivers");
+
6895 for (const auto& import : p->import->imports)
+
6896 WriteLineIndent("public " + *import + ".FBE." + receiver + " " + *import + "Receiver;");
+
6897 WriteLine();
+
6898 }
+
6899
+
6900 // Generate receiver models accessors
+
6901 if (p->body)
+
6902 {
+
6903 WriteLineIndent("// Receiver values accessors");
+
6904 for (const auto& s : p->body->structs)
+
6905 {
+
6906 if (s->message)
+
6907 {
+
6908 std::string struct_name = ConvertTypeName(domain, *p->name, *s->name, false);
+
6909 WriteLineIndent("private " + struct_name + " " + *s->name + "Value;");
+
6910 }
+
6911 }
+
6912 WriteLine();
+
6913 WriteLineIndent("// Receiver models accessors");
+
6914 for (const auto& s : p->body->structs)
+
6915 if (s->message)
+
6916 WriteLineIndent("private readonly " + *s->name + model + " " + *s->name + "Model;");
+
6917 WriteLine();
+
6918 }
+
6919
+
6920 // Generate receiver constructors
+
6921 WriteLineIndent("public " + receiver + "() : base(" + std::string(final ? "true" : "false") + ")");
+
6922 WriteLineIndent("{");
+
6923 Indent(1);
+
6924 if (p->import)
+
6925 {
+
6926 for (const auto& import : p->import->imports)
+
6927 WriteLineIndent(*import + "Receiver = new " + *import + ".FBE." + receiver + "(Buffer);");
+
6928 }
+
6929 if (p->body)
+
6930 {
+
6931 for (const auto& s : p->body->structs)
+
6932 {
+
6933 if (s->message)
+
6934 {
+
6935 std::string struct_name = ConvertTypeName(domain, *p->name, *s->name, false);
+
6936 WriteLineIndent(*s->name + "Value = " + struct_name + ".Default;");
+
6937 WriteLineIndent(*s->name + "Model = new " + *s->name + model + "();");
+
6938 }
+
6939 }
+
6940 }
+
6941 Indent(-1);
+
6942 WriteLineIndent("}");
+
6943 WriteLineIndent("public " + receiver + "(" + domain + "FBE.Buffer buffer) : base(buffer, " + std::string(final ? "true" : "false") + ")");
+
6944 WriteLineIndent("{");
+
6945 Indent(1);
+
6946 if (p->import)
+
6947 {
+
6948 for (const auto& import : p->import->imports)
+
6949 WriteLineIndent(*import + "Receiver = new " + *import + ".FBE." + receiver + "(Buffer);");
+
6950 }
+
6951 if (p->body)
+
6952 {
+
6953 for (const auto& s : p->body->structs)
+
6954 {
+
6955 if (s->message)
+
6956 {
+
6957 std::string struct_name = ConvertTypeName(domain, *p->name, *s->name, false);
+
6958 WriteLineIndent(*s->name + "Value = " + struct_name + ".Default;");
+
6959 WriteLineIndent(*s->name + "Model = new " + *s->name + model + "();");
+
6960 }
+
6961 }
+
6962 }
+
6963 Indent(-1);
+
6964 WriteLineIndent("}");
+
6965 WriteLine();
+
6966
+
6967 // Generate receiver message handler
+
6968 WriteLineIndent("internal override bool OnReceive(long type, byte[] buffer, long offset, long size) { return OnReceiveListener(this, type, buffer, offset, size); }");
+
6969 WriteLineIndent("internal bool OnReceiveListener(" + listener + " listener, long type, byte[] buffer, long offset, long size)");
+
6970 WriteLineIndent("{");
+
6971 Indent(1);
+
6972 if (p->body)
+
6973 {
+
6974 WriteLineIndent("switch (type)");
+
6975 WriteLineIndent("{");
+
6976 Indent(1);
+
6977 for (const auto& s : p->body->structs)
+
6978 {
+
6979 if (s->message)
+
6980 {
+
6981 WriteLineIndent("case " + *s->name + model + ".FBETypeConst:");
+
6982 WriteLineIndent("{");
+
6983 Indent(1);
+
6984 WriteLineIndent("// Deserialize the value from the FBE stream");
+
6985 WriteLineIndent(*s->name + "Model.Attach(buffer, offset);");
+
6986 WriteLineIndent("Debug.Assert(" + *s->name + "Model.Verify(), \"" + domain + *p->name + "." + *s->name + " validation failed!\");");
+
6987 WriteLineIndent("long deserialized = " + *s->name + "Model.Deserialize(out " + *s->name + "Value);");
+
6988 WriteLineIndent("Debug.Assert((deserialized > 0), \"" + domain + *p->name + "." + *s->name + " deserialization failed!\");");
+
6989 WriteLine();
+
6990 WriteLineIndent("// Log the value");
+
6991 WriteLineIndent("if (Logging)");
+
6992 WriteLineIndent("{");
+
6993 Indent(1);
+
6994 WriteLineIndent("string message = " + *s->name + "Value.ToString();");
+
6995 WriteLineIndent("listener.OnReceiveLog(message);");
+
6996 Indent(-1);
+
6997 WriteLineIndent("}");
+
6998 WriteLine();
+
6999 WriteLineIndent("// Call receive handler with deserialized value");
+
7000 WriteLineIndent("listener.OnReceive(" + *s->name + "Value);");
+
7001 WriteLineIndent("return true;");
+
7002 Indent(-1);
+
7003 WriteLineIndent("}");
+
7004 }
+
7005 }
+
7006 WriteLineIndent("default: break;");
+
7007 Indent(-1);
+
7008 WriteLineIndent("}");
+
7009 WriteLine();
+
7010 }
+
7011 if (p->import)
+
7012 {
+
7013 for (const auto& import : p->import->imports)
+
7014 {
+
7015 WriteLineIndent("if (" + *import + "Receiver.OnReceiveListener(listener, type, buffer, offset, size))");
+
7016 Indent(1);
+
7017 WriteLineIndent("return true;");
+
7018 Indent(-1);
+
7019 }
+
7020 WriteLine();
+
7021 }
+
7022 WriteLineIndent("return false;");
+
7023 Indent(-1);
+
7024 WriteLineIndent("}");
+
7025
+
7026 // Generate receiver end
+
7027 Indent(-1);
+
7028 WriteLineIndent("}");
+
7029
+
7030 // Generate namespace end
+
7031 Indent(-1);
+
7032 WriteLine();
+
7033 WriteLineIndent("} // namespace " + domain + *p->name + ".FBE");
+
7034}
+
7035
+
7036void GeneratorCSharp::GenerateProxy(const std::string& domain, const std::shared_ptr<Package>& p, bool final)
+
7037{
+
7038 // Generate namespace begin
+
7039 WriteLine();
+
7040 WriteLineIndent("namespace " + domain + *p->name + ".FBE {");
+
7041 Indent(1);
+
7042
+
7043 std::string proxy = (final ? "FinalProxy" : "Proxy");
+
7044 std::string model = (final ? "FinalModel" : "Model");
+
7045 std::string listener = "I" + proxy + "Listener";
+
7046
+
7047 // Generate proxy listener begin
+
7048 WriteLine();
+
7049 if (final)
+
7050 WriteLineIndent("// Fast Binary Encoding " + domain + *p->name + " final proxy listener interface");
+
7051 else
+
7052 WriteLineIndent("// Fast Binary Encoding " + domain + *p->name + " proxy listener interface");
+
7053 WriteIndent("public interface " + listener);
+
7054 if (p->import)
+
7055 {
+
7056 bool first = true;
+
7057 Write(" : ");
+
7058 for (const auto& import : p->import->imports)
+
7059 {
+
7060 Write(std::string(first ? "" : ", ") + domain + *import + ".FBE." + listener);
+
7061 first = false;
+
7062 }
+
7063 }
+
7064 else
+
7065 Write(" : " + domain + "FBE.IReceiverListener");
+
7066 WriteLine();
+
7067 WriteLineIndent("{");
+
7068 Indent(1);
+
7069
+
7070 // Generate proxy handlers
+
7071 if (p->body)
+
7072 {
+
7073 WriteLineIndent("// Proxy handlers");
+
7074 for (const auto& s : p->body->structs)
+
7075 {
+
7076 if (s->message)
+
7077 {
+
7078 std::string struct_model = *s->name + model;
+
7079 WriteLineIndent("void OnProxy(" + struct_model + " model, long type, byte[] buffer, long offset, long size) {}");
+
7080 }
+
7081 }
+
7082 }
+
7083
+
7084 // Generate proxy listener end
+
7085 Indent(-1);
+
7086 WriteLineIndent("}");
+
7087
+
7088 // Generate proxy begin
+
7089 WriteLine();
+
7090 if (final)
+
7091 WriteLineIndent("// Fast Binary Encoding " + domain + *p->name + " final proxy");
+
7092 else
+
7093 WriteLineIndent("// Fast Binary Encoding " + domain + *p->name + " proxy");
+
7094 WriteLineIndent("public class " + proxy + " : " + domain + "FBE.Receiver, " + listener);
+
7095 WriteLineIndent("{");
+
7096 Indent(1);
+
7097
+
7098 // Generate imported proxy accessors
+
7099 if (p->import)
+
7100 {
+
7101 WriteLineIndent("// Imported proxy");
+
7102 for (const auto& import : p->import->imports)
+
7103 WriteLineIndent("public " + *import + ".FBE." + proxy + " " + *import + "Proxy;");
+
7104 WriteLine();
+
7105 }
+
7106
+
7107 // Generate proxy models accessors
+
7108 if (p->body)
+
7109 {
+
7110 WriteLineIndent("// Proxy models accessors");
+
7111 for (const auto& s : p->body->structs)
+
7112 if (s->message)
+
7113 WriteLineIndent("private readonly " + *s->name + model + " " + *s->name + "Model;");
+
7114 WriteLine();
+
7115 }
+
7116
+
7117 // Generate proxy constructors
+
7118 WriteLineIndent("public " + proxy + "() : base(" + std::string(final ? "true" : "false") + ")");
+
7119 WriteLineIndent("{");
+
7120 Indent(1);
+
7121 if (p->import)
+
7122 {
+
7123 for (const auto& import : p->import->imports)
+
7124 WriteLineIndent(*import + "Proxy = new " + *import + ".FBE." + proxy + "(Buffer);");
+
7125 }
+
7126 if (p->body)
+
7127 {
+
7128 for (const auto& s : p->body->structs)
+
7129 if (s->message)
+
7130 WriteLineIndent(*s->name + "Model = new " + *s->name + model + "();");
+
7131 }
+
7132 Indent(-1);
+
7133 WriteLineIndent("}");
+
7134 WriteLineIndent("public " + proxy + "(" + domain + "FBE.Buffer buffer) : base(buffer, " + std::string(final ? "true" : "false") + ")");
+
7135 WriteLineIndent("{");
+
7136 Indent(1);
+
7137 if (p->import)
+
7138 {
+
7139 for (const auto& import : p->import->imports)
+
7140 WriteLineIndent(*import + "Proxy = new " + *import + ".FBE." + proxy + "(Buffer);");
+
7141 }
+
7142 if (p->body)
+
7143 {
+
7144 for (const auto& s : p->body->structs)
+
7145 if (s->message)
+
7146 WriteLineIndent(*s->name + "Model = new " + *s->name + model + "();");
+
7147 }
+
7148 Indent(-1);
+
7149 WriteLineIndent("}");
+
7150 WriteLine();
+
7151
+
7152 // Generate proxy message handler
+
7153 WriteLineIndent("internal override bool OnReceive(long type, byte[] buffer, long offset, long size) { return OnReceiveListener(this, type, buffer, offset, size); }");
+
7154 WriteLineIndent("internal bool OnReceiveListener(" + listener + " listener, long type, byte[] buffer, long offset, long size)");
+
7155 WriteLineIndent("{");
+
7156 Indent(1);
+
7157 if (p->body)
+
7158 {
+
7159 WriteLineIndent("switch (type)");
+
7160 WriteLineIndent("{");
+
7161 Indent(1);
+
7162 for (const auto& s : p->body->structs)
+
7163 {
+
7164 if (s->message)
+
7165 {
+
7166 WriteLineIndent("case " + *s->name + model + ".FBETypeConst:");
+
7167 WriteLineIndent("{");
+
7168 Indent(1);
+
7169 WriteLineIndent("// Attach the FBE stream to the proxy model");
+
7170 WriteLineIndent(*s->name + "Model.Attach(buffer, offset);");
+
7171 WriteLineIndent("Debug.Assert(" + *s->name + "Model.Verify(), \"" + domain + *p->name + "." + *s->name + " validation failed!\");");
+
7172 WriteLine();
+
7173 WriteLineIndent("long fbeBegin = " + *s->name + "Model.model.GetBegin();");
+
7174 WriteLineIndent("if (fbeBegin == 0)");
+
7175 Indent(1);
+
7176 WriteLineIndent("return false;");
+
7177 Indent(-1);
+
7178 WriteLineIndent("// Call proxy handler");
+
7179 WriteLineIndent("listener.OnProxy(" + *s->name + "Model, type, buffer, offset, size);");
+
7180 WriteLineIndent(*s->name + "Model.model.GetEnd(fbeBegin);");
+
7181 WriteLineIndent("return true;");
+
7182 Indent(-1);
+
7183 WriteLineIndent("}");
+
7184 }
+
7185 }
+
7186 WriteLineIndent("default: break;");
+
7187 Indent(-1);
+
7188 WriteLineIndent("}");
+
7189 WriteLine();
+
7190 }
+
7191 if (p->import)
+
7192 {
+
7193 for (const auto& import : p->import->imports)
+
7194 {
+
7195 WriteLineIndent("if (" + *import + "Proxy.OnReceiveListener(listener, type, buffer, offset, size))");
+
7196 Indent(1);
+
7197 WriteLineIndent("return true;");
+
7198 Indent(-1);
+
7199 }
+
7200 WriteLine();
+
7201 }
+
7202 WriteLineIndent("return false;");
+
7203 Indent(-1);
+
7204 WriteLineIndent("}");
+
7205
+
7206 // Generate proxy end
+
7207 Indent(-1);
+
7208 WriteLineIndent("}");
+
7209
+
7210 // Generate namespace end
+
7211 Indent(-1);
+
7212 WriteLine();
+
7213 WriteLineIndent("} // namespace " + domain + *p->name + ".FBE");
+
7214}
+
7215
+
7216void GeneratorCSharp::GenerateClient(const std::string& domain, const std::shared_ptr<Package>& p, bool final)
+
7217{
+
7218 // Generate namespace begin
+
7219 WriteLine();
+
7220 WriteLineIndent("namespace " + domain + *p->name + ".FBE {");
+
7221 Indent(1);
+
7222
+
7223 std::string sender = (final ? "FinalSender" : "Sender");
+
7224 std::string receiver = (final ? "FinalReceiver" : "Receiver");
+
7225 std::string client = (final ? "FinalClient" : "Client");
+
7226 std::string model = (final ? "FinalModel" : "Model");
+
7227 std::string listener = "I" + client + "Listener";
+
7228 std::string sender_listener = "I" + sender + "Listener";
+
7229 std::string receiver_listener = "I" + receiver + "Listener";
+
7230
+
7231 // Generate client listener begin
+
7232 WriteLine();
+
7233 if (final)
+
7234 WriteLineIndent("// Fast Binary Encoding " + domain + *p->name + " final client listener interface");
+
7235 else
+
7236 WriteLineIndent("// Fast Binary Encoding " + domain + *p->name + " client listener interface");
+
7237 WriteIndent("public interface " + listener);
+
7238 if (p->import)
+
7239 {
+
7240 bool first = true;
+
7241 Write(" : ");
+
7242 for (const auto& import : p->import->imports)
+
7243 {
+
7244 Write(std::string(first ? "" : ", ") + domain + *import + ".FBE." + listener);
+
7245 first = false;
+
7246 }
+
7247 }
+
7248 else
+
7249 Write(" : " + domain + "FBE.IClientListener");
+
7250 Write(", " + sender_listener + ", " + receiver_listener);
+
7251 WriteLine();
+
7252 WriteLineIndent("{");
+
7253 Indent(1);
+
7254
+
7255 // Generate client listener end
+
7256 Indent(-1);
+
7257 WriteLineIndent("}");
+
7258
+
7259 // Generate client begin
+
7260 WriteLine();
+
7261 if (final)
+
7262 WriteLineIndent("// Fast Binary Encoding " + domain + *p->name + " final client");
+
7263 else
+
7264 WriteLineIndent("// Fast Binary Encoding " + domain + *p->name + " client");
+
7265 WriteLineIndent("public class " + client + " : " + domain + "FBE.Client, " + listener);
+
7266 WriteLineIndent("{");
+
7267 Indent(1);
+
7268
+
7269 // Generate imported clients accessors
+
7270 if (p->import)
+
7271 {
+
7272 WriteLineIndent("// Imported clients");
+
7273 for (const auto& import : p->import->imports)
+
7274 WriteLineIndent("public readonly " + *import + ".FBE." + client + " " + *import + "Client;");
+
7275 WriteLine();
+
7276 }
+
7277
+
7278 // Generate client sender models accessors
+
7279 if (p->body)
+
7280 {
+
7281 WriteLineIndent("// Client sender models accessors");
+
7282 for (const auto& s : p->body->structs)
+
7283 if (s->message)
+
7284 WriteLineIndent("public readonly " + *s->name + model + " " + *s->name + "SenderModel;");
+
7285 WriteLine();
+
7286 }
+
7287
+
7288 // Generate client receiver models accessors
+
7289 if (p->body)
+
7290 {
+
7291 WriteLineIndent("// Client receiver values accessors");
+
7292 for (const auto& s : p->body->structs)
+
7293 {
+
7294 if (s->message)
+
7295 {
+
7296 std::string struct_name = ConvertTypeName(domain, *p->name, *s->name, false);
+
7297 WriteLineIndent("private " + struct_name + " " + *s->name + "ReceiverValue;");
+
7298 }
+
7299 }
+
7300 WriteLine();
+
7301 WriteLineIndent("// Client receiver models accessors");
+
7302 for (const auto& s : p->body->structs)
+
7303 if (s->message)
+
7304 WriteLineIndent("private readonly " + *s->name + model + " " + *s->name + "ReceiverModel;");
+
7305 WriteLine();
+
7306 }
+
7307
+
7308 // Collect responses & rejects collections
+
7309 std::set<std::string> responses;
+
7310 std::map<std::string, bool> rejects;
+
7311 if (p->body)
+
7312 {
+
7313 for (const auto& s : p->body->structs)
+
7314 {
+
7315 if (s->message && s->request)
+
7316 {
+
7317 std::string response_type = (s->response) ? ConvertTypeName(*s->response->response, false) : "";
+
7318
+
7319 if (!response_type.empty())
+
7320 {
+
7321 // Update responses and rejects cache
+
7322 responses.insert(*s->response->response);
+
7323 if (s->rejects)
+
7324 for (const auto& reject : s->rejects->rejects)
+
7325 rejects[*reject.reject] = reject.global;
+
7326 }
+
7327 }
+
7328 }
+
7329 }
+
7330
+
7331 // Generate client requests cache fields
+
7332 if (!responses.empty())
+
7333 {
+
7334 WriteLineIndent("// Client requests cache fields");
+
7335 for (const auto& response : responses)
+
7336 {
+
7337 std::string response_name = response;
+
7338 std::string response_type = ConvertTypeName(domain, *p->name, response, false);
+
7339 CppCommon::StringUtils::ReplaceAll(response_name, ".", "");
+
7340
+
7341 WriteLineIndent("private Dictionary<Guid, Tuple<DateTime, TimeSpan, TaskCompletionSource<" + response_type + ">>> _requestsById" + response_name + ";");
+
7342 WriteLineIndent("private SortedDictionary<DateTime, Guid> _requestsByTimestamp" + response_name + ";");
+
7343 }
+
7344 WriteLine();
+
7345 }
+
7346
+
7347 // Generate client constructors
+
7348 WriteLineIndent("public " + client + "() : base(" + std::string(final ? "true" : "false") + ")");
+
7349 WriteLineIndent("{");
+
7350 Indent(1);
+
7351 if (p->import)
+
7352 for (const auto& import : p->import->imports)
+
7353 WriteLineIndent(*import + "Client = new " + *import + ".FBE." + client + "(SendBuffer, ReceiveBuffer);");
+
7354 if (p->body)
+
7355 {
+
7356 for (const auto& s : p->body->structs)
+
7357 {
+
7358 if (s->message)
+
7359 {
+
7360 std::string struct_name = ConvertTypeName(domain, *p->name, *s->name, false);
+
7361 WriteLineIndent(*s->name + "SenderModel = new " + *s->name + model + "(SendBuffer);");
+
7362 WriteLineIndent(*s->name + "ReceiverValue = " + struct_name + ".Default;");
+
7363 WriteLineIndent(*s->name + "ReceiverModel = new " + *s->name + model + "();");
+
7364 }
+
7365 }
+
7366 }
+
7367 if (!responses.empty())
+
7368 {
+
7369 for (const auto& response : responses)
+
7370 {
+
7371 std::string response_name = response;
+
7372 std::string response_type = ConvertTypeName(domain, *p->name, response, false);
+
7373 CppCommon::StringUtils::ReplaceAll(response_name, ".", "");
+
7374
+
7375 WriteLineIndent("_requestsById" + response_name + " = new Dictionary<Guid, Tuple<DateTime, TimeSpan, TaskCompletionSource<" + response_type + ">>>();");
+
7376 WriteLineIndent("_requestsByTimestamp" + response_name + " = new SortedDictionary<DateTime, Guid>();");
+
7377 }
+
7378 }
+
7379 Indent(-1);
+
7380 WriteLineIndent("}");
+
7381 WriteLineIndent("public " + client + "(" + domain + "FBE.Buffer sendBuffer, " + domain + "FBE.Buffer receiveBuffer) : base(sendBuffer, receiveBuffer, " + std::string(final ? "true" : "false") + ")");
+
7382 WriteLineIndent("{");
+
7383 Indent(1);
+
7384 if (p->import)
+
7385 for (const auto& import : p->import->imports)
+
7386 WriteLineIndent(*import + "Client = new " + *import + ".FBE." + client + "(SendBuffer, ReceiveBuffer);");
+
7387 if (p->body)
+
7388 {
+
7389 for (const auto& s : p->body->structs)
+
7390 {
+
7391 if (s->message)
+
7392 {
+
7393 std::string struct_name = ConvertTypeName(domain, *p->name, *s->name, false);
+
7394 WriteLineIndent(*s->name + "SenderModel = new " + *s->name + model + "(SendBuffer);");
+
7395 WriteLineIndent(*s->name + "ReceiverValue = " + struct_name + ".Default;");
+
7396 WriteLineIndent(*s->name + "ReceiverModel = new " + *s->name + model + "();");
+
7397 }
+
7398 }
+
7399 }
+
7400 if (!responses.empty())
+
7401 {
+
7402 for (const auto& response : responses)
+
7403 {
+
7404 std::string response_name = response;
+
7405 std::string response_type = ConvertTypeName(domain, *p->name, response, false);
+
7406 CppCommon::StringUtils::ReplaceAll(response_name, ".", "");
+
7407
+
7408 WriteLineIndent("_requestsById" + response_name + " = new Dictionary<Guid, Tuple<DateTime, TimeSpan, TaskCompletionSource<" + response_type + ">>>();");
+
7409 WriteLineIndent("_requestsByTimestamp" + response_name + " = new SortedDictionary<DateTime, Guid>();");
+
7410 }
+
7411 }
+
7412 Indent(-1);
+
7413 WriteLineIndent("}");
+
7414
+
7415 // Generate request methods
+
7416 if (p->body)
+
7417 {
+
7418 for (const auto& s : p->body->structs)
+
7419 {
+
7420 if (s->message && s->request)
+
7421 {
+
7422 std::string request_name = *s->name;
+
7423 std::string request_type = ConvertTypeName(domain, *p->name, *s->name, false);
+
7424 std::string response_type = (s->response) ? ConvertTypeName(domain, *p->name, *s->response->response, false) : "";
+
7425 std::string response_field = (s->response) ? *s->response->response : "";
+
7426 CppCommon::StringUtils::ReplaceAll(request_name, ".", "");
+
7427 CppCommon::StringUtils::ReplaceAll(response_field, ".", "");
+
7428
+
7429 WriteLine();
+
7430 if (response_type.empty())
+
7431 {
+
7432 WriteLineIndent("public Task Request(" + request_type + " value) { return RequestListener(this, value, TimeSpan.Zero); }");
+
7433 WriteLineIndent("public Task Request(" + request_type + " value, TimeSpan timeout) { return RequestListener(this, value, timeout); }");
+
7434 WriteLineIndent("public Task RequestListener(" + listener + " listener, " + request_type + " value) { return RequestListener(listener, value, TimeSpan.Zero); }");
+
7435 WriteLineIndent("public Task RequestListener(" + listener + " listener, " + request_type + " value, TimeSpan timeout)");
+
7436 WriteLineIndent("{");
+
7437 Indent(1);
+
7438 WriteLineIndent("var source = new TaskCompletionSource();");
+
7439 WriteLineIndent("Task task = source.Task;");
+
7440 WriteLine();
+
7441 WriteLineIndent("// Send the request message");
+
7442 WriteLineIndent("long serialized = SendListener(listener, value);");
+
7443 WriteLineIndent("if (serialized > 0)");
+
7444 Indent(1);
+
7445 WriteLineIndent("source.SetResult();");
+
7446 Indent(-1);
+
7447 WriteLineIndent("else");
+
7448 Indent(1);
+
7449 WriteLineIndent("source.SetException(new Exception(\"Send request failed!\"));");
+
7450 Indent(-1);
+
7451 WriteLine();
+
7452 WriteLineIndent("return task;");
+
7453 Indent(-1);
+
7454 WriteLineIndent("}");
+
7455 }
+
7456 else
+
7457 {
+
7458 WriteLineIndent("public Task<" + response_type + "> Request(" + request_type + " value) { return RequestListener(this, value, TimeSpan.Zero); }");
+
7459 WriteLineIndent("public Task<" + response_type + "> Request(" + request_type + " value, TimeSpan timeout) { return RequestListener(this, value, timeout); }");
+
7460 WriteLineIndent("public Task<" + response_type + "> RequestListener(" + listener + " listener, " + request_type + " value) { return RequestListener(listener, value, TimeSpan.Zero); }");
+
7461 WriteLineIndent("public Task<" + response_type + "> RequestListener(" + listener + " listener, " + request_type + " value, TimeSpan timeout)");
+
7462 WriteLineIndent("{");
+
7463 Indent(1);
+
7464 WriteLineIndent("lock (Lock)");
+
7465 WriteLineIndent("{");
+
7466 Indent(1);
+
7467 WriteLineIndent("var source = new TaskCompletionSource<" + response_type + ">();");
+
7468 WriteLineIndent("Task<" + response_type + "> task = source.Task;");
+
7469 WriteLine();
+
7470 WriteLineIndent("DateTime current = DateTime.UtcNow;");
+
7471 WriteLine();
+
7472 WriteLineIndent("// Send the request message");
+
7473 WriteLineIndent("long serialized = SendListener(listener, value);");
+
7474 WriteLineIndent("if (serialized > 0)");
+
7475 WriteLineIndent("{");
+
7476 Indent(1);
+
7477 WriteLineIndent("// Calculate the unique timestamp");
+
7478 WriteLineIndent("Timestamp = (current <= Timestamp) ? new DateTime(Timestamp.Ticks + 1) : current;");
+
7479 WriteLine();
+
7480 WriteLineIndent("// Register the request");
+
7481 WriteLineIndent("_requestsById" + response_field + ".Add(value.id, new Tuple<DateTime, TimeSpan, TaskCompletionSource<" + response_type + ">>(Timestamp, timeout, source));");
+
7482 WriteLineIndent("if (timeout.Ticks > 0)");
+
7483 Indent(1);
+
7484 WriteLineIndent("_requestsByTimestamp" + response_field + ".Add(Timestamp, value.id);");
+
7485 Indent(-1);
+
7486 Indent(-1);
+
7487 WriteLineIndent("}");
+
7488 WriteLineIndent("else");
+
7489 Indent(1);
+
7490 WriteLineIndent("source.SetException(new Exception(\"Send request failed!\"));");
+
7491 Indent(-1);
+
7492 WriteLine();
+
7493 WriteLineIndent("return task;");
+
7494 Indent(-1);
+
7495 WriteLineIndent("}");
+
7496 Indent(-1);
+
7497 WriteLineIndent("}");
+
7498 }
+
7499 }
+
7500 }
+
7501 }
+
7502
+
7503 // Generate client send method
+
7504 WriteLine();
+
7505 WriteLineIndent("public long Send(object obj) { return SendListener(this, obj); }");
+
7506 WriteLineIndent("public long SendListener(" + listener + " listener, object obj)");
+
7507 WriteLineIndent("{");
+
7508 Indent(1);
+
7509 if (p->body)
+
7510 {
+
7511 WriteLineIndent("switch (obj)");
+
7512 WriteLineIndent("{");
+
7513 Indent(1);
+
7514 for (const auto& s : p->body->structs)
+
7515 {
+
7516 if (s->message)
+
7517 {
+
7518 std::string struct_name = ConvertTypeName(domain, *p->name, *s->name, false);
+
7519 WriteLineIndent("case " + struct_name + " value when value.FBEType == " + struct_name + ".FBETypeConst: return SendListener(listener, value);");
+
7520 }
+
7521 }
+
7522 WriteLineIndent("default: break;");
+
7523 Indent(-1);
+
7524 WriteLineIndent("}");
+
7525 WriteLine();
+
7526 }
+
7527 if (p->import)
+
7528 {
+
7529 WriteLineIndent("long result;");
+
7530 for (const auto& import : p->import->imports)
+
7531 {
+
7532 WriteLineIndent("result = " + *import + "Client.SendListener(listener, obj);");
+
7533 WriteLineIndent("if (result > 0)");
+
7534 Indent(1);
+
7535 WriteLineIndent("return result;");
+
7536 Indent(-1);
+
7537 }
+
7538 WriteLine();
+
7539 }
+
7540 WriteLineIndent("return 0;");
+
7541 Indent(-1);
+
7542 WriteLineIndent("}");
+
7543 WriteLine();
+
7544
+
7545 // Generate client send methods
+
7546 if (p->body)
+
7547 {
+
7548 for (const auto& s : p->body->structs)
+
7549 {
+
7550 if (s->message)
+
7551 {
+
7552 std::string struct_name = ConvertTypeName(domain, *p->name, *s->name, false);
+
7553 WriteLineIndent("public long Send(" + struct_name + " value) { return SendListener(this, value); }");
+
7554 WriteLineIndent("public long SendListener(" + listener + " listener, " + struct_name + " value)");
+
7555 WriteLineIndent("{");
+
7556 Indent(1);
+
7557 WriteLineIndent("// Serialize the value into the FBE stream");
+
7558 WriteLineIndent("long serialized = " + *s->name + "SenderModel.Serialize(value);");
+
7559 WriteLineIndent("Debug.Assert((serialized > 0), \"" + domain + *p->name + "." + *s->name + " serialization failed!\");");
+
7560 WriteLineIndent("Debug.Assert(" + *s->name + "SenderModel.Verify(), \"" + domain + *p->name + "." + *s->name + " validation failed!\");");
+
7561 WriteLine();
+
7562 WriteLineIndent("// Log the value");
+
7563 WriteLineIndent("if (Logging)");
+
7564 WriteLineIndent("{");
+
7565 Indent(1);
+
7566 WriteLineIndent("string message = value.ToString();");
+
7567 WriteLineIndent("listener.OnSendLog(message);");
+
7568 Indent(-1);
+
7569 WriteLineIndent("}");
+
7570 WriteLine();
+
7571 WriteLineIndent("// Send the serialized value");
+
7572 WriteLineIndent("return SendSerialized(listener, serialized);");
+
7573 Indent(-1);
+
7574 WriteLineIndent("}");
+
7575 }
+
7576 }
+
7577 }
+
7578
+
7579 // Generate response handlers
+
7580 for (const auto& response : responses)
+
7581 {
+
7582 std::string response_name = response;
+
7583 std::string response_type = ConvertTypeName(domain, *p->name, response, false);
+
7584 CppCommon::StringUtils::ReplaceAll(response_name, ".", "");
+
7585
+
7586 WriteLine();
+
7587 WriteLineIndent("public bool OnReceiveResponse(" + response_type + " response)");
+
7588 WriteLineIndent("{");
+
7589 Indent(1);
+
7590 WriteLineIndent("ReceivedResponse_" + response_name + "?.Invoke(response);");
+
7591 WriteLine();
+
7592 if (p->body)
+
7593 {
+
7594 std::set<std::string> cache;
+
7595 WriteLineIndent("lock (Lock)");
+
7596 WriteLineIndent("{");
+
7597 Indent(1);
+
7598 for (const auto& s : p->body->structs)
+
7599 {
+
7600 if (s->message && s->response)
+
7601 {
+
7602 std::string struct_response_name = *s->response->response;
+
7603 std::string struct_response_type = ConvertTypeName(domain, *p->name, *s->response->response, false);
+
7604 CppCommon::StringUtils::ReplaceAll(struct_response_name, ".", "");
+
7605
+
7606 if ((struct_response_type == response_type) && (cache.find(struct_response_type) == cache.end()))
+
7607 {
+
7608 WriteLineIndent("if (_requestsById" + struct_response_name + ".TryGetValue(response.id, out Tuple<DateTime, TimeSpan, TaskCompletionSource<" + struct_response_type + ">> tuple))");
+
7609 WriteLineIndent("{");
+
7610 Indent(1);
+
7611 WriteLineIndent("var timestamp = tuple.Item1;");
+
7612 WriteLineIndent("var timespan = tuple.Item2;");
+
7613 WriteLineIndent("var source = tuple.Item3;");
+
7614 WriteLineIndent("source.SetResult(response);");
+
7615 WriteLineIndent("_requestsById" + struct_response_name + ".Remove(response.id);");
+
7616 WriteLineIndent("_requestsByTimestamp" + struct_response_name + ".Remove(timestamp);");
+
7617 WriteLineIndent("return true;");
+
7618 cache.insert(struct_response_type);
+
7619 Indent(-1);
+
7620 WriteLineIndent("}");
+
7621 WriteLine();
+
7622 }
+
7623 }
+
7624 }
+
7625 }
+
7626 WriteLineIndent("return false;");
+
7627 Indent(-1);
+
7628 WriteLineIndent("}");
+
7629 Indent(-1);
+
7630 WriteLineIndent("}");
+
7631 }
+
7632
+
7633 // Generate remaining response handlers
+
7634 if (p->body)
+
7635 {
+
7636 bool found = false;
+
7637 std::set<std::string> cache;
+
7638 for (const auto& s : p->body->structs)
+
7639 {
+
7640 if (s->message)
+
7641 {
+
7642 std::string struct_response_name = *s->name;
+
7643 std::string struct_response_type = ConvertTypeName(domain, *p->name, *s->name, false);
+
7644 CppCommon::StringUtils::ReplaceAll(struct_response_name, ".", "");
+
7645
+
7646 if ((responses.find(*s->name) == responses.end()) && (cache.find(struct_response_type) == cache.end()))
+
7647 {
+
7648 if (!found)
+
7649 WriteLine();
+
7650 WriteLineIndent("public bool OnReceiveResponse(" + struct_response_type + " response) { ReceivedResponse_" + struct_response_name + "?.Invoke(response); return false; }");
+
7651 cache.insert(struct_response_type);
+
7652 found = true;
+
7653 }
+
7654 }
+
7655 }
+
7656 }
+
7657
+
7658 // Generate reject handlers
+
7659 for (const auto& reject : rejects)
+
7660 {
+
7661 std::string reject_name = reject.first;
+
7662 std::string reject_type = ConvertTypeName(domain, *p->name, reject.first, false);
+
7663 bool global = reject.second;
+
7664 bool imported = CppCommon::StringUtils::ReplaceAll(reject_name, ".", "");
+
7665 CppCommon::StringUtils::ReplaceAll(reject_name, ".", "");
+
7666
+
7667 WriteLine();
+
7668 WriteLineIndent("public bool OnReceiveReject(" + reject_type + " reject)");
+
7669 WriteLineIndent("{");
+
7670 Indent(1);
+
7671 WriteLineIndent("ReceivedReject_" + reject_name + "?.Invoke(reject);");
+
7672 WriteLine();
+
7673 if (global)
+
7674 {
+
7675 if (p->import)
+
7676 {
+
7677 for (const auto& import : p->import->imports)
+
7678 {
+
7679 WriteLineIndent("if (" + *import + "Client.OnReceiveReject(reject))");
+
7680 Indent(1);
+
7681 WriteLineIndent("return true;");
+
7682 Indent(-1);
+
7683 }
+
7684 WriteLine();
+
7685 }
+
7686 }
+
7687 else if (imported)
+
7688 {
+
7689 std::string ns = "";
+
7690 std::string t = reject.first;
+
7691 std::string type = reject.first;
+
7692
+
7693 size_t pos = type.find_last_of('.');
+
7694 if (pos != std::string::npos)
+
7695 {
+
7696 ns.assign(type, 0, pos);
+
7697 t.assign(type, pos + 1, type.size() - pos);
+
7698 }
+
7699
+
7700 WriteLineIndent("if (" + ns + "Client.OnReceiveReject(reject))");
+
7701 Indent(1);
+
7702 WriteLineIndent("return true;");
+
7703 Indent(-1);
+
7704 WriteLine();
+
7705 }
+
7706 if (p->body)
+
7707 {
+
7708 std::set<std::string> cache;
+
7709 WriteLineIndent("lock (Lock)");
+
7710 WriteLineIndent("{");
+
7711 Indent(1);
+
7712 WriteLine();
+
7713 for (const auto& s : p->body->structs)
+
7714 {
+
7715 if (s->message && s->response && s->rejects)
+
7716 {
+
7717 for (const auto& r : s->rejects->rejects)
+
7718 {
+
7719 std::string struct_response_name = *s->response->response;
+
7720 std::string struct_response_type = ConvertTypeName(domain, *p->name, *s->response->response, false);
+
7721 CppCommon::StringUtils::ReplaceAll(struct_response_name, ".", "");
+
7722
+
7723 std::string struct_reject_name = *r.reject;
+
7724 std::string struct_reject_type = ConvertTypeName(domain, *p->name, *r.reject, false);
+
7725 CppCommon::StringUtils::ReplaceAll(struct_reject_name, ".", "");
+
7726
+
7727 if ((struct_reject_type == reject_type) && (cache.find(struct_response_name) == cache.end()))
+
7728 {
+
7729 WriteLineIndent("if (_requestsById" + struct_response_name + ".TryGetValue(reject.id, out Tuple<DateTime, TimeSpan, TaskCompletionSource<" + struct_response_type + ">> tuple" + struct_response_name + "))");
+
7730 WriteLineIndent("{");
+
7731 Indent(1);
+
7732 WriteLineIndent("var timestamp = tuple" + struct_response_name + ".Item1;");
+
7733 WriteLineIndent("var timespan = tuple" + struct_response_name + ".Item2;");
+
7734 WriteLineIndent("var source = tuple" + struct_response_name + ".Item3;");
+
7735 WriteLineIndent("source.SetException(new Exception(reject.ToString()));");
+
7736 WriteLineIndent("_requestsById" + struct_response_name + ".Remove(reject.id);");
+
7737 WriteLineIndent("_requestsByTimestamp" + struct_response_name + ".Remove(timestamp);");
+
7738 WriteLineIndent("return true;");
+
7739 cache.insert(struct_response_name);
+
7740 Indent(-1);
+
7741 WriteLineIndent("}");
+
7742 WriteLine();
+
7743 }
+
7744 }
+
7745 }
+
7746 }
+
7747 }
+
7748 WriteLineIndent("return false;");
+
7749 Indent(-1);
+
7750 WriteLineIndent("}");
+
7751 Indent(-1);
+
7752 WriteLineIndent("}");
+
7753 }
+
7754
+
7755 // Generate remaining reject handlers
+
7756 if (p->body)
+
7757 {
+
7758 bool found = false;
+
7759 std::set<std::string> cache;
+
7760 for (const auto& s : p->body->structs)
+
7761 {
+
7762 if (s->message)
+
7763 {
+
7764 std::string struct_reject_name = *s->name;
+
7765 std::string struct_reject_type = ConvertTypeName(domain, *p->name, *s->name, false);
+
7766 CppCommon::StringUtils::ReplaceAll(struct_reject_name, ".", "");
+
7767
+
7768 if ((rejects.find(*s->name) == rejects.end()) && (cache.find(struct_reject_type) == cache.end()))
+
7769 {
+
7770 if (!found)
+
7771 WriteLine();
+
7772 WriteLineIndent("public bool OnReceiveReject(" + struct_reject_type + " reject) { ReceivedReject_" + struct_reject_name + "?.Invoke(reject); return false; }");
+
7773 cache.insert(struct_reject_type);
+
7774 found = true;
+
7775 }
+
7776 }
+
7777 }
+
7778 }
+
7779
+
7780 // Generate notify handlers
+
7781 if (p->body)
+
7782 {
+
7783 bool found = false;
+
7784 std::set<std::string> cache;
+
7785 for (const auto& s : p->body->structs)
+
7786 {
+
7787 if (s->message)
+
7788 {
+
7789 std::string struct_notify_name = *s->name;
+
7790 std::string struct_notify_type = ConvertTypeName(domain, *p->name, *s->name, false);
+
7791 CppCommon::StringUtils::ReplaceAll(struct_notify_name, ".", "");
+
7792
+
7793 if (cache.find(struct_notify_type) == cache.end())
+
7794 {
+
7795 if (!found)
+
7796 WriteLine();
+
7797 WriteLineIndent("public void OnReceiveNotify(" + struct_notify_type + " notify) { ReceivedNotify_" + struct_notify_name + "?.Invoke(notify); }");
+
7798 cache.insert(struct_notify_type);
+
7799 found = true;
+
7800 }
+
7801 }
+
7802 }
+
7803 }
+
7804
+
7805 // Generate receive handlers
+
7806 if (p->body)
+
7807 {
+
7808 bool found = false;
+
7809 std::set<std::string> cache;
+
7810 for (const auto& s : p->body->structs)
+
7811 {
+
7812 if (s->message)
+
7813 {
+
7814 std::string struct_response_name = *s->name;
+
7815 std::string struct_response_type = ConvertTypeName(domain, *p->name, *s->name, false);
+
7816 CppCommon::StringUtils::ReplaceAll(struct_response_name, ".", "");
+
7817
+
7818 if (cache.find(struct_response_type) == cache.end())
+
7819 {
+
7820 if (!found)
+
7821 WriteLine();
+
7822 WriteLineIndent("public void OnReceive(" + struct_response_type + " value) { if (!OnReceiveResponse(value) && !OnReceiveReject(value)) OnReceiveNotify(value); }");
+
7823 cache.insert(struct_response_type);
+
7824 found = true;
+
7825 }
+
7826 }
+
7827 }
+
7828 }
+
7829
+
7830 // Generate reset requests method
+
7831 WriteLine();
+
7832 WriteLineIndent("// Reset client requests");
+
7833 WriteLineIndent("internal override void ResetRequests()");
+
7834 WriteLineIndent("{");
+
7835 Indent(1);
+
7836 WriteLineIndent("base.ResetRequests();");
+
7837 if (p->import)
+
7838 {
+
7839 WriteLine();
+
7840 for (const auto& import : p->import->imports)
+
7841 WriteLineIndent(*import + "Client.ResetRequests();");
+
7842 }
+
7843 for (const auto& response : responses)
+
7844 {
+
7845 std::string response_name = response;
+
7846 std::string response_type = ConvertTypeName(domain, *p->name, response, false);
+
7847 CppCommon::StringUtils::ReplaceAll(response_name, ".", "");
+
7848
+
7849 WriteLine();
+
7850 WriteLineIndent("foreach(var request in _requestsById" + response_name + ")");
+
7851 Indent(1);
+
7852 WriteLineIndent("request.Value.Item3.SetException(new Exception(\"Reset client!\"));");
+
7853 Indent(-1);
+
7854 WriteLineIndent("_requestsById" + response_name + ".Clear();");
+
7855 WriteLineIndent("_requestsByTimestamp" + response_name + ".Clear();");
+
7856 }
+
7857 Indent(-1);
+
7858 WriteLineIndent("}");
+
7859
+
7860 // Generate watchdog requests method
+
7861 WriteLine();
+
7862 WriteLineIndent("// Watchdog client requests for timeouts");
+
7863 WriteLineIndent("internal override void WatchdogRequests(DateTime utc)");
+
7864 WriteLineIndent("{");
+
7865 Indent(1);
+
7866 WriteLineIndent("base.WatchdogRequests(utc);");
+
7867 if (p->import)
+
7868 {
+
7869 WriteLine();
+
7870 for (const auto& import : p->import->imports)
+
7871 WriteLineIndent(*import + "Client.WatchdogRequests(utc);");
+
7872 }
+
7873 for (const auto& response : responses)
+
7874 {
+
7875 std::string response_name = response;
+
7876 std::string response_type = ConvertTypeName(domain, *p->name, response, false);
+
7877 CppCommon::StringUtils::ReplaceAll(response_name, ".", "");
+
7878
+
7879 WriteLine();
+
7880 WriteLineIndent("while (_requestsByTimestamp" + response_name + ".Count > 0)");
+
7881 WriteLineIndent("{");
+
7882 Indent(1);
+
7883 WriteLineIndent("var request = _requestsByTimestamp" + response_name + ".First();");
+
7884 WriteLineIndent("Tuple<DateTime, TimeSpan, TaskCompletionSource<" + response_type + ">> tuple;");
+
7885 WriteLineIndent("_requestsById" + response_name + ".TryGetValue(request.Value, out tuple);");
+
7886 WriteLineIndent("var timestamp = tuple.Item1;");
+
7887 WriteLineIndent("var timespan = tuple.Item2;");
+
7888 WriteLineIndent("if ((timestamp + timespan) <= utc)");
+
7889 WriteLineIndent("{");
+
7890 Indent(1);
+
7891 WriteLineIndent("var source = tuple.Item3;");
+
7892 WriteLineIndent("source.SetException(new Exception(\"Timeout!\"));");
+
7893 WriteLineIndent("_requestsById" + response_name + ".Remove(request.Value);");
+
7894 WriteLineIndent("_requestsByTimestamp" + response_name + ".Remove(timestamp);");
+
7895 WriteLineIndent("continue;");
+
7896 Indent(-1);
+
7897 WriteLineIndent("}");
+
7898 WriteLineIndent("else");
+
7899 Indent(1);
+
7900 WriteLineIndent("break;");
+
7901 Indent(-1);
+
7902 Indent(-1);
+
7903 WriteLineIndent("}");
+
7904 }
+
7905 Indent(-1);
+
7906 WriteLineIndent("}");
+
7907
+
7908 // Generate receiver message handler
+
7909 WriteLine();
+
7910 WriteLineIndent("internal override bool OnReceive(long type, byte[] buffer, long offset, long size) { return OnReceiveListener(this, type, buffer, offset, size); }");
+
7911 WriteLineIndent("internal bool OnReceiveListener(" + listener + " listener, long type, byte[] buffer, long offset, long size)");
+
7912 WriteLineIndent("{");
+
7913 Indent(1);
+
7914 if (p->body)
+
7915 {
+
7916 WriteLineIndent("switch (type)");
+
7917 WriteLineIndent("{");
+
7918 Indent(1);
+
7919 for (const auto& s : p->body->structs)
+
7920 {
+
7921 if (s->message)
+
7922 {
+
7923 WriteLineIndent("case " + *s->name + model + ".FBETypeConst:");
+
7924 WriteLineIndent("{");
+
7925 Indent(1);
+
7926 WriteLineIndent("// Deserialize the value from the FBE stream");
+
7927 WriteLineIndent(*s->name + "ReceiverModel.Attach(buffer, offset);");
+
7928 WriteLineIndent("Debug.Assert(" + *s->name + "ReceiverModel.Verify(), \"" + domain + *p->name + "." + *s->name + " validation failed!\");");
+
7929 WriteLineIndent("long deserialized = " + *s->name + "ReceiverModel.Deserialize(out " + *s->name + "ReceiverValue);");
+
7930 WriteLineIndent("Debug.Assert((deserialized > 0), \"" + domain + *p->name + "." + *s->name + " deserialization failed!\");");
+
7931 WriteLine();
+
7932 WriteLineIndent("// Log the value");
+
7933 WriteLineIndent("if (Logging)");
+
7934 WriteLineIndent("{");
+
7935 Indent(1);
+
7936 WriteLineIndent("string message = " + *s->name + "ReceiverValue.ToString();");
+
7937 WriteLineIndent("listener.OnReceiveLog(message);");
+
7938 Indent(-1);
+
7939 WriteLineIndent("}");
+
7940 WriteLine();
+
7941 WriteLineIndent("// Call receive handler with deserialized value");
+
7942 WriteLineIndent("listener.OnReceive(" + *s->name + "ReceiverValue);");
+
7943 WriteLineIndent("return true;");
+
7944 Indent(-1);
+
7945 WriteLineIndent("}");
+
7946 }
+
7947 }
+
7948 WriteLineIndent("default: break;");
+
7949 Indent(-1);
+
7950 WriteLineIndent("}");
+
7951 WriteLine();
+
7952 }
+
7953 if (p->import)
+
7954 {
+
7955 for (const auto& import : p->import->imports)
+
7956 {
+
7957 WriteLineIndent("if (" + *import + "Client.OnReceiveListener(listener, type, buffer, offset, size))");
+
7958 Indent(1);
+
7959 WriteLineIndent("return true;");
+
7960 Indent(-1);
+
7961 }
+
7962 WriteLine();
+
7963 }
+
7964 WriteLineIndent("return false;");
+
7965 Indent(-1);
+
7966 WriteLineIndent("}");
+
7967
+
7968 WriteLine();
+
7969
+
7970 // Generate response events
+
7971 for (const auto& response : responses)
+
7972 {
+
7973 std::string response_name = response;
+
7974 std::string response_type = ConvertTypeName(domain, *p->name, response, false);
+
7975 CppCommon::StringUtils::ReplaceAll(response_name, ".", "");
+
7976
+
7977 WriteLineIndent("public delegate void ReceiveResponseHandler_" + response_name + "(" + response_type + " response);");
+
7978 WriteLineIndent("public event ReceiveResponseHandler_" + response_name + " ReceivedResponse_" + response_name + " = (response) => {};");
+
7979 }
+
7980 // Generate remaining response events
+
7981 if (p->body)
+
7982 {
+
7983 std::set<std::string> cache;
+
7984 for (const auto& s : p->body->structs)
+
7985 {
+
7986 if (s->message)
+
7987 {
+
7988 std::string struct_response_name = *s->name;
+
7989 std::string struct_response_type = ConvertTypeName(domain, *p->name, *s->name, false);
+
7990 CppCommon::StringUtils::ReplaceAll(struct_response_name, ".", "");
+
7991
+
7992 if ((responses.find(*s->name) == responses.end()) && (cache.find(struct_response_type) == cache.end()))
+
7993 {
+
7994 WriteLineIndent("public delegate void ReceiveResponseHandler_" + struct_response_name + "(" + struct_response_type + " response);");
+
7995 WriteLineIndent("public event ReceiveResponseHandler_" + struct_response_name + " ReceivedResponse_" + struct_response_name + " = (response) => {};");
+
7996 cache.insert(struct_response_type);
+
7997 }
+
7998 }
+
7999 }
+
8000 }
+
8001
+
8002 // Generate reject events
+
8003 for (const auto& reject : rejects)
+
8004 {
+
8005 std::string reject_name = reject.first;
+
8006 std::string reject_type = ConvertTypeName(domain, *p->name, reject.first, false);
+
8007 CppCommon::StringUtils::ReplaceAll(reject_name, ".", "");
+
8008
+
8009 WriteLineIndent("public delegate void ReceiveRejectHandler_" + reject_name + "(" + reject_type + " reject);");
+
8010 WriteLineIndent("public event ReceiveRejectHandler_" + reject_name + " ReceivedReject_" + reject_name + " = (reject) => {};");
+
8011 }
+
8012 // Generate remaining reject events
+
8013 if (p->body)
+
8014 {
+
8015 std::set<std::string> cache;
+
8016 for (const auto& s : p->body->structs)
+
8017 {
+
8018 if (s->message)
+
8019 {
+
8020 std::string struct_reject_name = *s->name;
+
8021 std::string struct_reject_type = ConvertTypeName(domain, *p->name, *s->name, false);
+
8022 CppCommon::StringUtils::ReplaceAll(struct_reject_name, ".", "");
+
8023
+
8024 if ((rejects.find(*s->name) == rejects.end()) && (cache.find(struct_reject_type) == cache.end()))
+
8025 {
+
8026 WriteLineIndent("public delegate void ReceiveRejectHandler_" + struct_reject_name + "(" + struct_reject_type + " reject);");
+
8027 WriteLineIndent("public event ReceiveRejectHandler_" + struct_reject_name + " ReceivedReject_" + struct_reject_name + " = (reject) => {};");
+
8028 cache.insert(struct_reject_type);
+
8029 }
+
8030 }
+
8031 }
+
8032 }
+
8033
+
8034 // Generate notify events
+
8035 if (p->body)
+
8036 {
+
8037 std::set<std::string> cache;
+
8038 for (const auto& s : p->body->structs)
+
8039 {
+
8040 if (s->message)
+
8041 {
+
8042 std::string struct_notify_name = *s->name;
+
8043 std::string struct_notify_type = ConvertTypeName(domain, *p->name, *s->name, false);
+
8044 CppCommon::StringUtils::ReplaceAll(struct_notify_name, ".", "");
+
8045
+
8046 if (cache.find(struct_notify_type) == cache.end())
+
8047 {
+
8048 WriteLineIndent("public delegate void ReceiveNotifyHandler_" + struct_notify_name + "(" + struct_notify_type + " notify);");
+
8049 WriteLineIndent("public event ReceiveNotifyHandler_" + struct_notify_name + " ReceivedNotify_" + struct_notify_name + " = (notify) => {};");
+
8050 cache.insert(struct_notify_type);
+
8051 }
+
8052 }
+
8053 }
+
8054 }
+
8055
+
8056 // Generate client end
+
8057 Indent(-1);
+
8058 WriteLineIndent("}");
+
8059
+
8060 // Generate namespace end
+
8061 Indent(-1);
+
8062 WriteLine();
+
8063 WriteLineIndent("} // namespace " + domain + *p->name + ".FBE");
+
8064}
+
8065
+
8066bool GeneratorCSharp::IsKnownType(const std::string& type)
+
8067{
+
8068 return ((type == "bool") ||
+
8069 (type == "byte") || (type == "bytes") ||
+
8070 (type == "char") || (type == "wchar") ||
+
8071 (type == "int8") || (type == "uint8") ||
+
8072 (type == "int16") || (type == "uint16") ||
+
8073 (type == "int32") || (type == "uint32") ||
+
8074 (type == "int64") || (type == "uint64") ||
+
8075 (type == "float") || (type == "double") ||
+
8076 (type == "decimal") || (type == "string") ||
+
8077 (type == "timestamp") || (type == "uuid"));
+
8078}
+
8079
+
8080bool GeneratorCSharp::IsReferenceType(const std::string& type)
+
8081{
+
8082 return ((type == "bytes") || (type == "string"));
+
8083}
+
8084
+
8085std::string GeneratorCSharp::ConvertEnumRead(const std::string& type)
+
8086{
+
8087 if (type == "byte")
+
8088 return "ReadByte";
+
8089 else if (type == "char")
+
8090 return "ReadUInt8";
+
8091 else if (type == "wchar")
+
8092 return "ReadUInt32";
+
8093 else if (type == "int8")
+
8094 return "ReadInt8";
+
8095 else if (type == "uint8")
+
8096 return "ReadUInt8";
+
8097 else if (type == "int16")
+
8098 return "ReadInt16";
+
8099 else if (type == "uint16")
+
8100 return "ReadUInt16";
+
8101 else if (type == "int32")
+
8102 return "ReadInt32";
+
8103 else if (type == "uint32")
+
8104 return "ReadUInt32";
+
8105 else if (type == "int64")
+
8106 return "ReadInt64";
+
8107 else if (type == "uint64")
+
8108 return "ReadUInt64";
+
8109
+
8110 yyerror("Unsupported enum base type - " + type);
+
8111 return "";
+
8112}
+
8113
+
8114std::string GeneratorCSharp::ConvertEnumSize(const std::string& type)
+
8115{
+
8116 if (type == "byte")
+
8117 return "1";
+
8118 else if (type == "char")
+
8119 return "1";
+
8120 else if (type == "wchar")
+
8121 return "4";
+
8122 else if (type == "int8")
+
8123 return "1";
+
8124 else if (type == "uint8")
+
8125 return "1";
+
8126 else if (type == "int16")
+
8127 return "2";
+
8128 else if (type == "uint16")
+
8129 return "2";
+
8130 else if (type == "int32")
+
8131 return "4";
+
8132 else if (type == "uint32")
+
8133 return "4";
+
8134 else if (type == "int64")
+
8135 return "8";
+
8136 else if (type == "uint64")
+
8137 return "8";
+
8138
+
8139 yyerror("Unsupported enum base type - " + type);
+
8140 return "";
+
8141}
+
8142
+
8143std::string GeneratorCSharp::ConvertEnumType(const std::string& type)
+
8144{
+
8145 if (type == "byte")
+
8146 return "byte";
+
8147 else if (type == "char")
+
8148 return "byte";
+
8149 else if (type == "wchar")
+
8150 return "ushort";
+
8151 else if (type == "int8")
+
8152 return "sbyte";
+
8153 else if (type == "uint8")
+
8154 return "byte";
+
8155 else if (type == "int16")
+
8156 return "short";
+
8157 else if (type == "uint16")
+
8158 return "ushort";
+
8159 else if (type == "int32")
+
8160 return "int";
+
8161 else if (type == "uint32")
+
8162 return "uint";
+
8163 else if (type == "int64")
+
8164 return "long";
+
8165 else if (type == "uint64")
+
8166 return "ulong";
+
8167
+
8168 yyerror("Unsupported enum base type - " + type);
+
8169 return "";
+
8170}
+
8171
+
8172std::string GeneratorCSharp::ConvertEnumTypeUtf8Json(const std::string& type)
+
8173{
+
8174 if (type == "byte")
+
8175 return "Byte";
+
8176 else if (type == "char")
+
8177 return "Byte";
+
8178 else if (type == "wchar")
+
8179 return "UInt16";
+
8180 else if (type == "int8")
+
8181 return "SByte";
+
8182 else if (type == "uint8")
+
8183 return "Byte";
+
8184 else if (type == "int16")
+
8185 return "Int16";
+
8186 else if (type == "uint16")
+
8187 return "UInt16";
+
8188 else if (type == "int32")
+
8189 return "Int32";
+
8190 else if (type == "uint32")
+
8191 return "UInt32";
+
8192 else if (type == "int64")
+
8193 return "Int64";
+
8194 else if (type == "uint64")
+
8195 return "UInt64";
+
8196
+
8197 yyerror("Unsupported enum base type - " + type);
+
8198 return "";
+
8199}
+
8200
+
8201std::string GeneratorCSharp::ConvertEnumConstant(const std::string& type, const std::string& value)
+
8202{
+
8203 std::string result = value;
+
8204
+
8205 // Fill flags values
+
8206 std::vector<std::string> flags = CppCommon::StringUtils::Split(result, '|', true);
+
8207
+
8208 // Generate flags combination
+
8209 if (flags.size() > 1)
+
8210 {
+
8211 result = "";
+
8212 bool first = true;
+
8213 for (const auto& it : flags)
+
8214 {
+
8215 std::string flag = CppCommon::StringUtils::ToTrim(it);
+
8216 result += (first ? "" : "_ | _") + flag;
+
8217 first = false;
+
8218 }
+
8219 }
+
8220
+
8221 return ConvertEnumConstantPrefix(type) + result + ConvertEnumConstantSuffix(type);
+
8222}
+
8223
+
8224std::string GeneratorCSharp::ConvertEnumConstantPrefix(const std::string& type)
+
8225{
+
8226 if (type == "byte")
+
8227 return "(byte)";
+
8228 else if (type == "char")
+
8229 return "(byte)";
+
8230 else if (type == "wchar")
+
8231 return "(ushort)";
+
8232 else if (type == "int8")
+
8233 return "(sbyte)";
+
8234 else if (type == "uint8")
+
8235 return "(byte)";
+
8236 else if (type == "int16")
+
8237 return "(short)";
+
8238 else if (type == "uint16")
+
8239 return "(ushort)";
+
8240 else if (type == "int32")
+
8241 return "(int)";
+
8242 else if (type == "uint32")
+
8243 return "(uint)";
+
8244 else if (type == "int64")
+
8245 return "(long)";
+
8246 else if (type == "uint64")
+
8247 return "(ulong)";
+
8248
+
8249 return "";
+
8250}
+
8251
+
8252std::string GeneratorCSharp::ConvertEnumConstantSuffix(const std::string& type)
+
8253{
+
8254 if ((type == "byte") || (type == "uint8") || (type == "uint16") || (type == "uint32"))
+
8255 return "U";
+
8256 else if (type == "int64")
+
8257 return "L";
+
8258 else if (type == "uint64")
+
8259 return "UL";
+
8260
+
8261 return "";
+
8262}
+
8263
+
8264std::string GeneratorCSharp::ConvertBaseTypeName(const std::string& type)
+
8265{
+
8266 return CppCommon::StringUtils::ToUpper(type);
+
8267}
+
8268
+
8269std::string GeneratorCSharp::ConvertTypeName(const std::string& type, bool optional)
+
8270{
+
8271 if (optional)
+
8272 {
+
8273 if (type == "bytes")
+
8274 return "MemoryStream";
+
8275 if (type == "string")
+
8276 return "string";
+
8277
+
8278 return ConvertTypeName(type, false) + "?";
+
8279 }
+
8280
+
8281 if (type == "bool")
+
8282 return "bool";
+
8283 else if (type == "byte")
+
8284 return "byte";
+
8285 else if (type == "bytes")
+
8286 return "MemoryStream";
+
8287 else if (type == "char")
+
8288 return "char";
+
8289 else if (type == "wchar")
+
8290 return "char";
+
8291 else if (type == "int8")
+
8292 return "sbyte";
+
8293 else if (type == "uint8")
+
8294 return "byte";
+
8295 else if (type == "int16")
+
8296 return "short";
+
8297 else if (type == "uint16")
+
8298 return "ushort";
+
8299 else if (type == "int32")
+
8300 return "int";
+
8301 else if (type == "uint32")
+
8302 return "uint";
+
8303 else if (type == "int64")
+
8304 return "long";
+
8305 else if (type == "uint64")
+
8306 return "ulong";
+
8307 else if (type == "float")
+
8308 return "float";
+
8309 else if (type == "double")
+
8310 return "double";
+
8311 else if (type == "decimal")
+
8312 return "decimal";
+
8313 else if (type == "string")
+
8314 return "string";
+
8315 else if (type == "timestamp")
+
8316 return "DateTime";
+
8317 else if (type == "uuid")
+
8318 return "Guid";
+
8319
+
8320 return type;
+
8321}
+
8322
+
8323std::string GeneratorCSharp::ConvertTypeName(const std::string& domain, const std::string& package, const std::string& type, bool optional)
+
8324{
+
8325 return (CppCommon::StringUtils::Contains(type, '.') ? "" : ("global::" + domain + package + ".")) + ConvertTypeName(type, optional);
+
8326}
+
8327
+
8328std::string GeneratorCSharp::ConvertTypeName(const StructField& field)
+
8329{
+
8330 if (field.array)
+
8331 return ConvertTypeName(*field.type, field.optional) + "[]";
+
8332 else if (field.vector)
+
8333 return "List<" + ConvertTypeName(*field.type, field.optional) + ">";
+
8334 else if (field.list)
+
8335 return "LinkedList<" + ConvertTypeName(*field.type, field.optional) + ">";
+
8336 else if (field.set)
+
8337 return "HashSet<" + ConvertTypeName(*field.key, false) + ">";
+
8338 else if (field.map)
+
8339 return "SortedDictionary<" + ConvertTypeName(*field.key, false) + ", " + ConvertTypeName(*field.type, field.optional) +">";
+
8340 else if (field.hash)
+
8341 return "Dictionary<" + ConvertTypeName(*field.key, false) + ", " + ConvertTypeName(*field.type, field.optional) +">";
+
8342
+
8343 return ConvertTypeName(*field.type, field.optional);
+
8344}
+
8345
+
8346std::string GeneratorCSharp::ConvertTypeFieldName(const std::string& domain, const std::string& package, const std::string& type, bool final)
+
8347{
+
8348 std::string modelType = final ? "Final" : "Field";
+
8349
+
8350 std::string ns = domain + package + ".FBE.";
+
8351 std::string t = type;
+
8352
+
8353 size_t pos = type.find_last_of('.');
+
8354 if (pos != std::string::npos)
+
8355 {
+
8356 ns.assign(type, 0, pos + 1);
+
8357 ns = domain + ns + "FBE.";
+
8358 t.assign(type, pos + 1, type.size() - pos);
+
8359 }
+
8360
+
8361 return ns + modelType + "Model" + ConvertTypeName(t, false);
+
8362}
+
8363
+
8364std::string GeneratorCSharp::ConvertTypeFieldDeclaration(const std::string& domain, const std::string& package, const StructField& field, bool final)
+
8365{
+
8366 std::string modelType = final ? "Final" : "Field";
+
8367
+
8368 if (field.array)
+
8369 {
+
8370 std::string name = IsReferenceType(*field.type) ? "ReferenceType" : "ValueType";
+
8371
+
8372 if (field.optional)
+
8373 name = "Optional" + name;
+
8374
+
8375 StructField value;
+
8376 value.type = field.type;
+
8377
+
8378 return domain + "FBE." + modelType + "ModelArray" + name + "<" + ConvertTypeName(*field.type, false) + ", " + ConvertTypeFieldDeclaration(domain, package, value, final) + ">";
+
8379 }
+
8380 else if (field.vector || field.list || field.set)
+
8381 {
+
8382 std::string name = IsReferenceType(*field.type) ? "ReferenceType" : "ValueType";
+
8383
+
8384 if (field.optional)
+
8385 name = "Optional" + name;
+
8386
+
8387 StructField value;
+
8388 value.type = field.type;
+
8389
+
8390 return domain + "FBE." + modelType + "ModelVector" + name + "<" + ConvertTypeName(*field.type, false) + ", " + ConvertTypeFieldDeclaration(domain, package, value, final) + ">";
+
8391 }
+
8392 else if (field.map || field.hash)
+
8393 {
+
8394 std::string key_name = IsReferenceType(*field.key) ? "ReferenceTypeKey" : "ValueTypeKey";
+
8395 std::string value_name = IsReferenceType(*field.type) ? "ReferenceTypeValue" : "ValueTypeValue";
+
8396
+
8397 if (field.optional)
+
8398 value_name = "Optional" + value_name;
+
8399
+
8400 StructField key;
+
8401 key.type = field.key;
+
8402
+
8403 StructField value;
+
8404 value.type = field.type;
+
8405
+
8406 return domain + "FBE." + modelType + "ModelMap" + key_name + value_name + "<" + ConvertTypeName(*field.key, false) + ", " + ConvertTypeFieldDeclaration(domain, package, key, final) + ", " + ConvertTypeName(*field.type, false) + ", " + ConvertTypeFieldDeclaration(domain, package, value, final) + ">";
+
8407 }
+
8408 else if (field.optional)
+
8409 {
+
8410 StructField value;
+
8411 value.type = field.type;
+
8412
+
8413 std::string name = IsReferenceType(*field.type) ? "ReferenceType" : "ValueType";
+
8414 return domain + "FBE." + modelType + "ModelOptional" + name + "<" + ConvertTypeName(*field.type, false) + ", " + ConvertTypeFieldDeclaration(domain, package, value, final) + ">";
+
8415 }
+
8416 else if (IsKnownType(*field.type))
+
8417 {
+
8418 std::string name = IsReferenceType(*field.type) ? "ReferenceType" : "ValueType";
+
8419 return domain + "FBE." + modelType + "Model" + name + "<" + ConvertTypeName(*field.type, field.optional) + ">";
+
8420 }
+
8421
+
8422 return ConvertTypeFieldName(domain, package, *field.type, final);
+
8423}
+
8424
+
8425std::string GeneratorCSharp::ConvertTypeFieldInitialization(const std::string& domain, const std::string& package, const StructField& field, const std::string& offset, bool final)
+
8426{
+
8427 std::string modelType = final ? "Final" : "Field";
+
8428
+
8429 if (field.array)
+
8430 {
+
8431 std::string name = IsReferenceType(*field.type) ? "ReferenceType" : "ValueType";
+
8432
+
8433 if (field.optional)
+
8434 name = "Optional" + name;
+
8435
+
8436 StructField value;
+
8437 value.type = field.type;
+
8438
+
8439 return "new " + domain + "FBE." + modelType + "ModelArray" + name + "<" + ConvertTypeName(*field.type, false) + ", " + ConvertTypeFieldDeclaration(domain, package, value, final) + ">(" + ConvertTypeFieldInitialization(domain, package, value, offset, final) + ", buffer, " + offset + ", " + std::to_string(field.N) + ")";
+
8440 }
+
8441 else if (field.vector || field.list || field.set)
+
8442 {
+
8443 std::string name = IsReferenceType(*field.type) ? "ReferenceType" : "ValueType";
+
8444
+
8445 if (field.optional)
+
8446 name = "Optional" + name;
+
8447
+
8448 StructField value;
+
8449 value.type = field.type;
+
8450
+
8451 return "new " + domain + "FBE." + modelType + "ModelVector" + name + "<" + ConvertTypeName(*field.type, false) + ", " + ConvertTypeFieldDeclaration(domain, package, value, final) + ">(" + ConvertTypeFieldInitialization(domain, package, value, offset, final) + ", buffer, " + offset + ")";
+
8452 }
+
8453 else if (field.map || field.hash)
+
8454 {
+
8455 std::string key_name = IsReferenceType(*field.key) ? "ReferenceTypeKey" : "ValueTypeKey";
+
8456 std::string value_name = IsReferenceType(*field.type) ? "ReferenceTypeValue" : "ValueTypeValue";
+
8457
+
8458 if (field.optional)
+
8459 value_name = "Optional" + value_name;
+
8460
+
8461 StructField key;
+
8462 key.type = field.key;
+
8463
+
8464 StructField value;
+
8465 value.type = field.type;
+
8466
+
8467 return "new " + domain + "FBE." + modelType + "ModelMap" + key_name + value_name + "<" + ConvertTypeName(*field.key, false) + ", " + ConvertTypeFieldDeclaration(domain, package, key, final) + ", " + ConvertTypeName(*field.type, false) + ", " + ConvertTypeFieldDeclaration(domain, package, value, final) + ">(" + ConvertTypeFieldInitialization(domain, package, key, offset, final) + ", " + ConvertTypeFieldInitialization(domain, package, value, offset, final) + ", buffer, " + offset + ")";
+
8468 }
+
8469 else if (field.optional)
+
8470 {
+
8471 std::string name = IsReferenceType(*field.type) ? "ReferenceType" : "ValueType";
+
8472
+
8473 StructField model;
+
8474 model.type = field.type;
+
8475
+
8476 StructField value;
+
8477 value.type = field.type;
+
8478
+
8479 return "new " + domain + "FBE." + modelType + "ModelOptional" + name + "<" + ConvertTypeName(*field.type, false) + ", " + ConvertTypeFieldDeclaration(domain, package, model, final) + ">(" + ConvertTypeFieldInitialization(domain, package, value, offset, final) + ", buffer, " + offset + ")";
+
8480 }
+
8481 else if (IsKnownType(*field.type))
+
8482 {
+
8483 std::string name = IsReferenceType(*field.type) ? "ReferenceType" : "ValueType";
+
8484 return domain + "FBE." + modelType + "Model" + name + "<" + ConvertTypeName(*field.type, field.optional) + ">.Create" + modelType + "Model(" + domain + "FBE.BaseTypes." + ConvertBaseTypeName(*field.type) + ", buffer, " + offset + ")";
+
8485 }
+
8486
+
8487 return "new " + ConvertTypeFieldName(domain, package, *field.type, final) + "(buffer, " + offset + ")";
+
8488}
+
8489
+
8490std::string GeneratorCSharp::ConvertConstant(const std::string& domain, const std::string& package, const std::string& type, const std::string& value, bool optional)
+
8491{
+
8492 if (value == "true")
+
8493 return "true";
+
8494 else if (value == "false")
+
8495 return "false";
+
8496 else if (value == "null")
+
8497 return "null";
+
8498 else if (value == "min")
+
8499 {
+
8500 if (type == "byte")
+
8501 return "Byte.MinValue";
+
8502 else if (type == "int8")
+
8503 return "SByte.MinValue";
+
8504 else if (type == "uint8")
+
8505 return "Byte.MinValue";
+
8506 else if (type == "int16")
+
8507 return "Int16.MinValue";
+
8508 else if (type == "uint16")
+
8509 return "UInt16.MinValue";
+
8510 else if (type == "int32")
+
8511 return "Int32.MinValue";
+
8512 else if (type == "uint32")
+
8513 return "UInt32.MinValue";
+
8514 else if (type == "int64")
+
8515 return "Int64.MinValue";
+
8516 else if (type == "uint64")
+
8517 return "UInt64.MinValue";
+
8518
+
8519 yyerror("Unsupported type " + type + " for 'min' constant");
+
8520 return "";
+
8521 }
+
8522 else if (value == "max")
+
8523 {
+
8524 if (type == "byte")
+
8525 return "Byte.MaxValue";
+
8526 else if (type == "int8")
+
8527 return "SByte.MaxValue";
+
8528 else if (type == "uint8")
+
8529 return "Byte.MaxValue";
+
8530 else if (type == "int16")
+
8531 return "Int16.MaxValue";
+
8532 else if (type == "uint16")
+
8533 return "UInt16.MaxValue";
+
8534 else if (type == "int32")
+
8535 return "Int32.MaxValue";
+
8536 else if (type == "uint32")
+
8537 return "UInt32.MaxValue";
+
8538 else if (type == "int64")
+
8539 return "Int64.MaxValue";
+
8540 else if (type == "uint64")
+
8541 return "UInt64.MaxValue";
+
8542
+
8543 yyerror("Unsupported type " + type + " for 'max' constant");
+
8544 return "";
+
8545 }
+
8546 else if (value == "epoch")
+
8547 return "new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)";
+
8548 else if (value == "utc")
+
8549 return "DateTime.UtcNow";
+
8550 else if (value == "uuid0")
+
8551 return domain + "FBE.UuidGenerator.Nil()";
+
8552 else if (value == "uuid1")
+
8553 return domain + "FBE.UuidGenerator.Sequential()";
+
8554 else if (value == "uuid2")
+
8555 return domain + "FBE.UuidGenerator.Random()";
+
8556
+
8557 std::string result = value;
+
8558
+
8559 if (!IsKnownType(type))
+
8560 {
+
8561 // Fill flags values
+
8562 std::vector<std::string> flags = CppCommon::StringUtils::Split(value, '|', true);
+
8563
+
8564 // Generate flags combination
+
8565 if (flags.size() > 1)
+
8566 {
+
8567 result = "";
+
8568 bool first = true;
+
8569 for (const auto& it : flags)
+
8570 {
+
8571 std::string flag = CppCommon::StringUtils::ToTrim(it);
+
8572 std::string ns = (CppCommon::StringUtils::CountAll(flag, ".") > 1) ? ("global::" + domain) : ("global::" + domain + package + ".");
+
8573 result += (first ? "" : " | ") + ns + flag;
+
8574 first = false;
+
8575 }
+
8576 }
+
8577 else
+
8578 {
+
8579 std::string ns = (CppCommon::StringUtils::CountAll(result, ".") > 1) ? ("global::" + domain) : ("global::" + domain + package + ".");
+
8580 result = ns + result;
+
8581 }
+
8582 }
+
8583
+
8584 return ConvertConstantPrefix(type) + result + ConvertConstantSuffix(type);
+
8585}
+
8586
+
8587std::string GeneratorCSharp::ConvertConstantPrefix(const std::string& type)
+
8588{
+
8589 if (type == "bool")
+
8590 return "(bool)";
+
8591 else if (type == "byte")
+
8592 return "(byte)";
+
8593 else if (type == "char")
+
8594 return "(char)";
+
8595 else if (type == "wchar")
+
8596 return "(char)";
+
8597 else if (type == "int8")
+
8598 return "(sbyte)";
+
8599 else if (type == "uint8")
+
8600 return "(byte)";
+
8601 else if (type == "int16")
+
8602 return "(short)";
+
8603 else if (type == "uint16")
+
8604 return "(ushort)";
+
8605 else if (type == "int32")
+
8606 return "(int)";
+
8607 else if (type == "uint32")
+
8608 return "(uint)";
+
8609 else if (type == "int64")
+
8610 return "(long)";
+
8611 else if (type == "uint64")
+
8612 return "(ulong)";
+
8613 else if (type == "float")
+
8614 return "(float)";
+
8615 else if (type == "double")
+
8616 return "(double)";
+
8617 else if (type == "decimal")
+
8618 return "(decimal)";
+
8619 else if (type == "uuid")
+
8620 return "Guid.Parse(";
+
8621
+
8622 return "";
+
8623}
+
8624
+
8625std::string GeneratorCSharp::ConvertConstantSuffix(const std::string& type)
+
8626{
+
8627 if ((type == "byte") || (type == "uint8") || (type == "uint16") || (type == "uint32"))
+
8628 return "U";
+
8629 else if (type == "int64")
+
8630 return "L";
+
8631 else if (type == "uint64")
+
8632 return "UL";
+
8633 else if (type == "float")
+
8634 return "F";
+
8635 else if (type == "double")
+
8636 return "D";
+
8637 else if (type == "decimal")
+
8638 return "M";
+
8639 else if (type == "uuid")
+
8640 return ")";
+
8641
+
8642 return "";
+
8643}
+
8644
+
8645std::string GeneratorCSharp::ConvertDefault(const std::string& domain, const std::string& package, const std::string& type)
+
8646{
+
8647 if (type == "bool")
+
8648 return "false";
+
8649 else if (type == "bytes")
+
8650 return "new MemoryStream()";
+
8651 else if ((type == "char") || (type == "wchar"))
+
8652 return "'\\0'";
+
8653 else if ((type == "byte") || (type == "int8") || (type == "uint8") || (type == "int16") || (type == "uint16") || (type == "int32") || (type == "uint32") || (type == "int64") || (type == "uint64"))
+
8654 return ConvertConstantPrefix(type) + "0" + ConvertConstantSuffix(type);
+
8655 else if (type == "float")
+
8656 return "0.0F";
+
8657 else if (type == "double")
+
8658 return "0.0D";
+
8659 else if (type == "decimal")
+
8660 return "0.0M";
+
8661 else if (type == "string")
+
8662 return "\"\"";
+
8663 else if (type == "timestamp")
+
8664 return "new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)";
+
8665 else if (type == "uuid")
+
8666 return domain + "FBE.UuidGenerator.Nil()";
+
8667
+
8668 std::string ns = "";
+
8669 std::string t = type;
+
8670
+
8671 size_t pos = type.find_last_of('.');
+
8672 if (pos != std::string::npos)
+
8673 {
+
8674 ns.assign(type, 0, pos + 1);
+
8675 ns = domain + ns;
+
8676 t.assign(type, pos + 1, type.size() - pos);
+
8677 }
+
8678 else if (!package.empty())
+
8679 ns = domain + package + ".";
+
8680
+
8681 return "new " + ns + t + "()";
+
8682}
+
8683
+
8684std::string GeneratorCSharp::ConvertDefault(const std::string& domain, const std::string& package, const StructField& field)
+
8685{
+
8686 if (field.value)
+
8687 return ConvertConstant(domain, package, *field.type, *field.value, field.optional);
+
8688
+
8689 if (field.array)
+
8690 return "new " + ConvertTypeName(*field.type, field.optional) + "[" + std::to_string(field.N) + "]";
+
8691 else if (field.vector || field.list || field.set || field.map || field.hash)
+
8692 return "new " + ConvertTypeName(field) + "()";
+
8693 else if (field.optional)
+
8694 return "null";
+
8695 else if (!IsKnownType(*field.type))
+
8696 {
+
8697 std::string ns = "global::" + domain + (CppCommon::StringUtils::Contains(*field.type, '.') ? "" : (package + "."));
+
8698 return ns + ConvertTypeName(field) + ".Default";
+
8699 }
+
8700
+
8701 return ConvertDefault(domain, package, *field.type);
+
8702}
+
8703
+
8704std::string GeneratorCSharp::ConvertOutputStreamType(const std::string& type, const std::string& name, bool optional)
+
8705{
+
8706 if (type == "bool")
+
8707 return ".Append(" + name + (optional ? ".Value" : "") + " ? \"true\" : \"false\")";
+
8708 else if (type == "bytes")
+
8709 return ".Append(\"bytes[\").Append(" + name + ".Length).Append(\"]\")";
+
8710 else if ((type == "char") || (type == "wchar"))
+
8711 return ".Append(\"'\").Append(" + name + ").Append(\"'\")";
+
8712 else if ((type == "float") || (type == "double") || (type == "decimal"))
+
8713 return ".Append(" + name + (optional ? ".Value" : "") + ".ToString(CultureInfo.InvariantCulture))";
+
8714 else if ((type == "string") || (type == "uuid"))
+
8715 return ".Append(\"\\\"\").Append(" + name + ").Append(\"\\\"\")";
+
8716 else if (type == "timestamp")
+
8717 return ".Append((ulong)((" + name + (optional ? ".Value" : "") + ".Ticks - 621355968000000000) * 100))";
+
8718 else
+
8719 return ".Append(" + name + ")";
+
8720}
+
8721
+
8722std::string GeneratorCSharp::ConvertOutputStreamValue(const std::string& type, const std::string& name, bool optional, bool separate)
+
8723{
+
8724 std::string comma = separate ? ".Append(first ? \"\" : \",\")" : "";
+
8725
+
8726 if (optional || (type == "bytes") || (type == "string"))
+
8727 return "if (" + name + " != null) sb" + comma + ConvertOutputStreamType(type, name, true) + "; else sb" + comma + ".Append(\"null\");";
+
8728 else
+
8729 return "sb" + comma + ConvertOutputStreamType(type, name, false) + ";";
+
8730}
+
8731
+
8732} // namespace FBE
+
bool Final() const noexcept
+
bool JSON() const noexcept
+
bool Proto() const noexcept
+
void Generate(const std::shared_ptr< Package > &package) override
+
void WriteBegin()
Definition generator.inl:24
+
void Store(const CppCommon::Path &filename)
Definition generator.cpp:17
+
static std::string EndLine()
Definition generator.inl:68
+
std::string _input
Definition generator.h:25
+ +
std::string _output
Definition generator.h:26
+
void WriteLineIndent(const std::string &str)
Definition generator.inl:58
+
void Write(const std::string &str)
Definition generator.inl:29
+ +
void Indent(int count)
Definition generator.inl:19
+
void WriteIndent()
Definition generator.inl:34
+
int yyerror(const char *msg)
Definition fbe.l:163
+
Fast binary encoding C# generator definition.
+
Definition fbe.h:33
+
const char version[]
Definition version.h:15
+ +
+ + +
+ + diff --git a/documents/html/generator__csharp_8h.html b/documents/html/generator__csharp_8h.html new file mode 100644 index 000000000..a935dc9f0 --- /dev/null +++ b/documents/html/generator__csharp_8h.html @@ -0,0 +1,114 @@ + + + + + + + +FastBinaryEncoding: include/generator_csharp.h File Reference + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+ +
generator_csharp.h File Reference
+
+
+ +

Fast binary encoding C# generator definition. +More...

+
#include "generator.h"
+
+

Go to the source code of this file.

+ + + +

+Classes

class  FBE::GeneratorCSharp
+ + +

+Namespaces

namespace  FBE
+

Detailed Description

+

Fast binary encoding C# generator definition.

+
Author
Ivan Shynkarenka
+
Date
20.04.2018
+ + +

Definition in file generator_csharp.h.

+
+ + +
+ + diff --git a/documents/html/generator__csharp_8h_source.html b/documents/html/generator__csharp_8h_source.html new file mode 100644 index 000000000..22609c9c6 --- /dev/null +++ b/documents/html/generator__csharp_8h_source.html @@ -0,0 +1,215 @@ + + + + + + + +FastBinaryEncoding: include/generator_csharp.h Source File + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+
generator_csharp.h
+
+
+Go to the documentation of this file.
1
+
8
+
9#ifndef GENERATOR_CSHARP_H
+
10#define GENERATOR_CSHARP_H
+
11
+
12#include "generator.h"
+
13
+
14namespace FBE {
+
15
+
+ +
17{
+
18public:
+ +
20
+
21 // Final protocol code generation
+
22 bool Final() const noexcept { return _final; }
+
23 GeneratorCSharp& Final(bool final) noexcept { _final = final; return *this; }
+
24
+
25 // JSON protocol code generation
+
26 bool JSON() const noexcept { return _json; }
+
27 GeneratorCSharp& JSON(bool json) noexcept { _json = json; return *this; }
+
28
+
29 // Sender/Receiver protocol code generation
+
30 bool Proto() const noexcept { return _proto; }
+
31 GeneratorCSharp& Proto(bool proto) noexcept { _proto = proto; return *this; }
+
32
+
33 void Generate(const std::shared_ptr<Package>& package) override;
+
34
+
35private:
+
36 bool _final{false};
+
37 bool _json{false};
+
38 bool _proto{false};
+
39
+
40 void GenerateHeader(const std::string& source);
+
41 void GenerateFooter();
+
42 void GenerateImports();
+
43 void GenerateImports(const std::string& domain, const std::shared_ptr<Package>& p);
+
44 void GenerateFBEUuidGenerator();
+
45 void GenerateFBEBuffer();
+
46 void GenerateFBEBaseModel();
+
47 void GenerateFBEFieldModelBase();
+
48 void GenerateFBEFieldModel(const std::string& name, const std::string& type, const std::string& base, const std::string& size, const std::string& defaults);
+
49 void GenerateFBEFieldModelTimestamp();
+
50 void GenerateFBEFieldModelBytes();
+
51 void GenerateFBEFieldModelString();
+
52 void GenerateFBEFieldModelOptional(bool valueType);
+
53 void GenerateFBEFieldModelArray(bool valueType, bool optional);
+
54 void GenerateFBEFieldModelVector(bool valueType, bool optional);
+
55 void GenerateFBEFieldModelMap(bool valueTypeKey, bool valueTypeValue, bool optional);
+
56 void GenerateFBEFinalModelBase();
+
57 void GenerateFBEFinalModel(const std::string& name, const std::string& type, const std::string& base, const std::string& size, const std::string& defaults);
+
58 void GenerateFBEFinalModelTimestamp();
+
59 void GenerateFBEFinalModelBytes();
+
60 void GenerateFBEFinalModelString();
+
61 void GenerateFBEFinalModelOptional(bool valueType);
+
62 void GenerateFBEFinalModelArray(bool valueType, bool optional);
+
63 void GenerateFBEFinalModelVector(bool valueType, bool optional);
+
64 void GenerateFBEFinalModelMap(bool valueTypeKey, bool valueTypeValue, bool optional);
+
65 void GenerateFBESender();
+
66 void GenerateFBEReceiver();
+
67 void GenerateFBEClient();
+
68 void GenerateFBEJson();
+
69 void GenerateFBE(const std::string& domain, const CppCommon::Path& path);
+
70
+
71 void GeneratePackage(const std::string& domain, const std::shared_ptr<Package>& p);
+
72 void GenerateEnum(const std::string& domain, const std::shared_ptr<Package>& p, const std::shared_ptr<EnumType>& e);
+
73 void GenerateEnumFieldModel(const std::string& domain, const std::shared_ptr<Package>& p, const std::shared_ptr<EnumType>& e);
+
74 void GenerateEnumFinalModel(const std::string& domain, const std::shared_ptr<Package>& p, const std::shared_ptr<EnumType>& e);
+
75 void GenerateFlags(const std::string& domain, const std::shared_ptr<Package>& p, const std::shared_ptr<FlagsType>& f);
+
76 void GenerateFlagsFieldModel(const std::string& domain, const std::shared_ptr<Package>& p, const std::shared_ptr<FlagsType>& f);
+
77 void GenerateFlagsFinalModel(const std::string& domain, const std::shared_ptr<Package>& p, const std::shared_ptr<FlagsType>& f);
+
78 void GenerateStruct(const std::string& domain, const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s);
+
79 void GenerateStructFieldModel(const std::string& domain, const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s);
+
80 void GenerateStructModel(const std::string& domain, const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s);
+
81 void GenerateStructFinalModel(const std::string& domain, const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s);
+
82 void GenerateStructModelFinal(const std::string& domain, const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s);
+
83 void GenerateProtocolVersion(const std::string& domain, const std::shared_ptr<Package>& p);
+
84 void GenerateSender(const std::string& domain, const std::shared_ptr<Package>& p, bool final);
+
85 void GenerateReceiver(const std::string& domain, const std::shared_ptr<Package>& p, bool final);
+
86 void GenerateProxy(const std::string& domain, const std::shared_ptr<Package>& p, bool final);
+
87 void GenerateClient(const std::string& domain, const std::shared_ptr<Package>& p, bool final);
+
88
+
89 bool IsKnownType(const std::string& type);
+
90 bool IsReferenceType(const std::string& type);
+
91
+
92 std::string ConvertEnumRead(const std::string& type);
+
93 std::string ConvertEnumSize(const std::string& type);
+
94 std::string ConvertEnumType(const std::string& type);
+
95 std::string ConvertEnumTypeUtf8Json(const std::string& type);
+
96 std::string ConvertEnumConstant(const std::string& type, const std::string& value);
+
97 std::string ConvertEnumConstantPrefix(const std::string& type);
+
98 std::string ConvertEnumConstantSuffix(const std::string& type);
+
99 std::string ConvertBaseTypeName(const std::string& type);
+
100 std::string ConvertTypeName(const std::string& type, bool optional);
+
101 std::string ConvertTypeName(const std::string& domain, const std::string& package, const std::string& type, bool optional);
+
102 std::string ConvertTypeName(const StructField& field);
+
103 std::string ConvertTypeFieldName(const std::string& domain, const std::string& package, const std::string& type, bool final);
+
104 std::string ConvertTypeFieldDeclaration(const std::string& domain, const std::string& package, const StructField& field, bool final);
+
105 std::string ConvertTypeFieldInitialization(const std::string& domain, const std::string& package, const StructField& field, const std::string& offset, bool final);
+
106 std::string ConvertConstant(const std::string& domain, const std::string& package, const std::string& type, const std::string& value, bool optional);
+
107 std::string ConvertConstantPrefix(const std::string& type);
+
108 std::string ConvertConstantSuffix(const std::string& type);
+
109 std::string ConvertDefault(const std::string& domain, const std::string& package, const std::string& type);
+
110 std::string ConvertDefault(const std::string& domain, const std::string& package, const StructField& field);
+
111
+
112 std::string ConvertOutputStreamType(const std::string& type, const std::string& name, bool optional);
+
113 std::string ConvertOutputStreamValue(const std::string& type, const std::string& name, bool optional, bool separate);
+
114};
+
+
115
+
116} // namespace FBE
+
117
+
118#endif // GENERATOR_CSHARP_H
+ +
bool Final() const noexcept
+
bool JSON() const noexcept
+
GeneratorCSharp & Final(bool final) noexcept
+
GeneratorCSharp & Proto(bool proto) noexcept
+
GeneratorCSharp & JSON(bool json) noexcept
+
bool Proto() const noexcept
+
void Generate(const std::shared_ptr< Package > &package) override
+
Generator(const std::string &input, const std::string &output, int indent, char space)
Definition generator.inl:11
+
Generator(const std::string &input, const std::string &output, int indent, char space)
Definition generator.inl:11
+
Fast binary encoding generator definition.
+
Definition fbe.h:33
+
+ + +
+ + diff --git a/documents/html/generator__go_8cpp.html b/documents/html/generator__go_8cpp.html new file mode 100644 index 000000000..153ecc40a --- /dev/null +++ b/documents/html/generator__go_8cpp.html @@ -0,0 +1,109 @@ + + + + + + + +FastBinaryEncoding: source/generator_go.cpp File Reference + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+ +
generator_go.cpp File Reference
+
+
+ +

Fast binary encoding Go generator implementation. +More...

+
#include "generator_go.h"
+
+

Go to the source code of this file.

+ + + +

+Namespaces

namespace  FBE
+

Detailed Description

+

Fast binary encoding Go generator implementation.

+
Author
Ivan Shynkarenka
+
Date
20.11.2018
+ + +

Definition in file generator_go.cpp.

+
+ + +
+ + diff --git a/documents/html/generator__go_8cpp_source.html b/documents/html/generator__go_8cpp_source.html new file mode 100644 index 000000000..f7b38ab01 --- /dev/null +++ b/documents/html/generator__go_8cpp_source.html @@ -0,0 +1,8757 @@ + + + + + + + +FastBinaryEncoding: source/generator_go.cpp Source File + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+
generator_go.cpp
+
+
+Go to the documentation of this file.
1
+
8
+
9#include "generator_go.h"
+
10
+
11namespace FBE {
+
12
+
+
13void GeneratorGo::Generate(const std::shared_ptr<Package>& package)
+
14{
+
15 GenerateFBEPackage("fbe");
+
16 GenerateFBEConstants("fbe");
+
17 GenerateFBEJson("fbe");
+
18 GenerateFBEOptional("fbe");
+
19 GenerateFBETypes("fbe");
+
20 GenerateFBEVersion("fbe", "fbe");
+
21 GenerateFBEBuffer("fbe");
+
22 GenerateFBEFieldModel("fbe", "Bool", "bool", "1", "false");
+
23 GenerateFBEFieldModel("fbe", "Byte", "byte", "1", "0");
+
24 GenerateFBEFieldModel("fbe", "Char", "rune", "1", "'\\000'");
+
25 GenerateFBEFieldModel("fbe", "WChar", "rune", "4", "'\\000'");
+
26 GenerateFBEFieldModel("fbe", "Int8", "int8", "1", "0");
+
27 GenerateFBEFieldModel("fbe", "UInt8", "uint8", "1", "0");
+
28 GenerateFBEFieldModel("fbe", "Int16", "int16", "2", "0");
+
29 GenerateFBEFieldModel("fbe", "UInt16", "uint16", "2", "0");
+
30 GenerateFBEFieldModel("fbe", "Int32", "int32", "4", "0");
+
31 GenerateFBEFieldModel("fbe", "UInt32", "uint32", "4", "0");
+
32 GenerateFBEFieldModel("fbe", "Int64", "int64", "8", "0");
+
33 GenerateFBEFieldModel("fbe", "UInt64", "uint64", "8", "0");
+
34 GenerateFBEFieldModel("fbe", "Float", "float32", "4", "0.0");
+
35 GenerateFBEFieldModel("fbe", "Double", "float64", "8", "0.0");
+
36 GenerateFBEFieldModelDecimal("fbe");
+
37 GenerateFBEFieldModelTimestamp("fbe");
+
38 GenerateFBEFieldModelUUID("fbe");
+
39 GenerateFBEFieldModelBytes("fbe");
+
40 GenerateFBEFieldModelString("fbe");
+
41 if (Final())
+
42 {
+
43 GenerateFBEFinalModel("fbe", "Bool", "bool", "1", "false");
+
44 GenerateFBEFinalModel("fbe", "Byte", "byte", "1", "0");
+
45 GenerateFBEFinalModel("fbe", "Char", "rune", "1", "'\\000'");
+
46 GenerateFBEFinalModel("fbe", "WChar", "rune", "4", "'\\000'");
+
47 GenerateFBEFinalModel("fbe", "Int8", "int8", "1", "0");
+
48 GenerateFBEFinalModel("fbe", "UInt8", "uint8", "1", "0");
+
49 GenerateFBEFinalModel("fbe", "Int16", "int16", "2", "0");
+
50 GenerateFBEFinalModel("fbe", "UInt16", "uint16", "2", "0");
+
51 GenerateFBEFinalModel("fbe", "Int32", "int32", "4", "0");
+
52 GenerateFBEFinalModel("fbe", "UInt32", "uint32", "4", "0");
+
53 GenerateFBEFinalModel("fbe", "Int64", "int64", "8", "0");
+
54 GenerateFBEFinalModel("fbe", "UInt64", "uint64", "8", "0");
+
55 GenerateFBEFinalModel("fbe", "Float", "float32", "4", "0.0");
+
56 GenerateFBEFinalModel("fbe", "Double", "float64", "8", "0.0");
+
57 GenerateFBEFinalModelDecimal("fbe");
+
58 GenerateFBEFinalModelTimestamp("fbe");
+
59 GenerateFBEFinalModelUUID("fbe");
+
60 GenerateFBEFinalModelBytes("fbe");
+
61 GenerateFBEFinalModelString("fbe");
+
62 }
+
63 if (Proto())
+
64 {
+
65 GenerateFBESender("fbe");
+
66 GenerateFBEReceiver("fbe");
+
67 }
+
68
+
69 GeneratePackage(package);
+
70}
+
+
71
+
72void GeneratorGo::GenerateHeader(const std::string& source)
+
73{
+
74 std::string code = R"CODE(//------------------------------------------------------------------------------
+
75// Automatically generated by the Fast Binary Encoding compiler, do not modify!
+
76// https://github.com/chronoxor/FastBinaryEncoding
+
77// Source: _INPUT_
+
78// FBE version: _VERSION_
+
79//------------------------------------------------------------------------------
+
80)CODE";
+
81
+
82 // Prepare code template
+
83 code = std::regex_replace(code, std::regex("_INPUT_"), source);
+
84 code = std::regex_replace(code, std::regex("_VERSION_"), version);
+
85 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
86
+
87 Write(code);
+
88}
+
89
+
90void GeneratorGo::GenerateFooter()
+
91{
+
92
+
93}
+
94
+
95void GeneratorGo::GenerateFBEPackage(const std::string& package)
+
96{
+
97 CppCommon::Path path = CppCommon::Path(_output) / package;
+
98
+
99 // Create FBE package path
+
100 CppCommon::Directory::CreateTree(path);
+
101}
+
102
+
103void GeneratorGo::GenerateFBEConstants(const std::string& package)
+
104{
+
105 CppCommon::Path path = CppCommon::Path(_output) / package;
+
106
+
107 // Generate the file
+
108 CppCommon::Path file = path / "Constants.go";
+
109 WriteBegin();
+
110
+
111 // Generate headers
+
112 GenerateHeader("FBE");
+
113
+
114 std::string code = R"CODE(
+
115package fbe
+
116
+
117// Maximal signed integer value
+
118const MaxInt = int(^uint(0) >> 1)
+
119// Minimal signed integer value
+
120const MinInt = -MaxInt - 1
+
121
+
122// Maximal unsigned integer value
+
123const MaxUint = ^uint(0)
+
124// Minimal unsigned integer value
+
125const MinUint = 0
+
126)CODE";
+
127
+
128 // Prepare code template
+
129 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
130
+
131 Write(code);
+
132
+
133 // Generate footer
+
134 GenerateFooter();
+
135
+
136 // Store the file
+
137 WriteEnd();
+
138 Store(file);
+
139}
+
140
+
141void GeneratorGo::GenerateFBEJson(const std::string& package)
+
142{
+
143 CppCommon::Path path = CppCommon::Path(_output) / package;
+
144
+
145 // Generate the file
+
146 CppCommon::Path file = path / "Json.go";
+
147 WriteBegin();
+
148
+
149 // Generate headers
+
150 GenerateHeader("FBE");
+
151
+
152 std::string code = R"CODE(
+
153package fbe
+
154
+
155import "github.com/json-iterator/go"
+
156
+
157// Json engine
+
158var Json = jsoniter.ConfigCompatibleWithStandardLibrary
+
159)CODE";
+
160
+
161 // Prepare code template
+
162 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
163
+
164 Write(code);
+
165
+
166 // Generate footer
+
167 GenerateFooter();
+
168
+
169 // Store the file
+
170 WriteEnd();
+
171 Store(file);
+
172}
+
173
+
174void GeneratorGo::GenerateFBEOptional(const std::string& package)
+
175{
+
176 CppCommon::Path path = CppCommon::Path(_output) / package;
+
177
+
178 // Generate the file
+
179 CppCommon::Path file = path / "Optional.go";
+
180 WriteBegin();
+
181
+
182 // Generate headers
+
183 GenerateHeader("FBE");
+
184
+
185 std::string code = R"CODE(
+
186package fbe
+
187
+
188// Create an optional bool
+
189func OptionalBool(value bool) *bool {
+
190 return &value
+
191}
+
192
+
193// Create an optional byte
+
194func OptionalByte(value byte) *byte {
+
195 return &value
+
196}
+
197
+
198// Create an optional bytes
+
199func OptionalBytes(value []byte) *[]byte {
+
200 return &value
+
201}
+
202
+
203// Create an optional rune
+
204func OptionalRune(value rune) *rune {
+
205 return &value
+
206}
+
207
+
208// Create an optional int8
+
209func OptionalInt8(value int8) *int8 {
+
210 return &value
+
211}
+
212
+
213// Create an optional uint8
+
214func OptionalUInt8(value uint8) *uint8 {
+
215 return &value
+
216}
+
217
+
218// Create an optional int16
+
219func OptionalInt16(value int16) *int16 {
+
220 return &value
+
221}
+
222
+
223// Create an optional uint16
+
224func OptionalUInt16(value uint16) *uint16 {
+
225 return &value
+
226}
+
227
+
228// Create an optional int32
+
229func OptionalInt32(value int32) *int32 {
+
230 return &value
+
231}
+
232
+
233// Create an optional uint32
+
234func OptionalUInt32(value uint32) *uint32 {
+
235 return &value
+
236}
+
237
+
238// Create an optional int64
+
239func OptionalInt64(value int64) *int64 {
+
240 return &value
+
241}
+
242
+
243// Create an optional uint64
+
244func OptionalUInt64(value uint64) *uint64 {
+
245 return &value
+
246}
+
247
+
248// Create an optional float32
+
249func OptionalFloat32(value float32) *float32 {
+
250 return &value
+
251}
+
252
+
253// Create an optional float64
+
254func OptionalFloat64(value float64) *float64 {
+
255 return &value
+
256}
+
257
+
258// Create an optional decimal
+
259func OptionalDecimal(value Decimal) *Decimal {
+
260 return &value
+
261}
+
262
+
263// Create an optional timestamp
+
264func OptionalTimestamp(value Timestamp) *Timestamp {
+
265 return &value
+
266}
+
267
+
268// Create an optional string
+
269func OptionalString(value string) *string {
+
270 return &value
+
271}
+
272
+
273// Create an optional UUID
+
274func OptionalUUID(value UUID) *UUID {
+
275 return &value
+
276}
+
277)CODE";
+
278
+
279 // Prepare code template
+
280 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
281
+
282 Write(code);
+
283
+
284 // Generate footer
+
285 GenerateFooter();
+
286
+
287 // Store the file
+
288 WriteEnd();
+
289 Store(file);
+
290}
+
291
+
292void GeneratorGo::GenerateFBETypes(const std::string& package)
+
293{
+
294 CppCommon::Path path = CppCommon::Path(_output) / package;
+
295
+
296 // Generate the file
+
297 CppCommon::Path file = path / "Types.go";
+
298 WriteBegin();
+
299
+
300 // Generate headers
+
301 GenerateHeader("FBE");
+
302
+
303 std::string code = R"CODE(
+
304package fbe
+
305
+
306import "time"
+
307import "github.com/google/uuid"
+
308import "github.com/shopspring/decimal"
+
309
+
310// Decimal struct
+
311type Decimal struct {
+
312 decimal.Decimal
+
313}
+
314
+
315// Create a new decimal from the given float value
+
316func DecimalFromFloat(value float64) Decimal {
+
317 result := decimal.NewFromFloat(value)
+
318 return Decimal{result}
+
319}
+
320
+
321// Create a new decimal from the given string
+
322func DecimalFromString(value string) Decimal {
+
323 result, _ := decimal.NewFromString(value)
+
324 return Decimal{result}
+
325}
+
326
+
327// Create zero decimal
+
328func DecimalZero() Decimal {
+
329 return Decimal{decimal.New(0, 0)}
+
330}
+
331
+
332// Timestamp struct
+
333type Timestamp struct {
+
334 time.Time
+
335}
+
336
+
337// Create a new timestamp from the given date
+
338func TimestampFromDate(year, month, day int) Timestamp {
+
339 return Timestamp{time.Date(year, time.Month(month + 1), day, 0, 0, 0, 0, time.UTC)}
+
340}
+
341
+
342// Create a new timestamp from the given date
+
343func TimestampFromDateTime(year, month, day, hour, minute, second, nanoseconds int) Timestamp {
+
344 return Timestamp{time.Date(year, time.Month(month + 1), day, hour, minute, second, nanoseconds, time.UTC)}
+
345}
+
346
+
347// Create a new timestamp from the given nanoseconds
+
348func TimestampFromNanoseconds(nanoseconds uint64) Timestamp {
+
349 return Timestamp{time.Unix(int64(nanoseconds / 1000000000), int64(nanoseconds % 1000000000)).UTC()}
+
350}
+
351
+
352// Create Unix Epoch timestamp
+
353func TimestampEpoch() Timestamp {
+
354 return Timestamp{time.Unix(0, 0).UTC()}
+
355}
+
356
+
357// Create the current UTC timestamp
+
358func TimestampUTC() Timestamp {
+
359 return Timestamp{time.Now().UTC()}
+
360}
+
361
+
362// Convert timestamp to JSON
+
363func (t *Timestamp) MarshalJSON() ([]byte, error) {
+
364 timestamp := t.UnixNano()
+
365 return Json.Marshal(&timestamp)
+
366}
+
367
+
368// Convert JSON to timestamp
+
369func (t *Timestamp) UnmarshalJSON(buffer []byte) error {
+
370 var nanoseconds int64
+
371 err := Json.Unmarshal(buffer, &nanoseconds)
+
372 if err != nil {
+
373 return err
+
374 }
+
375 *t = TimestampFromNanoseconds(uint64(nanoseconds))
+
376 return nil
+
377}
+
378
+
379// UUID struct
+
380type UUID struct {
+
381 uuid.UUID
+
382}
+
383
+
384// Create a new UUID from the given bytes buffer
+
385func UUIDFromBytes(buffer []byte) UUID {
+
386 result, _ := uuid.FromBytes(buffer)
+
387 return UUID{result}
+
388}
+
389
+
390// Create a new UUID from the given string
+
391func UUIDFromString(value string) UUID {
+
392 result, _ := uuid.Parse(value)
+
393 return UUID{result}
+
394}
+
395
+
396// Create nil UUID0 (all bits set to zero)
+
397func UUIDNil() UUID {
+
398 return UUID{uuid.Nil}
+
399}
+
400
+
401// Create sequential UUID1 (time based version)
+
402func UUIDSequential() UUID {
+
403 result, _ := uuid.NewUUID()
+
404 return UUID{result}
+
405}
+
406
+
407// Create random UUID4 (randomly or pseudo-randomly generated version)
+
408func UUIDRandom() UUID {
+
409 result, _ := uuid.NewRandom()
+
410 return UUID{result}
+
411}
+
412)CODE";
+
413
+
414 // Prepare code template
+
415 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
416
+
417 Write(code);
+
418
+
419 // Generate footer
+
420 GenerateFooter();
+
421
+
422 // Store the file
+
423 WriteEnd();
+
424 Store(file);
+
425}
+
426
+
427void GeneratorGo::GenerateFBEVersion(const std::string& package, const std::string& source)
+
428{
+
429 CppCommon::Path path = CppCommon::Path(_output) / package;
+
430
+
431 // Generate the file
+
432 CppCommon::Path file = path / "Version.go";
+
433 WriteBegin();
+
434
+
435 // Generate headers
+
436 GenerateHeader(source);
+
437
+
438 std::string code = R"CODE(
+
439package _PACKAGE_
+
440
+
441// Package version
+
442const Version = "_VERSION_"
+
443)CODE";
+
444
+
445 // Prepare code template
+
446 code = std::regex_replace(code, std::regex("_PACKAGE_"), package);
+
447 code = std::regex_replace(code, std::regex("_VERSION_"), version);
+
448 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
449
+
450 Write(code);
+
451
+
452 // Generate footer
+
453 GenerateFooter();
+
454
+
455 // Store the file
+
456 WriteEnd();
+
457 Store(file);
+
458}
+
459
+
460void GeneratorGo::GenerateFBEBuffer(const std::string& package)
+
461{
+
462 CppCommon::Path path = CppCommon::Path(_output) / package;
+
463
+
464 // Generate the file
+
465 CppCommon::Path file = path / "Buffer.go";
+
466 WriteBegin();
+
467
+
468 // Generate headers
+
469 GenerateHeader("FBE");
+
470
+
471 std::string code = R"CODE(
+
472package fbe
+
473
+
474import "math"
+
475
+
476// Fast Binary Encoding buffer based on dynamic byte array
+
477type Buffer struct {
+
478 // Bytes memory buffer
+
479 data []byte
+
480 // Bytes memory buffer size
+
481 size int
+
482 // Bytes memory buffer offset
+
483 offset int
+
484}
+
485
+
486// Create an empty buffer
+
487func NewEmptyBuffer() *Buffer {
+
488 return &Buffer{data: make([]byte, 0)}
+
489}
+
490
+
491// Create an empty buffer with the given capacity
+
492func NewCapacityBuffer(capacity int) *Buffer {
+
493 return &Buffer{data: make([]byte, capacity)}
+
494}
+
495
+
496// Create a buffer with attached bytes memory buffer
+
497func NewAttached(buffer []byte) *Buffer {
+
498 result := NewEmptyBuffer()
+
499 result.Attach(buffer)
+
500 return result
+
501}
+
502
+
503// Create a buffer with attached bytes memory buffer with offset and size
+
504func NewAttachedBytes(buffer []byte, offset int, size int) *Buffer {
+
505 result := NewEmptyBuffer()
+
506 result.AttachBytes(buffer, offset, size)
+
507 return result
+
508}
+
509
+
510// Create a buffer with another attached buffer
+
511func NewAttachedBuffer(buffer *Buffer) *Buffer {
+
512 result := NewEmptyBuffer()
+
513 result.AttachBuffer(buffer)
+
514 return result
+
515}
+
516
+
517// Is the buffer empty?
+
518func (b *Buffer) Empty() bool { return (len(b.data) == 0) || (b.size <= 0) }
+
519// Get bytes memory buffer
+
520func (b *Buffer) Data() []byte { return b.data }
+
521// Get bytes memory buffer capacity
+
522func (b *Buffer) Capacity() int { return len(b.data) }
+
523// Get bytes memory buffer size
+
524func (b *Buffer) Size() int { return b.size }
+
525// Get bytes memory buffer offset
+
526func (b *Buffer) Offset() int { return b.offset }
+
527
+
528// Attach an empty memory buffer
+
529func (b *Buffer) AttachNew() {
+
530 b.data = make([]byte, 0)
+
531 b.size = 0
+
532 b.offset = 0
+
533}
+
534
+
535// Attach an empty memory buffer with the given capacity
+
536func (b *Buffer) AttachCapacity(capacity int) {
+
537 b.data = make([]byte, capacity)
+
538 b.size = 0
+
539 b.offset = 0
+
540}
+
541
+
542// Attach the given bytes memory buffer
+
543func (b *Buffer) Attach(buffer []byte) {
+
544 b.AttachBytes(buffer, 0, len(buffer))
+
545}
+
546
+
547// Attach the given bytes memory buffer with offset and size
+
548func (b *Buffer) AttachBytes(buffer []byte, offset int, size int) {
+
549 if len(buffer) < size {
+
550 panic("invalid buffer")
+
551 }
+
552 if size <= 0 {
+
553 panic("invalid size")
+
554 }
+
555 if offset > size {
+
556 panic("invalid offset")
+
557 }
+
558
+
559 b.data = buffer
+
560 b.size = size
+
561 b.offset = offset
+
562}
+
563
+
564// Attach another buffer
+
565func (b *Buffer) AttachBuffer(buffer *Buffer) {
+
566 b.AttachBytes(buffer.data, 0, buffer.size)
+
567}
+
568
+
569// Allocate memory in the current write buffer and return offset to the allocated memory block
+
570func (b *Buffer) Allocate(size int) int {
+
571 if size < 0 {
+
572 panic("invalid allocation size")
+
573 }
+
574
+
575 offset := b.size
+
576
+
577 // Calculate a new buffer size
+
578 total := b.size + size
+
579
+
580 if total <= len(b.data) {
+
581 b.size = total
+
582 return offset
+
583 }
+
584
+
585 length := 2 * len(b.data)
+
586 if length < total {
+
587 length = total
+
588 }
+
589
+
590 data := make([]byte, length)
+
591 copy(data, b.data[:b.size])
+
592 b.data = data
+
593 b.size = total
+
594 return offset
+
595}
+
596
+
597// Remove some memory of the given size from the current write buffer
+
598func (b *Buffer) Remove(offset int, size int) {
+
599 if (offset + size) > len(b.data) {
+
600 panic("invalid offset & size")
+
601 }
+
602
+
603 copy(b.data[offset:], b.data[offset+size:])
+
604 b.size -= size
+
605 if b.offset >= (offset + size) {
+
606 b.offset -= size
+
607 } else if b.offset >= offset {
+
608 b.offset -= b.offset - offset
+
609 if b.offset > b.size {
+
610 b.offset = b.size
+
611 }
+
612 }
+
613}
+
614
+
615// Reserve memory of the given capacity in the current write bufferb
+
616func (b *Buffer) Reserve(capacity int) {
+
617 if capacity < 0 {
+
618 panic("invalid reserve capacity")
+
619 }
+
620
+
621 if capacity > len(b.data) {
+
622 length := 2 * len(b.data)
+
623 if length < capacity {
+
624 length = capacity
+
625 }
+
626
+
627 data := make([]byte, length)
+
628 copy(data, b.data[:b.size])
+
629 b.data = data
+
630 }
+
631}
+
632
+
633// Resize the current write buffer
+
634func (b *Buffer) Resize(size int) {
+
635 b.Reserve(size)
+
636 b.size = size
+
637 if b.offset > b.size {
+
638 b.offset = b.size
+
639 }
+
640}
+
641
+
642// Reset the current write buffer and its offset
+
643func (b *Buffer) Reset() {
+
644 b.size = 0
+
645 b.offset = 0
+
646}
+
647
+
648// Shift the current write buffer offset
+
649func (b *Buffer) Shift(offset int) {
+
650 b.offset += offset
+
651}
+
652
+
653// Unshift the current write buffer offset
+
654func (b *Buffer) Unshift(offset int) {
+
655 b.offset -= offset
+
656}
+
657
+
658// Buffer I/O methods
+
659
+
660// Read bool from the buffer
+
661func ReadBool(buffer []byte, offset int) bool {
+
662 return buffer[offset] != 0
+
663}
+
664
+
665// Read byte from the buffer
+
666func ReadByte(buffer []byte, offset int) byte {
+
667 return buffer[offset]
+
668}
+
669
+
670// Read single byte character from the buffer
+
671func ReadChar(buffer []byte, offset int) rune {
+
672 return rune(ReadUInt8(buffer, offset))
+
673}
+
674
+
675// Read four bytes character from the buffer
+
676func ReadWChar(buffer []byte, offset int) rune {
+
677 return rune(ReadUInt32(buffer, offset))
+
678}
+
679
+
680// Read signed 8-bits integer from the buffer
+
681func ReadInt8(buffer []byte, offset int) int8 {
+
682 return int8(buffer[offset])
+
683}
+
684
+
685// Read unsigned 8-bits integer from the buffer
+
686func ReadUInt8(buffer []byte, offset int) uint8 {
+
687 return uint8(buffer[offset])
+
688}
+
689
+
690// Read signed 16-bits integer from the buffer
+
691func ReadInt16(buffer []byte, offset int) int16 {
+
692 return (int16(buffer[offset + 0]) << 0) | (int16(buffer[offset + 1]) << 8)
+
693}
+
694
+
695// Read unsigned 16-bits integer from the buffer
+
696func ReadUInt16(buffer []byte, offset int) uint16 {
+
697 return (uint16(buffer[offset + 0]) << 0) | (uint16(buffer[offset + 1]) << 8)
+
698}
+
699
+
700// Read signed 32-bits integer from the buffer
+
701func ReadInt32(buffer []byte, offset int) int32 {
+
702 return (int32(buffer[offset + 0]) << 0) |
+
703 (int32(buffer[offset + 1]) << 8) |
+
704 (int32(buffer[offset + 2]) << 16) |
+
705 (int32(buffer[offset + 3]) << 24)
+
706}
+
707
+
708// Read unsigned 32-bits integer from the buffer
+
709func ReadUInt32(buffer []byte, offset int) uint32 {
+
710 return (uint32(buffer[offset + 0]) << 0) |
+
711 (uint32(buffer[offset + 1]) << 8) |
+
712 (uint32(buffer[offset + 2]) << 16) |
+
713 (uint32(buffer[offset + 3]) << 24)
+
714}
+
715
+
716// Read signed 64-bits integer from the buffer
+
717func ReadInt64(buffer []byte, offset int) int64 {
+
718 return (int64(buffer[offset + 0]) << 0) |
+
719 (int64(buffer[offset + 1]) << 8) |
+
720 (int64(buffer[offset + 2]) << 16) |
+
721 (int64(buffer[offset + 3]) << 24) |
+
722 (int64(buffer[offset + 4]) << 32) |
+
723 (int64(buffer[offset + 5]) << 40) |
+
724 (int64(buffer[offset + 6]) << 48) |
+
725 (int64(buffer[offset + 7]) << 56)
+
726}
+
727
+
728// Read unsigned 64-bits integer from the buffer
+
729func ReadUInt64(buffer []byte, offset int) uint64 {
+
730 return (uint64(buffer[offset + 0]) << 0) |
+
731 (uint64(buffer[offset + 1]) << 8) |
+
732 (uint64(buffer[offset + 2]) << 16) |
+
733 (uint64(buffer[offset + 3]) << 24) |
+
734 (uint64(buffer[offset + 4]) << 32) |
+
735 (uint64(buffer[offset + 5]) << 40) |
+
736 (uint64(buffer[offset + 6]) << 48) |
+
737 (uint64(buffer[offset + 7]) << 56)
+
738}
+
739
+
740// Read float from the buffer
+
741func ReadFloat(buffer []byte, offset int) float32 {
+
742 bits := ReadUInt32(buffer, offset)
+
743 return math.Float32frombits(bits)
+
744}
+
745
+
746// Read double from the buffer
+
747func ReadDouble(buffer []byte, offset int) float64 {
+
748 bits := ReadUInt64(buffer, offset)
+
749 return math.Float64frombits(bits)
+
750}
+
751
+
752// Read bytes from the buffer
+
753func ReadBytes(buffer []byte, offset int, size int) []byte {
+
754 return buffer[offset:offset + size]
+
755}
+
756
+
757// Read string from the buffer
+
758func ReadString(buffer []byte, offset int, size int) string {
+
759 return string(buffer[offset:offset + size])
+
760}
+
761
+
762// Read timestamp from the buffer
+
763func ReadTimestamp(buffer []byte, offset int) Timestamp {
+
764 nanoseconds := ReadUInt64(buffer, offset)
+
765 return TimestampFromNanoseconds(nanoseconds)
+
766}
+
767
+
768// Read UUID from the buffer
+
769func ReadUUID(buffer []byte, offset int) UUID {
+
770 bytes := ReadBytes(buffer, offset, 16)
+
771 return UUIDFromBytes(bytes)
+
772}
+
773
+
774// Write bool into the buffer
+
775func WriteBool(buffer []byte, offset int, value bool) {
+
776 if value {
+
777 buffer[offset] = 1
+
778 } else {
+
779 buffer[offset] = 0
+
780 }
+
781}
+
782
+
783// Write byte into the buffer
+
784func WriteByte(buffer []byte, offset int, value byte) {
+
785 buffer[offset] = value
+
786}
+
787
+
788// Write single byte character into the buffer
+
789func WriteChar(buffer []byte, offset int, value rune) {
+
790 WriteUInt8(buffer, offset, uint8(value))
+
791}
+
792
+
793// Write four bytes character into the buffer
+
794func WriteWChar(buffer []byte, offset int, value rune) {
+
795 WriteUInt32(buffer, offset, uint32(value))
+
796}
+
797
+
798// Write signed 8-bits integer into the buffer
+
799func WriteInt8(buffer []byte, offset int, value int8) {
+
800 buffer[offset] = byte(value)
+
801}
+
802
+
803// Write unsigned 8-bits integer into the buffer
+
804func WriteUInt8(buffer []byte, offset int, value uint8) {
+
805 buffer[offset] = byte(value)
+
806}
+
807
+
808// Write signed 16-bits integer into the buffer
+
809func WriteInt16(buffer []byte, offset int, value int16) {
+
810 buffer[offset + 0] = byte(value >> 0)
+
811 buffer[offset + 1] = byte(value >> 8)
+
812}
+
813
+
814// Write unsigned 16-bits integer into the buffer
+
815func WriteUInt16(buffer []byte, offset int, value uint16) {
+
816 buffer[offset + 0] = byte(value >> 0)
+
817 buffer[offset + 1] = byte(value >> 8)
+
818}
+
819
+
820// Write signed 32-bits integer into the buffer
+
821func WriteInt32(buffer []byte, offset int, value int32) {
+
822 buffer[offset + 0] = byte(value >> 0)
+
823 buffer[offset + 1] = byte(value >> 8)
+
824 buffer[offset + 2] = byte(value >> 16)
+
825 buffer[offset + 3] = byte(value >> 24)
+
826}
+
827
+
828// Write unsigned 32-bits integer into the buffer
+
829func WriteUInt32(buffer []byte, offset int, value uint32) {
+
830 buffer[offset + 0] = byte(value >> 0)
+
831 buffer[offset + 1] = byte(value >> 8)
+
832 buffer[offset + 2] = byte(value >> 16)
+
833 buffer[offset + 3] = byte(value >> 24)
+
834}
+
835
+
836// Write signed 64-bits integer into the buffer
+
837func WriteInt64(buffer []byte, offset int, value int64) {
+
838 buffer[offset + 0] = byte(value >> 0)
+
839 buffer[offset + 1] = byte(value >> 8)
+
840 buffer[offset + 2] = byte(value >> 16)
+
841 buffer[offset + 3] = byte(value >> 24)
+
842 buffer[offset + 4] = byte(value >> 32)
+
843 buffer[offset + 5] = byte(value >> 40)
+
844 buffer[offset + 6] = byte(value >> 48)
+
845 buffer[offset + 7] = byte(value >> 56)
+
846}
+
847
+
848// Write unsigned 64-bits integer into the buffer
+
849func WriteUInt64(buffer []byte, offset int, value uint64) {
+
850 buffer[offset + 0] = byte(value >> 0)
+
851 buffer[offset + 1] = byte(value >> 8)
+
852 buffer[offset + 2] = byte(value >> 16)
+
853 buffer[offset + 3] = byte(value >> 24)
+
854 buffer[offset + 4] = byte(value >> 32)
+
855 buffer[offset + 5] = byte(value >> 40)
+
856 buffer[offset + 6] = byte(value >> 48)
+
857 buffer[offset + 7] = byte(value >> 56)
+
858}
+
859
+
860// Write float into the buffer
+
861func WriteFloat(buffer []byte, offset int, value float32) {
+
862 WriteUInt32(buffer, offset, math.Float32bits(value))
+
863}
+
864
+
865// Write double into the buffer
+
866func WriteDouble(buffer []byte, offset int, value float64) {
+
867 WriteUInt64(buffer, offset, math.Float64bits(value))
+
868}
+
869
+
870// Write bytes into the buffer
+
871func WriteBytes(buffer []byte, offset int, value []byte) {
+
872 copy(buffer[offset:offset + len(value)], value)
+
873}
+
874
+
875// Write slice into the buffer
+
876func WriteSlice(buffer []byte, offset int, value []byte, valueOffset int, valueSize int) {
+
877 copy(buffer[offset:offset + len(value)], value[valueOffset:valueOffset + valueSize])
+
878}
+
879
+
880// Write count of single byte into the buffer
+
881func WriteCount(buffer []byte, offset int, value byte, valueCount int) {
+
882 for i := 0; i < valueCount; i++ {
+
883 buffer[offset + i] = value
+
884 }
+
885}
+
886
+
887// Write string into the buffer
+
888func WriteString(buffer []byte, offset int, value string) {
+
889 WriteBytes(buffer, offset, []byte(value))
+
890}
+
891
+
892// Write timestamp into the buffer
+
893func WriteTimestamp(buffer []byte, offset int, value Timestamp) {
+
894 nanoseconds := uint64(value.UnixNano())
+
895 WriteUInt64(buffer, offset, nanoseconds)
+
896}
+
897
+
898// Write UUID into the buffer
+
899func WriteUUID(buffer []byte, offset int, value UUID) {
+
900 bytes, _ := value.MarshalBinary()
+
901 WriteBytes(buffer, offset, bytes)
+
902}
+
903)CODE";
+
904
+
905 // Prepare code template
+
906 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
907
+
908 Write(code);
+
909
+
910 // Generate footer
+
911 GenerateFooter();
+
912
+
913 // Store the file
+
914 WriteEnd();
+
915 Store(file);
+
916}
+
917
+
918void GeneratorGo::GenerateFBEFieldModel(const std::string& package, const std::string& name, const std::string& type, const std::string& size, const std::string& defaults)
+
919{
+
920 CppCommon::Path path = CppCommon::Path(_output) / package;
+
921
+
922 // Generate the file
+
923 CppCommon::Path file = path / ("FieldModel" + name + ".go");
+
924 WriteBegin();
+
925
+
926 // Generate headers
+
927 GenerateHeader("FBE");
+
928
+
929 std::string code = R"CODE(
+
930package fbe
+
931
+
932import "errors"
+
933
+
934// Fast Binary Encoding _NAME_ field model
+
935type FieldModel_NAME_ struct {
+
936 // Field model buffer
+
937 buffer *Buffer
+
938 // Field model buffer offset
+
939 offset int
+
940}
+
941
+
942// Create a new _NAME_ field model
+
943func NewFieldModel_NAME_(buffer *Buffer, offset int) *FieldModel_NAME_ {
+
944 return &FieldModel_NAME_{buffer: buffer, offset: offset}
+
945}
+
946
+
947// Get the field size
+
948func (fm *FieldModel_NAME_) FBESize() int { return _SIZE_ }
+
949// Get the field extra size
+
950func (fm *FieldModel_NAME_) FBEExtra() int { return 0 }
+
951
+
952// Get the field offset
+
953func (fm *FieldModel_NAME_) FBEOffset() int { return fm.offset }
+
954// Set the field offset
+
955func (fm *FieldModel_NAME_) SetFBEOffset(value int) { fm.offset = value }
+
956
+
957// Shift the current field offset
+
958func (fm *FieldModel_NAME_) FBEShift(size int) { fm.offset += size }
+
959// Unshift the current field offset
+
960func (fm *FieldModel_NAME_) FBEUnshift(size int) { fm.offset -= size }
+
961
+
962// Check if the value is valid
+
963func (fm *FieldModel_NAME_) Verify() bool { return true }
+
964
+
965// Get the value
+
966func (fm *FieldModel_NAME_) Get() (_TYPE_, error) {
+
967 return fm.GetDefault(_DEFAULTS_)
+
968}
+
969
+
970// Get the value with provided default value
+
971func (fm *FieldModel_NAME_) GetDefault(defaults _TYPE_) (_TYPE_, error) {
+
972 if (fm.buffer.Offset() + fm.FBEOffset() + fm.FBESize()) > fm.buffer.Size() {
+
973 return defaults, nil
+
974 }
+
975
+
976 return Read_NAME_(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset()), nil
+
977}
+
978
+
979// Set the value
+
980func (fm *FieldModel_NAME_) Set(value _TYPE_) error {
+
981 if (fm.buffer.Offset() + fm.FBEOffset() + fm.FBESize()) > fm.buffer.Size() {
+
982 return errors.New("model is broken")
+
983 }
+
984
+
985 Write_NAME_(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset(), value)
+
986 return nil
+
987}
+
988)CODE";
+
989
+
990 // Prepare code template
+
991 code = std::regex_replace(code, std::regex("_NAME_"), name);
+
992 code = std::regex_replace(code, std::regex("_TYPE_"), type);
+
993 code = std::regex_replace(code, std::regex("_SIZE_"), size);
+
994 code = std::regex_replace(code, std::regex("_DEFAULTS_"), defaults);
+
995 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
996
+
997 Write(code);
+
998
+
999 // Generate footer
+
1000 GenerateFooter();
+
1001
+
1002 // Store the file
+
1003 WriteEnd();
+
1004 Store(file);
+
1005}
+
1006
+
1007void GeneratorGo::GenerateFBEFieldModelDecimal(const std::string& package)
+
1008{
+
1009 CppCommon::Path path = CppCommon::Path(_output) / package;
+
1010
+
1011 // Generate the file
+
1012 CppCommon::Path file = path / ("FieldModelDecimal.go");
+
1013 WriteBegin();
+
1014
+
1015 // Generate headers
+
1016 GenerateHeader("FBE");
+
1017
+
1018 std::string code = R"CODE(
+
1019package fbe
+
1020
+
1021import "errors"
+
1022import "math/big"
+
1023import "github.com/shopspring/decimal"
+
1024
+
1025// Fast Binary Encoding decimal field model
+
1026type FieldModelDecimal struct {
+
1027 // Field model buffer
+
1028 buffer *Buffer
+
1029 // Field model buffer offset
+
1030 offset int
+
1031}
+
1032
+
1033// Create a new decimal field model
+
1034func NewFieldModelDecimal(buffer *Buffer, offset int) *FieldModelDecimal {
+
1035 return &FieldModelDecimal{buffer: buffer, offset: offset}
+
1036}
+
1037
+
1038// Get the field size
+
1039func (fm *FieldModelDecimal) FBESize() int { return 16 }
+
1040// Get the field extra size
+
1041func (fm *FieldModelDecimal) FBEExtra() int { return 0 }
+
1042
+
1043// Get the field offset
+
1044func (fm *FieldModelDecimal) FBEOffset() int { return fm.offset }
+
1045// Set the field offset
+
1046func (fm *FieldModelDecimal) SetFBEOffset(value int) { fm.offset = value }
+
1047
+
1048// Shift the current field offset
+
1049func (fm *FieldModelDecimal) FBEShift(size int) { fm.offset += size }
+
1050// Unshift the current field offset
+
1051func (fm *FieldModelDecimal) FBEUnshift(size int) { fm.offset -= size }
+
1052
+
1053// Check if the decimal value is valid
+
1054func (fm *FieldModelDecimal) Verify() bool { return true }
+
1055
+
1056// Get the decimal value
+
1057func (fm *FieldModelDecimal) Get() (Decimal, error) {
+
1058 return fm.GetDefault(DecimalZero())
+
1059}
+
1060
+
1061// Get the decimal value with provided default value
+
1062func (fm *FieldModelDecimal) GetDefault(defaults Decimal) (Decimal, error) {
+
1063 if (fm.buffer.Offset() + fm.FBEOffset() + fm.FBESize()) > fm.buffer.Size() {
+
1064 return defaults, nil
+
1065 }
+
1066
+
1067 // Read decimal parts
+
1068 low := ReadUInt32(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset())
+
1069 mid := ReadUInt32(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset() + 4)
+
1070 high := ReadUInt32(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset() + 8)
+
1071 flags := ReadUInt32(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset() + 12)
+
1072
+
1073 // Calculate decimal value
+
1074 negative := (flags & 0x80000000) != 0
+
1075 scale := (flags & 0x7FFFFFFF) >> 16
+
1076 result := decimal.New(int64(high), 0).Mul(lowScaleField)
+
1077 result = result.Add(decimal.New(int64(mid), 0).Mul(midScaleField))
+
1078 result = result.Add(decimal.New(int64(low), 0))
+
1079 result = result.Shift(-int32(scale))
+
1080 if negative {
+
1081 result = result.Neg()
+
1082 }
+
1083
+
1084 return Decimal{result}, nil
+
1085}
+
1086
+
1087// Set the decimal value
+
1088func (fm *FieldModelDecimal) Set(value Decimal) error {
+
1089 if (fm.buffer.Offset() + fm.FBEOffset() + fm.FBESize()) > fm.buffer.Size() {
+
1090 return errors.New("model is broken")
+
1091 }
+
1092
+
1093 // Extract decimal parts
+
1094 negative := value.IsNegative()
+
1095 number := value.Coefficient()
+
1096 scale := -value.Exponent()
+
1097
+
1098 // Check for decimal number overflow
+
1099 bits := number.BitLen()
+
1100 if (bits < 0) || (bits > 96) {
+
1101 // Value too big for .NET Decimal (bit length is limited to [0, 96])
+
1102 WriteCount(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset(), 0, fm.FBESize())
+
1103 return errors.New("value too big for .NET Decimal (bit length is limited to [0, 96])")
+
1104 }
+
1105
+
1106 // Check for decimal scale overflow
+
1107 if (scale < 0) || (scale > 28) {
+
1108 // Value scale exceeds .NET Decimal limit of [0, 28]
+
1109 WriteCount(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset(), 0, fm.FBESize())
+
1110 return errors.New("value scale exceeds .NET Decimal limit of [0, 28]")
+
1111 }
+
1112
+
1113 // Write unscaled value to bytes 0-11
+
1114 bytes := number.Bytes()
+
1115 for i := range bytes {
+
1116 WriteByte(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset() + i, bytes[len(bytes) - i - 1])
+
1117 }
+
1118 WriteCount(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset() + len(bytes), 0, 12 - len(bytes))
+
1119
+
1120 // Write scale at byte 14
+
1121 WriteByte(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset() + 14, byte(scale))
+
1122
+
1123 // Write signum at byte 15
+
1124 if negative {
+
1125 WriteByte(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset() + 15, 0x80)
+
1126 } else {
+
1127 WriteByte(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset() + 15, 0)
+
1128 }
+
1129 return nil
+
1130}
+
1131
+
1132var lowScaleField, midScaleField decimal.Decimal
+
1133
+
1134func init() {
+
1135 var low, mid big.Int
+
1136 low.SetString("18446744073709551616", 10)
+
1137 mid.SetString("4294967296", 10)
+
1138 lowScaleField = decimal.NewFromBigInt(&low, 0)
+
1139 midScaleField = decimal.NewFromBigInt(&mid, 0)
+
1140}
+
1141)CODE";
+
1142
+
1143 // Prepare code template
+
1144 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
1145
+
1146 Write(code);
+
1147
+
1148 // Generate footer
+
1149 GenerateFooter();
+
1150
+
1151 // Store the file
+
1152 WriteEnd();
+
1153 Store(file);
+
1154}
+
1155
+
1156void GeneratorGo::GenerateFBEFieldModelTimestamp(const std::string& package)
+
1157{
+
1158 CppCommon::Path path = CppCommon::Path(_output) / package;
+
1159
+
1160 // Generate the file
+
1161 CppCommon::Path file = path / ("FieldModelTimestamp.go");
+
1162 WriteBegin();
+
1163
+
1164 // Generate headers
+
1165 GenerateHeader("FBE");
+
1166
+
1167 std::string code = R"CODE(
+
1168package fbe
+
1169
+
1170import "errors"
+
1171
+
1172// Fast Binary Encoding timestamp field model
+
1173type FieldModelTimestamp struct {
+
1174 // Field model buffer
+
1175 buffer *Buffer
+
1176 // Field model buffer offset
+
1177 offset int
+
1178}
+
1179
+
1180// Create a new timestamp field model
+
1181func NewFieldModelTimestamp(buffer *Buffer, offset int) *FieldModelTimestamp {
+
1182 return &FieldModelTimestamp{buffer: buffer, offset: offset}
+
1183}
+
1184
+
1185// Get the field size
+
1186func (fm *FieldModelTimestamp) FBESize() int { return 8 }
+
1187// Get the field extra size
+
1188func (fm *FieldModelTimestamp) FBEExtra() int { return 0 }
+
1189
+
1190// Get the field offset
+
1191func (fm *FieldModelTimestamp) FBEOffset() int { return fm.offset }
+
1192// Set the field offset
+
1193func (fm *FieldModelTimestamp) SetFBEOffset(value int) { fm.offset = value }
+
1194
+
1195// Shift the current field offset
+
1196func (fm *FieldModelTimestamp) FBEShift(size int) { fm.offset += size }
+
1197// Unshift the current field offset
+
1198func (fm *FieldModelTimestamp) FBEUnshift(size int) { fm.offset -= size }
+
1199
+
1200// Check if the timestamp value is valid
+
1201func (fm *FieldModelTimestamp) Verify() bool { return true }
+
1202
+
1203// Get the timestamp value
+
1204func (fm *FieldModelTimestamp) Get() (Timestamp, error) {
+
1205 return fm.GetDefault(TimestampEpoch())
+
1206}
+
1207
+
1208// Get the timestamp value with provided default value
+
1209func (fm *FieldModelTimestamp) GetDefault(defaults Timestamp) (Timestamp, error) {
+
1210 if (fm.buffer.Offset() + fm.FBEOffset() + fm.FBESize()) > fm.buffer.Size() {
+
1211 return defaults, nil
+
1212 }
+
1213
+
1214 return ReadTimestamp(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset()), nil
+
1215}
+
1216
+
1217// Set the timestamp value
+
1218func (fm *FieldModelTimestamp) Set(value Timestamp) error {
+
1219 if (fm.buffer.Offset() + fm.FBEOffset() + fm.FBESize()) > fm.buffer.Size() {
+
1220 return errors.New("model is broken")
+
1221 }
+
1222
+
1223 WriteTimestamp(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset(), value)
+
1224 return nil
+
1225}
+
1226)CODE";
+
1227
+
1228 // Prepare code template
+
1229 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
1230
+
1231 Write(code);
+
1232
+
1233 // Generate footer
+
1234 GenerateFooter();
+
1235
+
1236 // Store the file
+
1237 WriteEnd();
+
1238 Store(file);
+
1239}
+
1240
+
1241void GeneratorGo::GenerateFBEFieldModelUUID(const std::string& package)
+
1242{
+
1243 CppCommon::Path path = CppCommon::Path(_output) / package;
+
1244
+
1245 // Generate the file
+
1246 CppCommon::Path file = path / ("FieldModelUUID.go");
+
1247 WriteBegin();
+
1248
+
1249 // Generate headers
+
1250 GenerateHeader("FBE");
+
1251
+
1252 std::string code = R"CODE(
+
1253package fbe
+
1254
+
1255import "errors"
+
1256
+
1257// Fast Binary Encoding UUID field model
+
1258type FieldModelUUID struct {
+
1259 // Field model buffer
+
1260 buffer *Buffer
+
1261 // Field model buffer offset
+
1262 offset int
+
1263}
+
1264
+
1265// Create a new UUID field model
+
1266func NewFieldModelUUID(buffer *Buffer, offset int) *FieldModelUUID {
+
1267 return &FieldModelUUID{buffer: buffer, offset: offset}
+
1268}
+
1269
+
1270// Get the field size
+
1271func (fm *FieldModelUUID) FBESize() int { return 16 }
+
1272// Get the field extra size
+
1273func (fm *FieldModelUUID) FBEExtra() int { return 0 }
+
1274
+
1275// Get the field offset
+
1276func (fm *FieldModelUUID) FBEOffset() int { return fm.offset }
+
1277// Set the field offset
+
1278func (fm *FieldModelUUID) SetFBEOffset(value int) { fm.offset = value }
+
1279
+
1280// Shift the current field offset
+
1281func (fm *FieldModelUUID) FBEShift(size int) { fm.offset += size }
+
1282// Unshift the current field offset
+
1283func (fm *FieldModelUUID) FBEUnshift(size int) { fm.offset -= size }
+
1284
+
1285// Check if the UUID value is valid
+
1286func (fm *FieldModelUUID) Verify() bool { return true }
+
1287
+
1288// Get the UUID value
+
1289func (fm *FieldModelUUID) Get() (UUID, error) {
+
1290 return fm.GetDefault(UUIDNil())
+
1291}
+
1292
+
1293// Get the UUID value with provided default value
+
1294func (fm *FieldModelUUID) GetDefault(defaults UUID) (UUID, error) {
+
1295 if (fm.buffer.Offset() + fm.FBEOffset() + fm.FBESize()) > fm.buffer.Size() {
+
1296 return defaults, nil
+
1297 }
+
1298
+
1299 return ReadUUID(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset()), nil
+
1300}
+
1301
+
1302// Set the UUID value
+
1303func (fm *FieldModelUUID) Set(value UUID) error {
+
1304 if (fm.buffer.Offset() + fm.FBEOffset() + fm.FBESize()) > fm.buffer.Size() {
+
1305 return errors.New("model is broken")
+
1306 }
+
1307
+
1308 WriteUUID(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset(), value)
+
1309 return nil
+
1310}
+
1311)CODE";
+
1312
+
1313 // Prepare code template
+
1314 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
1315
+
1316 Write(code);
+
1317
+
1318 // Generate footer
+
1319 GenerateFooter();
+
1320
+
1321 // Store the file
+
1322 WriteEnd();
+
1323 Store(file);
+
1324}
+
1325
+
1326void GeneratorGo::GenerateFBEFieldModelBytes(const std::string& package)
+
1327{
+
1328 CppCommon::Path path = CppCommon::Path(_output) / package;
+
1329
+
1330 // Generate the file
+
1331 CppCommon::Path file = path / ("FieldModelBytes.go");
+
1332 WriteBegin();
+
1333
+
1334 // Generate headers
+
1335 GenerateHeader("FBE");
+
1336
+
1337 std::string code = R"CODE(
+
1338package fbe
+
1339
+
1340import "errors"
+
1341
+
1342// Fast Binary Encoding bytes field model
+
1343type FieldModelBytes struct {
+
1344 // Field model buffer
+
1345 buffer *Buffer
+
1346 // Field model buffer offset
+
1347 offset int
+
1348}
+
1349
+
1350// Create a new bytes field model
+
1351func NewFieldModelBytes(buffer *Buffer, offset int) *FieldModelBytes {
+
1352 return &FieldModelBytes{buffer: buffer, offset: offset}
+
1353}
+
1354
+
1355// Get the field size
+
1356func (fm *FieldModelBytes) FBESize() int { return 4 }
+
1357// Get the field extra size
+
1358func (fm *FieldModelBytes) FBEExtra() int {
+
1359 if (fm.buffer.Offset() + fm.FBEOffset() + fm.FBESize()) > fm.buffer.Size() {
+
1360 return 0
+
1361 }
+
1362
+
1363 fbeBytesOffset := int(ReadUInt32(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset()))
+
1364 if (fbeBytesOffset == 0) || ((fm.buffer.Offset() + fbeBytesOffset + 4) > fm.buffer.Size()) {
+
1365 return 0
+
1366 }
+
1367
+
1368 fbeBytesSize := int(ReadUInt32(fm.buffer.Data(), fm.buffer.Offset() + fbeBytesOffset))
+
1369 return 4 + fbeBytesSize
+
1370}
+
1371
+
1372// Get the field offset
+
1373func (fm *FieldModelBytes) FBEOffset() int { return fm.offset }
+
1374// Set the field offset
+
1375func (fm *FieldModelBytes) SetFBEOffset(value int) { fm.offset = value }
+
1376
+
1377// Shift the current field offset
+
1378func (fm *FieldModelBytes) FBEShift(size int) { fm.offset += size }
+
1379// Unshift the current field offset
+
1380func (fm *FieldModelBytes) FBEUnshift(size int) { fm.offset -= size }
+
1381
+
1382// Check if the bytes value is valid
+
1383func (fm *FieldModelBytes) Verify() bool {
+
1384 if (fm.buffer.Offset() + fm.FBEOffset() + fm.FBESize()) > fm.buffer.Size() {
+
1385 return true
+
1386 }
+
1387
+
1388 fbeBytesOffset := int(ReadUInt32(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset()))
+
1389 if fbeBytesOffset == 0 {
+
1390 return true
+
1391 }
+
1392
+
1393 if (fm.buffer.Offset() + fbeBytesOffset + 4) > fm.buffer.Size() {
+
1394 return false
+
1395 }
+
1396
+
1397 fbeBytesSize := int(ReadUInt32(fm.buffer.Data(), fm.buffer.Offset() + fbeBytesOffset))
+
1398 if (fm.buffer.Offset() + fbeBytesOffset + 4 + fbeBytesSize) > fm.buffer.Size() {
+
1399 return false
+
1400 }
+
1401
+
1402 return true
+
1403}
+
1404
+
1405// Get the bytes value
+
1406func (fm *FieldModelBytes) Get() ([]byte, error) {
+
1407 return fm.GetDefault(make([]byte, 0))
+
1408}
+
1409
+
1410// Get the bytes value with provided default value
+
1411func (fm *FieldModelBytes) GetDefault(defaults []byte) ([]byte, error) {
+
1412 if (fm.buffer.Offset() + fm.FBEOffset() + fm.FBESize()) > fm.buffer.Size() {
+
1413 return defaults, nil
+
1414 }
+
1415
+
1416 fbeBytesOffset := int(ReadUInt32(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset()))
+
1417 if fbeBytesOffset == 0 {
+
1418 return defaults, nil
+
1419 }
+
1420
+
1421 if (fm.buffer.Offset() + fbeBytesOffset + 4) > fm.buffer.Size() {
+
1422 return defaults, errors.New("model is broken")
+
1423 }
+
1424
+
1425 fbeBytesSize := int(ReadUInt32(fm.buffer.Data(), fm.buffer.Offset() + fbeBytesOffset))
+
1426 if (fm.buffer.Offset() + fbeBytesOffset + 4 + fbeBytesSize) > fm.buffer.Size() {
+
1427 return defaults, errors.New("model is broken")
+
1428 }
+
1429
+
1430 return ReadBytes(fm.buffer.Data(), fm.buffer.Offset() + fbeBytesOffset + 4, fbeBytesSize), nil
+
1431}
+
1432
+
1433// Set the bytes value
+
1434func (fm *FieldModelBytes) Set(value []byte) error {
+
1435 if (fm.buffer.Offset() + fm.FBEOffset() + fm.FBESize()) > fm.buffer.Size() {
+
1436 return errors.New("model is broken")
+
1437 }
+
1438
+
1439 fbeBytesSize := len(value)
+
1440 fbeBytesOffset := fm.buffer.Allocate(4 + fbeBytesSize) - fm.buffer.Offset()
+
1441 if (fbeBytesOffset <= 0) || ((fm.buffer.Offset() + fbeBytesOffset + 4 + fbeBytesSize) > fm.buffer.Size()) {
+
1442 return errors.New("model is broken")
+
1443 }
+
1444
+
1445 WriteUInt32(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset(), uint32(fbeBytesOffset))
+
1446 WriteUInt32(fm.buffer.Data(), fm.buffer.Offset() + fbeBytesOffset, uint32(fbeBytesSize))
+
1447 WriteBytes(fm.buffer.Data(), fm.buffer.Offset() + fbeBytesOffset + 4, value)
+
1448 return nil
+
1449}
+
1450)CODE";
+
1451
+
1452 // Prepare code template
+
1453 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
1454
+
1455 Write(code);
+
1456
+
1457 // Generate footer
+
1458 GenerateFooter();
+
1459
+
1460 // Store the file
+
1461 WriteEnd();
+
1462 Store(file);
+
1463}
+
1464
+
1465void GeneratorGo::GenerateFBEFieldModelString(const std::string& package)
+
1466{
+
1467 CppCommon::Path path = CppCommon::Path(_output) / package;
+
1468
+
1469 // Generate the file
+
1470 CppCommon::Path file = path / ("FieldModelString.go");
+
1471 WriteBegin();
+
1472
+
1473 // Generate headers
+
1474 GenerateHeader("FBE");
+
1475
+
1476 std::string code = R"CODE(
+
1477package fbe
+
1478
+
1479import "errors"
+
1480
+
1481// Fast Binary Encoding string field model
+
1482type FieldModelString struct {
+
1483 // Field model buffer
+
1484 buffer *Buffer
+
1485 // Field model buffer offset
+
1486 offset int
+
1487}
+
1488
+
1489// Create a new string field model
+
1490func NewFieldModelString(buffer *Buffer, offset int) *FieldModelString {
+
1491 return &FieldModelString{buffer: buffer, offset: offset}
+
1492}
+
1493
+
1494// Get the field size
+
1495func (fm *FieldModelString) FBESize() int { return 4 }
+
1496// Get the field extra size
+
1497func (fm *FieldModelString) FBEExtra() int {
+
1498 if (fm.buffer.Offset() + fm.FBEOffset() + fm.FBESize()) > fm.buffer.Size() {
+
1499 return 0
+
1500 }
+
1501
+
1502 fbeStringOffset := int(ReadUInt32(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset()))
+
1503 if (fbeStringOffset == 0) || ((fm.buffer.Offset() + fbeStringOffset + 4) > fm.buffer.Size()) {
+
1504 return 0
+
1505 }
+
1506
+
1507 fbeStringSize := int(ReadUInt32(fm.buffer.Data(), fm.buffer.Offset() + fbeStringOffset))
+
1508 return 4 + fbeStringSize
+
1509}
+
1510
+
1511// Get the field offset
+
1512func (fm *FieldModelString) FBEOffset() int { return fm.offset }
+
1513// Set the field offset
+
1514func (fm *FieldModelString) SetFBEOffset(value int) { fm.offset = value }
+
1515
+
1516// Shift the current field offset
+
1517func (fm *FieldModelString) FBEShift(size int) { fm.offset += size }
+
1518// Unshift the current field offset
+
1519func (fm *FieldModelString) FBEUnshift(size int) { fm.offset -= size }
+
1520
+
1521// Check if the string value is valid
+
1522func (fm *FieldModelString) Verify() bool {
+
1523 if (fm.buffer.Offset() + fm.FBEOffset() + fm.FBESize()) > fm.buffer.Size() {
+
1524 return true
+
1525 }
+
1526
+
1527 fbeStringOffset := int(ReadUInt32(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset()))
+
1528 if fbeStringOffset == 0 {
+
1529 return true
+
1530 }
+
1531
+
1532 if (fm.buffer.Offset() + fbeStringOffset + 4) > fm.buffer.Size() {
+
1533 return false
+
1534 }
+
1535
+
1536 fbeStringSize := int(ReadUInt32(fm.buffer.Data(), fm.buffer.Offset() + fbeStringOffset))
+
1537 if (fm.buffer.Offset() + fbeStringOffset + 4 + fbeStringSize) > fm.buffer.Size() {
+
1538 return false
+
1539 }
+
1540
+
1541 return true
+
1542}
+
1543
+
1544// Get the string value
+
1545func (fm *FieldModelString) Get() (string, error) {
+
1546 return fm.GetDefault("")
+
1547}
+
1548
+
1549// Get the string value with provided default value
+
1550func (fm *FieldModelString) GetDefault(defaults string) (string, error) {
+
1551 if (fm.buffer.Offset() + fm.FBEOffset() + fm.FBESize()) > fm.buffer.Size() {
+
1552 return defaults, nil
+
1553 }
+
1554
+
1555 fbeStringOffset := int(ReadUInt32(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset()))
+
1556 if fbeStringOffset == 0 {
+
1557 return defaults, nil
+
1558 }
+
1559
+
1560 if (fm.buffer.Offset() + fbeStringOffset + 4) > fm.buffer.Size() {
+
1561 return defaults, errors.New("model is broken")
+
1562 }
+
1563
+
1564 fbeStringSize := int(ReadUInt32(fm.buffer.Data(), fm.buffer.Offset() + fbeStringOffset))
+
1565 if (fm.buffer.Offset() + fbeStringOffset + 4 + fbeStringSize) > fm.buffer.Size() {
+
1566 return defaults, errors.New("model is broken")
+
1567 }
+
1568
+
1569 data := ReadBytes(fm.buffer.Data(), fm.buffer.Offset() + fbeStringOffset + 4, fbeStringSize)
+
1570 return string(data), nil
+
1571}
+
1572
+
1573// Set the string value
+
1574func (fm *FieldModelString) Set(value string) error {
+
1575 if (fm.buffer.Offset() + fm.FBEOffset() + fm.FBESize()) > fm.buffer.Size() {
+
1576 return errors.New("model is broken")
+
1577 }
+
1578
+
1579 data := []byte(value)
+
1580
+
1581 fbeStringSize := len(data)
+
1582 fbeStringOffset := fm.buffer.Allocate(4 + fbeStringSize) - fm.buffer.Offset()
+
1583 if (fbeStringOffset <= 0) || ((fm.buffer.Offset() + fbeStringOffset + 4 + fbeStringSize) > fm.buffer.Size()) {
+
1584 return errors.New("model is broken")
+
1585 }
+
1586
+
1587 WriteUInt32(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset(), uint32(fbeStringOffset))
+
1588 WriteUInt32(fm.buffer.Data(), fm.buffer.Offset() + fbeStringOffset, uint32(fbeStringSize))
+
1589 WriteBytes(fm.buffer.Data(), fm.buffer.Offset() + fbeStringOffset + 4, data)
+
1590 return nil
+
1591}
+
1592)CODE";
+
1593
+
1594 // Prepare code template
+
1595 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
1596
+
1597 Write(code);
+
1598
+
1599 // Generate footer
+
1600 GenerateFooter();
+
1601
+
1602 // Store the file
+
1603 WriteEnd();
+
1604 Store(file);
+
1605}
+
1606
+
1607void GeneratorGo::GenerateFBEFieldModelOptional(const std::shared_ptr<Package>& p, const std::string& name, const std::string& model, const StructField& field, const CppCommon::Path& path)
+
1608{
+
1609 // Generate the output file
+
1610 CppCommon::Path output = path / ("FieldModelOptional" + name + ".go");
+
1611 WriteBegin();
+
1612
+
1613 // Generate headers
+
1614 GenerateHeader("FBE");
+
1615
+
1616 // Generate package
+
1617 WriteLine();
+
1618 WriteLineIndent("package " + *p->name);
+
1619
+
1620 // Generate imports
+
1621 WriteLine();
+
1622 GenerateImports(p);
+
1623
+
1624 std::string code = R"CODE(
+
1625// Fast Binary Encoding optional _NAME_ field model
+
1626type FieldModelOptional_NAME_ struct {
+
1627 // Field model buffer
+
1628 buffer *fbe.Buffer
+
1629 // Field model buffer offset
+
1630 offset int
+
1631
+
1632 // Base field model value
+
1633 value *_MODEL_
+
1634}
+
1635
+
1636// Create a new optional _NAME_ field model
+
1637func NewFieldModelOptional_NAME_(buffer *fbe.Buffer, offset int) *FieldModelOptional_NAME_ {
+
1638 fbeResult := FieldModelOptional_NAME_{buffer: buffer, offset: offset}
+
1639 fbeResult.value = _MODEL_NEW_(buffer, 0)
+
1640 return &fbeResult
+
1641}
+
1642
+
1643// Get the optional field model value
+
1644func (fm *FieldModelOptional_NAME_) Value() *_MODEL_ { return fm.value }
+
1645
+
1646// Get the field size
+
1647func (fm *FieldModelOptional_NAME_) FBESize() int { return 1 + 4 }
+
1648
+
1649// Get the field extra size
+
1650func (fm *FieldModelOptional_NAME_) FBEExtra() int {
+
1651 if !fm.HasValue() {
+
1652 return 0
+
1653 }
+
1654
+
1655 fbeOptionalOffset := int(fbe.ReadUInt32(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset() + 1))
+
1656 if (fbeOptionalOffset == 0) || ((fm.buffer.Offset() + fbeOptionalOffset + 4) > fm.buffer.Size()) {
+
1657 return 0
+
1658 }
+
1659
+
1660 fm.buffer.Shift(fbeOptionalOffset)
+
1661 fbeResult := fm.value.FBESize() + fm.value.FBEExtra()
+
1662 fm.buffer.Unshift(fbeOptionalOffset)
+
1663 return fbeResult
+
1664}
+
1665
+
1666// Get the field offset
+
1667func (fm *FieldModelOptional_NAME_) FBEOffset() int { return fm.offset }
+
1668// Set the field offset
+
1669func (fm *FieldModelOptional_NAME_) SetFBEOffset(value int) { fm.offset = value }
+
1670
+
1671// Shift the current field offset
+
1672func (fm *FieldModelOptional_NAME_) FBEShift(size int) { fm.offset += size }
+
1673// Unshift the current field offset
+
1674func (fm *FieldModelOptional_NAME_) FBEUnshift(size int) { fm.offset -= size }
+
1675
+
1676// Check if the object contains a value
+
1677func (fm *FieldModelOptional_NAME_) HasValue() bool {
+
1678 if (fm.buffer.Offset() + fm.FBEOffset() + fm.FBESize()) > fm.buffer.Size() {
+
1679 return false
+
1680 }
+
1681
+
1682 fbeHasValue := fbe.ReadUInt8(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset())
+
1683 return fbeHasValue != 0
+
1684}
+
1685
+
1686// Check if the optional value is valid
+
1687func (fm *FieldModelOptional_NAME_) Verify() bool {
+
1688 if (fm.buffer.Offset() + fm.FBEOffset() + fm.FBESize()) > fm.buffer.Size() {
+
1689 return true
+
1690 }
+
1691
+
1692 fbeHasValue := fbe.ReadUInt8(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset())
+
1693 if fbeHasValue == 0 {
+
1694 return true
+
1695 }
+
1696
+
1697 fbeOptionalOffset := int(fbe.ReadUInt32(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset() + 1))
+
1698 if fbeOptionalOffset == 0 {
+
1699 return false
+
1700 }
+
1701
+
1702 fm.buffer.Shift(fbeOptionalOffset)
+
1703 fbeResult := fm.value.Verify()
+
1704 fm.buffer.Unshift(fbeOptionalOffset)
+
1705 return fbeResult
+
1706}
+
1707
+
1708// Get the optional value (being phase)
+
1709func (fm *FieldModelOptional_NAME_) GetBegin() (int, error) {
+
1710 if !fm.HasValue() {
+
1711 return 0, nil
+
1712 }
+
1713
+
1714 fbeOptionalOffset := int(fbe.ReadUInt32(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset() + 1))
+
1715 if fbeOptionalOffset <= 0 {
+
1716 return 0, errors.New("model is broken")
+
1717 }
+
1718
+
1719 fm.buffer.Shift(fbeOptionalOffset)
+
1720 return fbeOptionalOffset, nil
+
1721}
+
1722
+
1723// Get the optional value (end phase)
+
1724func (fm *FieldModelOptional_NAME_) GetEnd(fbeBegin int) {
+
1725 fm.buffer.Unshift(fbeBegin)
+
1726}
+
1727
+
1728// Get the optional value
+
1729func (fm *FieldModelOptional_NAME_) Get() (_TYPE_ARG_, error) {
+
1730 var fbeValue _TYPE_ARG_ = nil
+
1731
+
1732 fbeBegin, err := fm.GetBegin()
+
1733 if fbeBegin == 0 {
+
1734 return fbeValue, err
+
1735 }
+
1736
+
1737 fbeValue = _TYPE_NEW_
+
1738
+
1739 _GET_VALUE_
+
1740 fm.GetEnd(fbeBegin)
+
1741 return fbeValue, err
+
1742}
+
1743
+
1744// Set the optional value (begin phase)
+
1745func (fm *FieldModelOptional_NAME_) SetBegin(hasValue bool) (int, error) {
+
1746 if (fm.buffer.Offset() + fm.FBEOffset() + fm.FBESize()) > fm.buffer.Size() {
+
1747 return 0, nil
+
1748 }
+
1749
+
1750 fbeHasValue := uint8(0)
+
1751 if hasValue {
+
1752 fbeHasValue = uint8(1)
+
1753 }
+
1754 fbe.WriteUInt8(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset(), fbeHasValue)
+
1755 if fbeHasValue == 0 {
+
1756 return 0, nil
+
1757 }
+
1758
+
1759 fbeOptionalSize := fm.value.FBESize()
+
1760 fbeOptionalOffset := fm.buffer.Allocate(fbeOptionalSize) - fm.buffer.Offset()
+
1761 if (fbeOptionalOffset <= 0) || ((fm.buffer.Offset() + fbeOptionalOffset + fbeOptionalSize) > fm.buffer.Size()) {
+
1762 return 0, errors.New("model is broken")
+
1763 }
+
1764
+
1765 fbe.WriteUInt32(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset() + 1, uint32(fbeOptionalOffset))
+
1766
+
1767 fm.buffer.Shift(fbeOptionalOffset)
+
1768 return fbeOptionalOffset, nil
+
1769}
+
1770
+
1771// Set the optional value (end phase)
+
1772func (fm *FieldModelOptional_NAME_) SetEnd(fbeBegin int) {
+
1773 fm.buffer.Unshift(fbeBegin)
+
1774}
+
1775
+
1776// Set the optional value
+
1777func (fm *FieldModelOptional_NAME_) Set(fbeValue _TYPE_ARG_) error {
+
1778 fbeBegin, err := fm.SetBegin(fbeValue != nil)
+
1779 if fbeBegin == 0 {
+
1780 return err
+
1781 }
+
1782
+
1783 _SET_VALUE_
+
1784 fm.SetEnd(fbeBegin)
+
1785 return err
+
1786}
+
1787)CODE";
+
1788
+
1789 // Prepare code template
+
1790 code = std::regex_replace(code, std::regex("_NAME_"), name);
+
1791 code = std::regex_replace(code, std::regex("_TYPE_ARG_"), ConvertTypeName(*field.type, field.optional));
+
1792 code = std::regex_replace(code, std::regex("_TYPE_NEW_"), IsGoType(*field.type) ? ConvertOptional(*field.type) : (ConvertNewName(*field.type) + "()"));
+
1793 code = std::regex_replace(code, std::regex("_TYPE_"), ConvertTypeFieldType(*field.type, field.optional));
+
1794 code = std::regex_replace(code, std::regex("_MODEL_NEW_"), ConvertNewName(model));
+
1795 code = std::regex_replace(code, std::regex("_MODEL_"), model);
+
1796 code = std::regex_replace(code, std::regex("_GET_VALUE_"), IsGoType(*field.type) ? "*fbeValue, err = fm.value.Get()" : "err = fm.value.GetValue(fbeValue)");
+
1797 code = std::regex_replace(code, std::regex("_SET_VALUE_"), IsGoType(*field.type) ? "err = fm.value.Set(*fbeValue)" : "err = fm.value.Set(fbeValue)");
+
1798 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
1799
+
1800 Write(code);
+
1801
+
1802 // Generate footer
+
1803 GenerateFooter();
+
1804
+
1805 // Store the output file
+
1806 WriteEnd();
+
1807 Store(output);
+
1808}
+
1809
+
1810void GeneratorGo::GenerateFBEFieldModelArray(const std::shared_ptr<Package>& p, const std::string& name, const std::string& model, const StructField& field, const CppCommon::Path& path)
+
1811{
+
1812 // Generate the output file
+
1813 CppCommon::Path output = path / ("FieldModelArray" + name + ".go");
+
1814 WriteBegin();
+
1815
+
1816 // Generate headers
+
1817 GenerateHeader("FBE");
+
1818
+
1819 // Generate package
+
1820 WriteLine();
+
1821 WriteLineIndent("package " + *p->name);
+
1822
+
1823 // Generate imports
+
1824 WriteLine();
+
1825 GenerateImports(p);
+
1826
+
1827 std::string code = R"CODE(
+
1828// Fast Binary Encoding _NAME_ array field model
+
1829type FieldModelArray_NAME_ struct {
+
1830 // Field model buffer
+
1831 buffer *fbe.Buffer
+
1832 // Field model buffer offset
+
1833 offset int
+
1834
+
1835 // Array item field model
+
1836 model *_MODEL_
+
1837 // Array size
+
1838 size int
+
1839}
+
1840
+
1841// Create a new _NAME_ array field model
+
1842func NewFieldModelArray_NAME_(buffer *fbe.Buffer, offset int, size int) *FieldModelArray_NAME_ {
+
1843 fbeResult := FieldModelArray_NAME_{buffer: buffer, offset: offset}
+
1844 fbeResult.model = _MODEL_NEW_(buffer, offset)
+
1845 fbeResult.size = size
+
1846 return &fbeResult
+
1847}
+
1848
+
1849// Get the field size
+
1850func (fm *FieldModelArray_NAME_) FBESize() int { return fm.size * fm.model.FBESize() }
+
1851
+
1852// Get the field extra size
+
1853func (fm *FieldModelArray_NAME_) FBEExtra() int { return 0 }
+
1854
+
1855// Get the field offset
+
1856func (fm *FieldModelArray_NAME_) FBEOffset() int { return fm.offset }
+
1857// Set the field offset
+
1858func (fm *FieldModelArray_NAME_) SetFBEOffset(value int) { fm.offset = value }
+
1859
+
1860// Shift the current field offset
+
1861func (fm *FieldModelArray_NAME_) FBEShift(size int) { fm.offset += size }
+
1862// Unshift the current field offset
+
1863func (fm *FieldModelArray_NAME_) FBEUnshift(size int) { fm.offset -= size }
+
1864
+
1865// Get the array offset
+
1866func (fm *FieldModelArray_NAME_) Offset() int { return 0 }
+
1867// Get the array size
+
1868func (fm *FieldModelArray_NAME_) Size() int { return fm.size }
+
1869
+
1870// Array index operator
+
1871func (fm *FieldModelArray_NAME_) GetItem(index int) (*_MODEL_, error) {
+
1872 if (fm.buffer.Offset() + fm.FBEOffset() + fm.FBESize()) > fm.buffer.Size() {
+
1873 return nil, errors.New("model is broken")
+
1874 }
+
1875 if index >= fm.size {
+
1876 return nil, errors.New("index is out of bounds")
+
1877 }
+
1878
+
1879 fm.model.SetFBEOffset(fm.FBEOffset())
+
1880 fm.model.FBEShift(index * fm.model.FBESize())
+
1881 return fm.model, nil
+
1882}
+
1883
+
1884// Check if the array is valid
+
1885func (fm *FieldModelArray_NAME_) Verify() bool {
+
1886 if (fm.buffer.Offset() + fm.FBEOffset() + fm.FBESize()) > fm.buffer.Size() {
+
1887 return false
+
1888 }
+
1889
+
1890 fm.model.SetFBEOffset(fm.FBEOffset())
+
1891 for i := 0; i < fm.size; i++ {
+
1892 if !fm.model.Verify() {
+
1893 return false
+
1894 }
+
1895 fm.model.FBEShift(fm.model.FBESize())
+
1896 }
+
1897
+
1898 return true
+
1899}
+
1900
+
1901// Get the array
+
1902func (fm *FieldModelArray_NAME_) Get() ([]_TYPE_, error) {
+
1903 values := make([]_TYPE_, 0, fm.size)
+
1904
+
1905 fbeModel, err := fm.GetItem(0)
+
1906 if err != nil {
+
1907 return values, err
+
1908 }
+
1909
+
1910 for i := 0; i < fm.size; i++ {
+
1911 value, err := fbeModel.Get()
+
1912 if err != nil {
+
1913 return values, err
+
1914 }
+
1915 values = append(values, _GET_VALUE_)
+
1916 fbeModel.FBEShift(fbeModel.FBESize())
+
1917 }
+
1918
+
1919 return values, nil
+
1920}
+
1921
+
1922// Set the array
+
1923func (fm *FieldModelArray_NAME_) Set(values []_TYPE_) error {
+
1924 if (fm.buffer.Offset() + fm.FBEOffset() + fm.FBESize()) > fm.buffer.Size() {
+
1925 return errors.New("model is broken")
+
1926 }
+
1927
+
1928 fbeModel, err := fm.GetItem(0)
+
1929 if err != nil {
+
1930 return err
+
1931 }
+
1932
+
1933 size := len(values)
+
1934 if size > fm.size {
+
1935 size = fm.size
+
1936 }
+
1937
+
1938 for i := 0; i < size; i++ {
+
1939 err := fbeModel.Set(_SET_VALUE_)
+
1940 if err != nil {
+
1941 return err
+
1942 }
+
1943 fbeModel.FBEShift(fbeModel.FBESize())
+
1944 }
+
1945
+
1946 return nil
+
1947}
+
1948)CODE";
+
1949
+
1950 // Prepare code template
+
1951 code = std::regex_replace(code, std::regex("_NAME_"), name);
+
1952 code = std::regex_replace(code, std::regex("_TYPE_"), ConvertTypeFieldType(*field.type, field.optional));
+
1953 code = std::regex_replace(code, std::regex("_MODEL_NEW_"), ConvertNewName(model));
+
1954 code = std::regex_replace(code, std::regex("_MODEL_"), model);
+
1955 code = std::regex_replace(code, std::regex("_GET_VALUE_"), (IsGoType(*field.type) || field.optional) ? "value" : "*value");
+
1956 code = std::regex_replace(code, std::regex("_SET_VALUE_"), (IsGoType(*field.type) || field.optional) ? "values[i]" : "&values[i]");
+
1957 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
1958
+
1959 Write(code);
+
1960
+
1961 // Generate footer
+
1962 GenerateFooter();
+
1963
+
1964 // Store the output file
+
1965 WriteEnd();
+
1966 Store(output);
+
1967}
+
1968
+
1969void GeneratorGo::GenerateFBEFieldModelVector(const std::shared_ptr<Package>& p, const std::string& name, const std::string& model, const StructField& field, const CppCommon::Path& path)
+
1970{
+
1971 // Generate the output file
+
1972 CppCommon::Path output = path / ("FieldModelVector" + name + ".go");
+
1973 WriteBegin();
+
1974
+
1975 // Generate headers
+
1976 GenerateHeader("FBE");
+
1977
+
1978 // Generate package
+
1979 WriteLine();
+
1980 WriteLineIndent("package " + *p->name);
+
1981
+
1982 // Generate imports
+
1983 WriteLine();
+
1984 GenerateImports(p);
+
1985
+
1986 std::string code = R"CODE(
+
1987// Fast Binary Encoding _NAME_ vector field model
+
1988type FieldModelVector_NAME_ struct {
+
1989 // Field model buffer
+
1990 buffer *fbe.Buffer
+
1991 // Field model buffer offset
+
1992 offset int
+
1993
+
1994 // Vector item field model
+
1995 model *_MODEL_
+
1996}
+
1997
+
1998// Create a new _NAME_ vector field model
+
1999func NewFieldModelVector_NAME_(buffer *fbe.Buffer, offset int) *FieldModelVector_NAME_ {
+
2000 fbeResult := FieldModelVector_NAME_{buffer: buffer, offset: offset}
+
2001 fbeResult.model = _MODEL_NEW_(buffer, offset)
+
2002 return &fbeResult
+
2003}
+
2004
+
2005// Get the field size
+
2006func (fm *FieldModelVector_NAME_) FBESize() int { return 4 }
+
2007
+
2008// Get the field extra size
+
2009func (fm *FieldModelVector_NAME_) FBEExtra() int {
+
2010 if (fm.buffer.Offset() + fm.FBEOffset() + fm.FBESize()) > fm.buffer.Size() {
+
2011 return 0
+
2012 }
+
2013
+
2014 fbeVectorOffset := int(fbe.ReadUInt32(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset()))
+
2015 if (fbeVectorOffset == 0) || ((fm.buffer.Offset() + fbeVectorOffset + 4) > fm.buffer.Size()) {
+
2016 return 0
+
2017 }
+
2018
+
2019 fbeVectorSize := int(fbe.ReadUInt32(fm.buffer.Data(), fm.buffer.Offset() + fbeVectorOffset))
+
2020
+
2021 fbeResult := 0
+
2022 fm.model.SetFBEOffset(fbeVectorOffset + 4)
+
2023 for i := fbeVectorSize; i > 0; i-- {
+
2024 fbeResult += fm.model.FBESize() + fm.model.FBEExtra()
+
2025 fm.model.FBEShift(fm.model.FBESize())
+
2026 }
+
2027 return fbeResult
+
2028}
+
2029
+
2030// Get the field offset
+
2031func (fm *FieldModelVector_NAME_) FBEOffset() int { return fm.offset }
+
2032// Set the field offset
+
2033func (fm *FieldModelVector_NAME_) SetFBEOffset(value int) { fm.offset = value }
+
2034
+
2035// Shift the current field offset
+
2036func (fm *FieldModelVector_NAME_) FBEShift(size int) { fm.offset += size }
+
2037// Unshift the current field offset
+
2038func (fm *FieldModelVector_NAME_) FBEUnshift(size int) { fm.offset -= size }
+
2039
+
2040// Get the vector offset
+
2041func (fm *FieldModelVector_NAME_) Offset() int {
+
2042 if (fm.buffer.Offset() + fm.FBEOffset() + fm.FBESize()) > fm.buffer.Size() {
+
2043 return 0
+
2044 }
+
2045
+
2046 fbeVectorOffset := int(fbe.ReadUInt32(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset()))
+
2047 return fbeVectorOffset
+
2048}
+
2049
+
2050// Get the vector size
+
2051func (fm *FieldModelVector_NAME_) Size() int {
+
2052 if (fm.buffer.Offset() + fm.FBEOffset() + fm.FBESize()) > fm.buffer.Size() {
+
2053 return 0
+
2054 }
+
2055
+
2056 fbeVectorOffset := int(fbe.ReadUInt32(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset()))
+
2057 if (fbeVectorOffset == 0) || ((fm.buffer.Offset() + fbeVectorOffset + 4) > fm.buffer.Size()) {
+
2058 return 0
+
2059 }
+
2060
+
2061 fbeVectorSize := int(fbe.ReadUInt32(fm.buffer.Data(), fm.buffer.Offset() + fbeVectorOffset))
+
2062 return fbeVectorSize
+
2063}
+
2064
+
2065// Vector index operator
+
2066func (fm *FieldModelVector_NAME_) GetItem(index int) (*_MODEL_, error) {
+
2067 if (fm.buffer.Offset() + fm.FBEOffset() + fm.FBESize()) > fm.buffer.Size() {
+
2068 return nil, errors.New("model is broken")
+
2069 }
+
2070
+
2071 fbeVectorOffset := int(fbe.ReadUInt32(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset()))
+
2072 if (fbeVectorOffset == 0) || ((fm.buffer.Offset() + fbeVectorOffset + 4) > fm.buffer.Size()) {
+
2073 return nil, errors.New("model is broken")
+
2074 }
+
2075
+
2076 fbeVectorSize := int(fbe.ReadUInt32(fm.buffer.Data(), fm.buffer.Offset() + fbeVectorOffset))
+
2077 if index >= fbeVectorSize {
+
2078 return nil, errors.New("index is out of bounds")
+
2079 }
+
2080
+
2081 fm.model.SetFBEOffset(fbeVectorOffset + 4)
+
2082 fm.model.FBEShift(index * fm.model.FBESize())
+
2083 return fm.model, nil
+
2084}
+
2085
+
2086// Resize the vector and get its first model
+
2087func (fm *FieldModelVector_NAME_) Resize(size int) (*_MODEL_, error) {
+
2088 fbeVectorSize := size * fm.model.FBESize()
+
2089 fbeVectorOffset := fm.buffer.Allocate(4 + fbeVectorSize) - fm.buffer.Offset()
+
2090 if (fbeVectorOffset == 0) || ((fm.buffer.Offset() + fbeVectorOffset + 4) > fm.buffer.Size()) {
+
2091 return nil, errors.New("model is broken")
+
2092 }
+
2093
+
2094 fbe.WriteUInt32(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset(), uint32(fbeVectorOffset))
+
2095 fbe.WriteUInt32(fm.buffer.Data(), fm.buffer.Offset() + fbeVectorOffset, uint32(size))
+
2096 fbe.WriteCount(fm.buffer.Data(), fm.buffer.Offset() + fbeVectorOffset + 4, 0, fbeVectorSize)
+
2097
+
2098 fm.model.SetFBEOffset(fbeVectorOffset + 4)
+
2099 return fm.model, nil
+
2100}
+
2101
+
2102// Check if the vector is valid
+
2103func (fm *FieldModelVector_NAME_) Verify() bool {
+
2104 if (fm.buffer.Offset() + fm.FBEOffset() + fm.FBESize()) > fm.buffer.Size() {
+
2105 return true
+
2106 }
+
2107
+
2108 fbeVectorOffset := int(fbe.ReadUInt32(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset()))
+
2109 if fbeVectorOffset == 0 {
+
2110 return true
+
2111 }
+
2112
+
2113 if (fm.buffer.Offset() + fbeVectorOffset + 4) > fm.buffer.Size() {
+
2114 return false
+
2115 }
+
2116
+
2117 fbeVectorSize := int(fbe.ReadUInt32(fm.buffer.Data(), fm.buffer.Offset() + fbeVectorOffset))
+
2118
+
2119 fm.model.SetFBEOffset(fbeVectorOffset + 4)
+
2120 for i := fbeVectorSize; i > 0; i-- {
+
2121 if !fm.model.Verify() {
+
2122 return false
+
2123 }
+
2124 fm.model.FBEShift(fm.model.FBESize())
+
2125 }
+
2126
+
2127 return true
+
2128}
+
2129
+
2130// Get the vector
+
2131func (fm *FieldModelVector_NAME_) Get() ([]_TYPE_, error) {
+
2132 values := make([]_TYPE_, 0)
+
2133
+
2134 fbeVectorSize := fm.Size()
+
2135 if fbeVectorSize == 0 {
+
2136 return values, nil
+
2137 }
+
2138
+
2139 values = make([]_TYPE_, 0, fbeVectorSize)
+
2140
+
2141 fbeModel, err := fm.GetItem(0)
+
2142 if err != nil {
+
2143 return values, err
+
2144 }
+
2145
+
2146 for i := fbeVectorSize; i > 0; i-- {
+
2147 value, err := fbeModel.Get()
+
2148 if err != nil {
+
2149 return values, err
+
2150 }
+
2151 values = append(values, _GET_VALUE_)
+
2152 fbeModel.FBEShift(fbeModel.FBESize())
+
2153 }
+
2154
+
2155 return values, nil
+
2156}
+
2157
+
2158// Set the vector
+
2159func (fm *FieldModelVector_NAME_) Set(values []_TYPE_) error {
+
2160 if (fm.buffer.Offset() + fm.FBEOffset() + fm.FBESize()) > fm.buffer.Size() {
+
2161 return errors.New("model is broken")
+
2162 }
+
2163
+
2164 fbeModel, err := fm.Resize(len(values))
+
2165 if err != nil {
+
2166 return err
+
2167 }
+
2168
+
2169 for _, value := range values {
+
2170 err := fbeModel.Set(_SET_VALUE_)
+
2171 if err != nil {
+
2172 return err
+
2173 }
+
2174 fbeModel.FBEShift(fbeModel.FBESize())
+
2175 }
+
2176
+
2177 return nil
+
2178}
+
2179)CODE";
+
2180
+
2181 // Prepare code template
+
2182 code = std::regex_replace(code, std::regex("_NAME_"), name);
+
2183 code = std::regex_replace(code, std::regex("_TYPE_"), ConvertTypeFieldType(*field.type, field.optional));
+
2184 code = std::regex_replace(code, std::regex("_MODEL_NEW_"), ConvertNewName(model));
+
2185 code = std::regex_replace(code, std::regex("_MODEL_"), model);
+
2186 code = std::regex_replace(code, std::regex("_GET_VALUE_"), (IsGoType(*field.type) || field.optional) ? "value" : "*value");
+
2187 code = std::regex_replace(code, std::regex("_SET_VALUE_"), (IsGoType(*field.type) || field.optional) ? "value" : "&value");
+
2188 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2189
+
2190 Write(code);
+
2191
+
2192 // Generate footer
+
2193 GenerateFooter();
+
2194
+
2195 // Store the output file
+
2196 WriteEnd();
+
2197 Store(output);
+
2198}
+
2199
+
2200void GeneratorGo::GenerateFBEFieldModelSet(const std::shared_ptr<Package>& p, const std::string& name, const std::string& model, const StructField& field, const CppCommon::Path& path)
+
2201{
+
2202 // Generate the output file
+
2203 CppCommon::Path output = path / ("FieldModelSet" + name + ".go");
+
2204 WriteBegin();
+
2205
+
2206 // Generate headers
+
2207 GenerateHeader("FBE");
+
2208
+
2209 // Generate package
+
2210 WriteLine();
+
2211 WriteLineIndent("package " + *p->name);
+
2212
+
2213 // Generate imports
+
2214 WriteLine();
+
2215 GenerateImports(p);
+
2216
+
2217 std::string code = R"CODE(
+
2218// Fast Binary Encoding _NAME_ set field model
+
2219type FieldModelSet_NAME_ struct {
+
2220 // Field model buffer
+
2221 buffer *fbe.Buffer
+
2222 // Field model buffer offset
+
2223 offset int
+
2224
+
2225 // Set item field model
+
2226 model *_MODEL_
+
2227}
+
2228
+
2229// Create a new _NAME_ set field model
+
2230func NewFieldModelSet_NAME_(buffer *fbe.Buffer, offset int) *FieldModelSet_NAME_ {
+
2231 fbeResult := FieldModelSet_NAME_{buffer: buffer, offset: offset}
+
2232 fbeResult.model = _MODEL_NEW_(buffer, offset)
+
2233 return &fbeResult
+
2234}
+
2235
+
2236// Get the field size
+
2237func (fm *FieldModelSet_NAME_) FBESize() int { return 4 }
+
2238
+
2239// Get the field extra size
+
2240func (fm *FieldModelSet_NAME_) FBEExtra() int {
+
2241 if (fm.buffer.Offset() + fm.FBEOffset() + fm.FBESize()) > fm.buffer.Size() {
+
2242 return 0
+
2243 }
+
2244
+
2245 fbeSetOffset := int(fbe.ReadUInt32(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset()))
+
2246 if (fbeSetOffset == 0) || ((fm.buffer.Offset() + fbeSetOffset + 4) > fm.buffer.Size()) {
+
2247 return 0
+
2248 }
+
2249
+
2250 fbeSetSize := int(fbe.ReadUInt32(fm.buffer.Data(), fm.buffer.Offset() + fbeSetOffset))
+
2251
+
2252 fbeResult := 0
+
2253 fm.model.SetFBEOffset(fbeSetOffset + 4)
+
2254 for i := fbeSetSize; i > 0; i-- {
+
2255 fbeResult += fm.model.FBESize() + fm.model.FBEExtra()
+
2256 fm.model.FBEShift(fm.model.FBESize())
+
2257 }
+
2258 return fbeResult
+
2259}
+
2260
+
2261// Get the field offset
+
2262func (fm *FieldModelSet_NAME_) FBEOffset() int { return fm.offset }
+
2263// Set the field offset
+
2264func (fm *FieldModelSet_NAME_) SetFBEOffset(value int) { fm.offset = value }
+
2265
+
2266// Shift the current field offset
+
2267func (fm *FieldModelSet_NAME_) FBEShift(size int) { fm.offset += size }
+
2268// Unshift the current field offset
+
2269func (fm *FieldModelSet_NAME_) FBEUnshift(size int) { fm.offset -= size }
+
2270
+
2271// Get the set offset
+
2272func (fm *FieldModelSet_NAME_) Offset() int {
+
2273 if (fm.buffer.Offset() + fm.FBEOffset() + fm.FBESize()) > fm.buffer.Size() {
+
2274 return 0
+
2275 }
+
2276
+
2277 fbeSetOffset := int(fbe.ReadUInt32(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset()))
+
2278 return fbeSetOffset
+
2279}
+
2280
+
2281// Get the set size
+
2282func (fm *FieldModelSet_NAME_) Size() int {
+
2283 if (fm.buffer.Offset() + fm.FBEOffset() + fm.FBESize()) > fm.buffer.Size() {
+
2284 return 0
+
2285 }
+
2286
+
2287 fbeSetOffset := int(fbe.ReadUInt32(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset()))
+
2288 if (fbeSetOffset == 0) || ((fm.buffer.Offset() + fbeSetOffset + 4) > fm.buffer.Size()) {
+
2289 return 0
+
2290 }
+
2291
+
2292 fbeSetSize := int(fbe.ReadUInt32(fm.buffer.Data(), fm.buffer.Offset() + fbeSetOffset))
+
2293 return fbeSetSize
+
2294}
+
2295
+
2296// Set index operator
+
2297func (fm *FieldModelSet_NAME_) GetItem(index int) (*_MODEL_, error) {
+
2298 if (fm.buffer.Offset() + fm.FBEOffset() + fm.FBESize()) > fm.buffer.Size() {
+
2299 return nil, errors.New("model is broken")
+
2300 }
+
2301
+
2302 fbeSetOffset := int(fbe.ReadUInt32(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset()))
+
2303 if (fbeSetOffset == 0) || ((fm.buffer.Offset() + fbeSetOffset + 4) > fm.buffer.Size()) {
+
2304 return nil, errors.New("model is broken")
+
2305 }
+
2306
+
2307 fbeSetSize := int(fbe.ReadUInt32(fm.buffer.Data(), fm.buffer.Offset() + fbeSetOffset))
+
2308 if index >= fbeSetSize {
+
2309 return nil, errors.New("index is out of bounds")
+
2310 }
+
2311
+
2312 fm.model.SetFBEOffset(fbeSetOffset + 4)
+
2313 fm.model.FBEShift(index * fm.model.FBESize())
+
2314 return fm.model, nil
+
2315}
+
2316
+
2317// Resize the set and get its first model
+
2318func (fm *FieldModelSet_NAME_) Resize(size int) (*_MODEL_, error) {
+
2319 fbeSetSize := size * fm.model.FBESize()
+
2320 fbeSetOffset := fm.buffer.Allocate(4 + fbeSetSize) - fm.buffer.Offset()
+
2321 if (fbeSetOffset == 0) || ((fm.buffer.Offset() + fbeSetOffset + 4) > fm.buffer.Size()) {
+
2322 return nil, errors.New("model is broken")
+
2323 }
+
2324
+
2325 fbe.WriteUInt32(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset(), uint32(fbeSetOffset))
+
2326 fbe.WriteUInt32(fm.buffer.Data(), fm.buffer.Offset() + fbeSetOffset, uint32(size))
+
2327 fbe.WriteCount(fm.buffer.Data(), fm.buffer.Offset() + fbeSetOffset + 4, 0, fbeSetSize)
+
2328
+
2329 fm.model.SetFBEOffset(fbeSetOffset + 4)
+
2330 return fm.model, nil
+
2331}
+
2332
+
2333// Check if the set value is valid
+
2334func (fm *FieldModelSet_NAME_) Verify() bool {
+
2335 if (fm.buffer.Offset() + fm.FBEOffset() + fm.FBESize()) > fm.buffer.Size() {
+
2336 return true
+
2337 }
+
2338
+
2339 fbeSetOffset := int(fbe.ReadUInt32(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset()))
+
2340 if fbeSetOffset == 0 {
+
2341 return true
+
2342 }
+
2343
+
2344 if (fm.buffer.Offset() + fbeSetOffset + 4) > fm.buffer.Size() {
+
2345 return false
+
2346 }
+
2347
+
2348 fbeSetSize := int(fbe.ReadUInt32(fm.buffer.Data(), fm.buffer.Offset() + fbeSetOffset))
+
2349
+
2350 fm.model.SetFBEOffset(fbeSetOffset + 4)
+
2351 for i := fbeSetSize; i > 0; i-- {
+
2352 if !fm.model.Verify() {
+
2353 return false
+
2354 }
+
2355 fm.model.FBEShift(fm.model.FBESize())
+
2356 }
+
2357
+
2358 return true
+
2359}
+
2360
+
2361// Get the set value
+
2362func (fm *FieldModelSet_NAME_) Get() (_TYPE_, error) {
+
2363 values := make(_TYPE_)
+
2364
+
2365 fbeSetSize := fm.Size()
+
2366 if fbeSetSize == 0 {
+
2367 return values, nil
+
2368 }
+
2369
+
2370 fbeModel, err := fm.GetItem(0)
+
2371 if err != nil {
+
2372 return values, err
+
2373 }
+
2374
+
2375 for i := fbeSetSize; i > 0; i-- {
+
2376 value, err := fbeModel.Get()
+
2377 if err != nil {
+
2378 return values, err
+
2379 }
+
2380 values[_GET_KEY_] = _GET_VALUE_
+
2381 fbeModel.FBEShift(fbeModel.FBESize())
+
2382 }
+
2383
+
2384 return values, nil
+
2385}
+
2386
+
2387// Set the set value
+
2388func (fm *FieldModelSet_NAME_) Set(values _TYPE_) error {
+
2389 if (fm.buffer.Offset() + fm.FBEOffset() + fm.FBESize()) > fm.buffer.Size() {
+
2390 return errors.New("model is broken")
+
2391 }
+
2392
+
2393 fbeModel, err := fm.Resize(len(values))
+
2394 if err != nil {
+
2395 return err
+
2396 }
+
2397
+
2398 for _, value := range values {
+
2399 err := fbeModel.Set(_SET_VALUE_)
+
2400 if err != nil {
+
2401 return err
+
2402 }
+
2403 fbeModel.FBEShift(fbeModel.FBESize())
+
2404 }
+
2405
+
2406 return nil
+
2407}
+
2408)CODE";
+
2409
+
2410 // Prepare code template
+
2411 code = std::regex_replace(code, std::regex("_NAME_"), name);
+
2412 code = std::regex_replace(code, std::regex("_TYPE_"), "map[" + ConvertKeyName(*field.key) + "]" + ConvertTypeName(*field.type, field.optional));
+
2413 code = std::regex_replace(code, std::regex("_MODEL_NEW_"), ConvertNewName(model));
+
2414 code = std::regex_replace(code, std::regex("_MODEL_"), model);
+
2415 code = std::regex_replace(code, std::regex("_GET_KEY_"), IsGoType(*field.type) ? "value" : "value.Key()");
+
2416 code = std::regex_replace(code, std::regex("_GET_VALUE_"), (IsGoType(*field.type) || field.optional) ? "value" : "*value");
+
2417 code = std::regex_replace(code, std::regex("_SET_VALUE_"), (IsGoType(*field.type) || field.optional) ? "value" : "&value");
+
2418 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2419
+
2420 Write(code);
+
2421
+
2422 // Generate footer
+
2423 GenerateFooter();
+
2424
+
2425 // Store the output file
+
2426 WriteEnd();
+
2427 Store(output);
+
2428}
+
2429
+
2430void GeneratorGo::GenerateFBEFieldModelMap(const std::shared_ptr<Package>& p, const std::string& key_name, const std::string& key_model, const std::string& value_name, const std::string& value_model, const StructField& field, const CppCommon::Path& path)
+
2431{
+
2432 // Generate the output file
+
2433 CppCommon::Path output = path / ("FieldModelMap" + key_name + value_name + ".go");
+
2434 WriteBegin();
+
2435
+
2436 // Generate headers
+
2437 GenerateHeader("FBE");
+
2438
+
2439 // Generate package
+
2440 WriteLine();
+
2441 WriteLineIndent("package " + *p->name);
+
2442
+
2443 // Generate imports
+
2444 WriteLine();
+
2445 GenerateImports(p);
+
2446
+
2447 std::string code = R"CODE(
+
2448// Fast Binary Encoding _KEY_NAME_->_VALUE_NAME_ map field model
+
2449type FieldModelMap_KEY_NAME__VALUE_NAME_ struct {
+
2450 // Field model buffer
+
2451 buffer *fbe.Buffer
+
2452 // Field model buffer offset
+
2453 offset int
+
2454
+
2455 // Map key field model
+
2456 modelKey *_MODEL_KEY_
+
2457 // Map value field model
+
2458 modelValue *_MODEL_VALUE_
+
2459}
+
2460
+
2461// Create a new _KEY_NAME_->_VALUE_NAME_ map field model
+
2462func NewFieldModelMap_KEY_NAME__VALUE_NAME_(buffer *fbe.Buffer, offset int) *FieldModelMap_KEY_NAME__VALUE_NAME_ {
+
2463 fbeResult := FieldModelMap_KEY_NAME__VALUE_NAME_{buffer: buffer, offset: offset}
+
2464 fbeResult.modelKey = _MODEL_KEY_NEW_(buffer, offset)
+
2465 fbeResult.modelValue = _MODEL_VALUE_NEW_(buffer, offset)
+
2466 return &fbeResult
+
2467}
+
2468
+
2469// Get the field size
+
2470func (fm *FieldModelMap_KEY_NAME__VALUE_NAME_) FBESize() int { return 4 }
+
2471
+
2472// Get the field extra size
+
2473func (fm *FieldModelMap_KEY_NAME__VALUE_NAME_) FBEExtra() int {
+
2474 if (fm.buffer.Offset() + fm.FBEOffset() + fm.FBESize()) > fm.buffer.Size() {
+
2475 return 0
+
2476 }
+
2477
+
2478 fbeMapOffset := int(fbe.ReadUInt32(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset()))
+
2479 if (fbeMapOffset == 0) || ((fm.buffer.Offset() + fbeMapOffset + 4) > fm.buffer.Size()) {
+
2480 return 0
+
2481 }
+
2482
+
2483 fbeMapSize := int(fbe.ReadUInt32(fm.buffer.Data(), fm.buffer.Offset() + fbeMapOffset))
+
2484
+
2485 fbeResult := 0
+
2486 fm.modelKey.SetFBEOffset(fbeMapOffset + 4)
+
2487 fm.modelValue.SetFBEOffset(fbeMapOffset + 4 + fm.modelKey.FBESize())
+
2488 for i := fbeMapSize; i > 0; i-- {
+
2489 fbeResult += fm.modelKey.FBESize() + fm.modelKey.FBEExtra()
+
2490 fm.modelKey.FBEShift(fm.modelKey.FBESize() + fm.modelValue.FBESize())
+
2491
+
2492 fbeResult += fm.modelValue.FBESize() + fm.modelValue.FBEExtra()
+
2493 fm.modelValue.FBEShift(fm.modelKey.FBESize() + fm.modelValue.FBESize())
+
2494 }
+
2495 return fbeResult
+
2496}
+
2497
+
2498// Get the field offset
+
2499func (fm *FieldModelMap_KEY_NAME__VALUE_NAME_) FBEOffset() int { return fm.offset }
+
2500// Set the field offset
+
2501func (fm *FieldModelMap_KEY_NAME__VALUE_NAME_) SetFBEOffset(value int) { fm.offset = value }
+
2502
+
2503// Shift the current field offset
+
2504func (fm *FieldModelMap_KEY_NAME__VALUE_NAME_) FBEShift(size int) { fm.offset += size }
+
2505// Unshift the current field offset
+
2506func (fm *FieldModelMap_KEY_NAME__VALUE_NAME_) FBEUnshift(size int) { fm.offset -= size }
+
2507
+
2508// Get the map offset
+
2509func (fm *FieldModelMap_KEY_NAME__VALUE_NAME_) Offset() int {
+
2510 if (fm.buffer.Offset() + fm.FBEOffset() + fm.FBESize()) > fm.buffer.Size() {
+
2511 return 0
+
2512 }
+
2513
+
2514 fbeMapOffset := int(fbe.ReadUInt32(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset()))
+
2515 return fbeMapOffset
+
2516}
+
2517
+
2518// Get the map size
+
2519func (fm *FieldModelMap_KEY_NAME__VALUE_NAME_) Size() int {
+
2520 if (fm.buffer.Offset() + fm.FBEOffset() + fm.FBESize()) > fm.buffer.Size() {
+
2521 return 0
+
2522 }
+
2523
+
2524 fbeMapOffset := int(fbe.ReadUInt32(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset()))
+
2525 if (fbeMapOffset == 0) || ((fm.buffer.Offset() + fbeMapOffset + 4) > fm.buffer.Size()) {
+
2526 return 0
+
2527 }
+
2528
+
2529 fbeMapSize := int(fbe.ReadUInt32(fm.buffer.Data(), fm.buffer.Offset() + fbeMapOffset))
+
2530 return fbeMapSize
+
2531}
+
2532
+
2533// Map index operator
+
2534func (fm *FieldModelMap_KEY_NAME__VALUE_NAME_) GetItem(index int) (*_MODEL_KEY_, *_MODEL_VALUE_, error) {
+
2535 if (fm.buffer.Offset() + fm.FBEOffset() + fm.FBESize()) > fm.buffer.Size() {
+
2536 return nil, nil, errors.New("model is broken")
+
2537 }
+
2538
+
2539 fbeMapOffset := int(fbe.ReadUInt32(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset()))
+
2540 if (fbeMapOffset == 0) || ((fm.buffer.Offset() + fbeMapOffset + 4) > fm.buffer.Size()) {
+
2541 return nil, nil, errors.New("model is broken")
+
2542 }
+
2543
+
2544 fbeMapSize := int(fbe.ReadUInt32(fm.buffer.Data(), fm.buffer.Offset() + fbeMapOffset))
+
2545 if index >= fbeMapSize {
+
2546 return nil, nil, errors.New("index is out of bounds")
+
2547 }
+
2548
+
2549 fm.modelKey.SetFBEOffset(fbeMapOffset + 4)
+
2550 fm.modelValue.SetFBEOffset(fbeMapOffset + 4 + fm.modelKey.FBESize())
+
2551 fm.modelKey.FBEShift(index * (fm.modelKey.FBESize() + fm.modelValue.FBESize()))
+
2552 fm.modelValue.FBEShift(index * (fm.modelKey.FBESize() + fm.modelValue.FBESize()))
+
2553 return fm.modelKey, fm.modelValue, nil
+
2554}
+
2555
+
2556// Resize the map and get its first model
+
2557func (fm *FieldModelMap_KEY_NAME__VALUE_NAME_) Resize(size int) (*_MODEL_KEY_, *_MODEL_VALUE_, error) {
+
2558 fbeMapSize := size * (fm.modelKey.FBESize() + fm.modelValue.FBESize())
+
2559 fbeMapOffset := fm.buffer.Allocate(4 + fbeMapSize) - fm.buffer.Offset()
+
2560 if (fbeMapOffset == 0) || ((fm.buffer.Offset() + fbeMapOffset + 4) > fm.buffer.Size()) {
+
2561 return nil, nil, errors.New("model is broken")
+
2562 }
+
2563
+
2564 fbe.WriteUInt32(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset(), uint32(fbeMapOffset))
+
2565 fbe.WriteUInt32(fm.buffer.Data(), fm.buffer.Offset() + fbeMapOffset, uint32(size))
+
2566 fbe.WriteCount(fm.buffer.Data(), fm.buffer.Offset() + fbeMapOffset + 4, 0, fbeMapSize)
+
2567
+
2568 fm.modelKey.SetFBEOffset(fbeMapOffset + 4)
+
2569 fm.modelValue.SetFBEOffset(fbeMapOffset + 4 + fm.modelKey.FBESize())
+
2570 return fm.modelKey, fm.modelValue, nil
+
2571}
+
2572
+
2573// Check if the map is valid
+
2574func (fm *FieldModelMap_KEY_NAME__VALUE_NAME_) Verify() bool {
+
2575 if (fm.buffer.Offset() + fm.FBEOffset() + fm.FBESize()) > fm.buffer.Size() {
+
2576 return true
+
2577 }
+
2578
+
2579 fbeMapOffset := int(fbe.ReadUInt32(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset()))
+
2580 if fbeMapOffset == 0 {
+
2581 return true
+
2582 }
+
2583
+
2584 if (fm.buffer.Offset() + fbeMapOffset + 4) > fm.buffer.Size() {
+
2585 return false
+
2586 }
+
2587
+
2588 fbeMapSize := int(fbe.ReadUInt32(fm.buffer.Data(), fm.buffer.Offset() + fbeMapOffset))
+
2589
+
2590 fm.modelKey.SetFBEOffset(fbeMapOffset + 4)
+
2591 fm.modelValue.SetFBEOffset(fbeMapOffset + 4 + fm.modelKey.FBESize())
+
2592 for i := fbeMapSize; i > 0; i-- {
+
2593 if !fm.modelKey.Verify() {
+
2594 return false
+
2595 }
+
2596 fm.modelKey.FBEShift(fm.modelKey.FBESize() + fm.modelValue.FBESize())
+
2597 if !fm.modelValue.Verify() {
+
2598 return false
+
2599 }
+
2600 fm.modelValue.FBEShift(fm.modelKey.FBESize() + fm.modelValue.FBESize())
+
2601 }
+
2602
+
2603 return true
+
2604}
+
2605
+
2606// Get the map
+
2607func (fm *FieldModelMap_KEY_NAME__VALUE_NAME_) Get() (_TYPE_, error) {
+
2608 values := make(_TYPE_)
+
2609
+
2610 fbeMapSize := fm.Size()
+
2611 if fbeMapSize == 0 {
+
2612 return values, nil
+
2613 }
+
2614
+
2615 fbeModelKey, fbeModelValue, err := fm.GetItem(0)
+
2616 if err != nil {
+
2617 return values, err
+
2618 }
+
2619
+
2620 for i := fbeMapSize; i > 0; i-- {
+
2621 key, err := fbeModelKey.Get()
+
2622 if err != nil {
+
2623 return values, err
+
2624 }
+
2625 value, err := fbeModelValue.Get()
+
2626 if err != nil {
+
2627 return values, err
+
2628 }
+
2629 values[_GET_KEY_] = _GET_VALUE_
+
2630 fbeModelKey.FBEShift(fbeModelKey.FBESize() + fbeModelValue.FBESize())
+
2631 fbeModelValue.FBEShift(fbeModelKey.FBESize() + fbeModelValue.FBESize())
+
2632 }
+
2633
+
2634 return values, nil
+
2635}
+
2636
+
2637// Set the map
+
2638func (fm *FieldModelMap_KEY_NAME__VALUE_NAME_) Set(values _TYPE_) error {
+
2639 if (fm.buffer.Offset() + fm.FBEOffset() + fm.FBESize()) > fm.buffer.Size() {
+
2640 return errors.New("model is broken")
+
2641 }
+
2642
+
2643 fbeModelKey, fbeModelValue, err := fm.Resize(len(values))
+
2644 if err != nil {
+
2645 return err
+
2646 }
+
2647
+
2648 for _KEY_, value := range values {
+
2649 err := fbeModelKey.Set(_SET_KEY_)
+
2650 if err != nil {
+
2651 return err
+
2652 }
+
2653 fbeModelKey.FBEShift(fbeModelKey.FBESize() + fbeModelValue.FBESize())
+
2654 err = fbeModelValue.Set(_SET_VALUE_)
+
2655 if err != nil {
+
2656 return err
+
2657 }
+
2658 fbeModelValue.FBEShift(fbeModelKey.FBESize() + fbeModelValue.FBESize())
+
2659 }
+
2660
+
2661 return nil
+
2662}
+
2663)CODE";
+
2664
+
2665 // Prepare code template
+
2666 code = std::regex_replace(code, std::regex("_KEY_NAME_"), key_name);
+
2667 code = std::regex_replace(code, std::regex("_VALUE_NAME_"), value_name);
+
2668 code = std::regex_replace(code, std::regex("_TYPE_"), ConvertTypeName(field));
+
2669 code = std::regex_replace(code, std::regex("_MODEL_KEY_NEW_"), ConvertNewName(key_model));
+
2670 code = std::regex_replace(code, std::regex("_MODEL_VALUE_NEW_"), ConvertNewName(value_model));
+
2671 code = std::regex_replace(code, std::regex("_MODEL_KEY_"), key_model);
+
2672 code = std::regex_replace(code, std::regex("_MODEL_VALUE_"), value_model);
+
2673 code = std::regex_replace(code, std::regex("_GET_KEY_"), IsGoType(*field.key) ? "key" : "key.Key()");
+
2674 code = std::regex_replace(code, std::regex("_GET_VALUE_"), IsGoType(*field.key) ? ((IsGoType(*field.type) || field.optional) ? "value" : "*value") : ("struct{Key " + ConvertTypeName(*field.key, false) + "; Value " + ConvertTypeName(*field.type, field.optional) + "}{*key, " + ((IsGoType(*field.type) || field.optional) ? "value" : "*value") + "}"));
+
2675 code = std::regex_replace(code, std::regex("_SET_KEY_"), IsGoType(*field.key) ? "key" : "&value.Key");
+
2676 code = std::regex_replace(code, std::regex("_SET_VALUE_"), IsGoType(*field.key) ? ((IsGoType(*field.type) || field.optional) ? "value" : "&value") : ((IsGoType(*field.type) || field.optional) ? "value.Value" : "&value.Value"));
+
2677 code = std::regex_replace(code, std::regex("_KEY_"), IsGoType(*field.key) ? "key" : "_");
+
2678 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2679
+
2680 Write(code);
+
2681
+
2682 // Generate footer
+
2683 GenerateFooter();
+
2684
+
2685 // Store the output file
+
2686 WriteEnd();
+
2687 Store(output);
+
2688}
+
2689
+
2690void GeneratorGo::GenerateFBEFieldModelEnumFlags(const std::string& package, const std::string& name, const std::string& type)
+
2691{
+
2692 CppCommon::Path path = CppCommon::Path(_output) / package;
+
2693
+
2694 // Generate the file
+
2695 CppCommon::Path file = path / ("FieldModel" + name + ".go");
+
2696 WriteBegin();
+
2697
+
2698 // Generate header
+
2699 GenerateHeader(CppCommon::Path(_input).filename().string());
+
2700
+
2701 // Generate package
+
2702 WriteLine();
+
2703 WriteLineIndent("package " + package);
+
2704
+
2705 // Generate imports
+
2706 WriteLine();
+
2707 WriteLineIndent("import \"errors\"");
+
2708 WriteLineIndent("import \"../fbe\"");
+
2709
+
2710 std::string code = R"CODE(
+
2711// Fast Binary Encoding _NAME_ field model
+
2712type FieldModel_NAME_ struct {
+
2713 // Field model buffer
+
2714 buffer *fbe.Buffer
+
2715 // Field model buffer offset
+
2716 offset int
+
2717}
+
2718
+
2719// Create a new _NAME_ field model
+
2720func NewFieldModel_NAME_(buffer *fbe.Buffer, offset int) *FieldModel_NAME_ {
+
2721 return &FieldModel_NAME_{buffer: buffer, offset: offset}
+
2722}
+
2723
+
2724// Get the field size
+
2725func (fm *FieldModel_NAME_) FBESize() int { return _SIZE_ }
+
2726// Get the field extra size
+
2727func (fm *FieldModel_NAME_) FBEExtra() int { return 0 }
+
2728
+
2729// Get the field offset
+
2730func (fm *FieldModel_NAME_) FBEOffset() int { return fm.offset }
+
2731// Set the field offset
+
2732func (fm *FieldModel_NAME_) SetFBEOffset(value int) { fm.offset = value }
+
2733
+
2734// Shift the current field offset
+
2735func (fm *FieldModel_NAME_) FBEShift(size int) { fm.offset += size }
+
2736// Unshift the current field offset
+
2737func (fm *FieldModel_NAME_) FBEUnshift(size int) { fm.offset -= size }
+
2738
+
2739// Check if the value is valid
+
2740func (fm *FieldModel_NAME_) Verify() bool { return true }
+
2741
+
2742// Get the value
+
2743func (fm *FieldModel_NAME_) Get() (*_NAME_, error) {
+
2744 var value _NAME_
+
2745 return &value, fm.GetValueDefault(&value, _NAME_(0))
+
2746}
+
2747
+
2748// Get the value with provided default value
+
2749func (fm *FieldModel_NAME_) GetDefault(defaults _NAME_) (*_NAME_, error) {
+
2750 var value _NAME_
+
2751 err := fm.GetValueDefault(&value, defaults)
+
2752 return &value, err
+
2753}
+
2754
+
2755// Get the value by the given pointer
+
2756func (fm *FieldModel_NAME_) GetValue(value *_NAME_) error {
+
2757 return fm.GetValueDefault(value, _NAME_(0))
+
2758}
+
2759
+
2760// Get the value by the given pointer with provided default value
+
2761func (fm *FieldModel_NAME_) GetValueDefault(value *_NAME_, defaults _NAME_) error {
+
2762 if (fm.buffer.Offset() + fm.FBEOffset() + fm.FBESize()) > fm.buffer.Size() {
+
2763 *value = defaults
+
2764 return nil
+
2765 }
+
2766
+
2767 *value = _NAME_(fbe.Read_BASE_(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset()))
+
2768 return nil
+
2769}
+
2770
+
2771// Set the value by the given pointer
+
2772func (fm *FieldModel_NAME_) Set(value *_NAME_) error {
+
2773 return fm.SetValue(*value)
+
2774}
+
2775
+
2776// Set the value
+
2777func (fm *FieldModel_NAME_) SetValue(value _NAME_) error {
+
2778 if (fm.buffer.Offset() + fm.FBEOffset() + fm.FBESize()) > fm.buffer.Size() {
+
2779 return errors.New("model is broken")
+
2780 }
+
2781
+
2782 fbe.Write_BASE_(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset(), _TYPE_(value))
+
2783 return nil
+
2784}
+
2785)CODE";
+
2786
+
2787 // Prepare code template
+
2788 code = std::regex_replace(code, std::regex("_NAME_"), name);
+
2789 code = std::regex_replace(code, std::regex("_TYPE_"), ConvertEnumType(type));
+
2790 code = std::regex_replace(code, std::regex("_BASE_"), ConvertEnumBase(type));
+
2791 code = std::regex_replace(code, std::regex("_SIZE_"), ConvertEnumSize(type));
+
2792 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2793
+
2794 Write(code);
+
2795
+
2796 // Generate footer
+
2797 GenerateFooter();
+
2798
+
2799 // Store the file
+
2800 WriteEnd();
+
2801 Store(file);
+
2802}
+
2803
+
2804void GeneratorGo::GenerateFBEFinalModel(const std::string& package, const std::string& name, const std::string& type, const std::string& size, const std::string& defaults)
+
2805{
+
2806 CppCommon::Path path = CppCommon::Path(_output) / package;
+
2807
+
2808 // Generate the file
+
2809 CppCommon::Path file = path / ("FinalModel" + name + ".go");
+
2810 WriteBegin();
+
2811
+
2812 // Generate headers
+
2813 GenerateHeader("FBE");
+
2814
+
2815 std::string code = R"CODE(
+
2816package fbe
+
2817
+
2818import "errors"
+
2819
+
2820// Fast Binary Encoding _NAME_ final model
+
2821type FinalModel_NAME_ struct {
+
2822 // Final model buffer
+
2823 buffer *Buffer
+
2824 // Final model buffer offset
+
2825 offset int
+
2826}
+
2827
+
2828// Create a new _NAME_ final model
+
2829func NewFinalModel_NAME_(buffer *Buffer, offset int) *FinalModel_NAME_ {
+
2830 return &FinalModel_NAME_{buffer: buffer, offset: offset}
+
2831}
+
2832
+
2833// Get the allocation size
+
2834func (fm *FinalModel_NAME_) FBEAllocationSize(value _TYPE_) int { return fm.FBESize() }
+
2835
+
2836// Get the final size
+
2837func (fm *FinalModel_NAME_) FBESize() int { return _SIZE_ }
+
2838
+
2839// Get the final offset
+
2840func (fm *FinalModel_NAME_) FBEOffset() int { return fm.offset }
+
2841// Set the final offset
+
2842func (fm *FinalModel_NAME_) SetFBEOffset(value int) { fm.offset = value }
+
2843
+
2844// Shift the current final offset
+
2845func (fm *FinalModel_NAME_) FBEShift(size int) { fm.offset += size }
+
2846// Unshift the current final offset
+
2847func (fm *FinalModel_NAME_) FBEUnshift(size int) { fm.offset -= size }
+
2848
+
2849// Check if the value is valid
+
2850func (fm *FinalModel_NAME_) Verify() int {
+
2851 if (fm.buffer.Offset() + fm.FBEOffset() + fm.FBESize()) > fm.buffer.Size() {
+
2852 return MaxInt
+
2853 }
+
2854
+
2855 return fm.FBESize()
+
2856}
+
2857
+
2858// Get the value
+
2859func (fm *FinalModel_NAME_) Get() (_TYPE_, int, error) {
+
2860 if (fm.buffer.Offset() + fm.FBEOffset() + fm.FBESize()) > fm.buffer.Size() {
+
2861 return _DEFAULTS_, 0, errors.New("model is broken")
+
2862 }
+
2863
+
2864 return Read_NAME_(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset()), fm.FBESize(), nil
+
2865}
+
2866
+
2867// Set the value
+
2868func (fm *FinalModel_NAME_) Set(value _TYPE_) (int, error) {
+
2869 if (fm.buffer.Offset() + fm.FBEOffset() + fm.FBESize()) > fm.buffer.Size() {
+
2870 return 0, errors.New("model is broken")
+
2871 }
+
2872
+
2873 Write_NAME_(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset(), value)
+
2874 return fm.FBESize(), nil
+
2875}
+
2876)CODE";
+
2877
+
2878 // Prepare code template
+
2879 code = std::regex_replace(code, std::regex("_NAME_"), name);
+
2880 code = std::regex_replace(code, std::regex("_TYPE_"), type);
+
2881 code = std::regex_replace(code, std::regex("_SIZE_"), size);
+
2882 code = std::regex_replace(code, std::regex("_DEFAULTS_"), defaults);
+
2883 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2884
+
2885 Write(code);
+
2886
+
2887 // Generate footer
+
2888 GenerateFooter();
+
2889
+
2890 // Store the file
+
2891 WriteEnd();
+
2892 Store(file);
+
2893}
+
2894
+
2895void GeneratorGo::GenerateFBEFinalModelDecimal(const std::string& package)
+
2896{
+
2897 CppCommon::Path path = CppCommon::Path(_output) / package;
+
2898
+
2899 // Generate the file
+
2900 CppCommon::Path file = path / ("FinalModelDecimal.go");
+
2901 WriteBegin();
+
2902
+
2903 // Generate headers
+
2904 GenerateHeader("FBE");
+
2905
+
2906 std::string code = R"CODE(
+
2907package fbe
+
2908
+
2909import "errors"
+
2910import "math/big"
+
2911import "github.com/shopspring/decimal"
+
2912
+
2913// Fast Binary Encoding decimal final model
+
2914type FinalModelDecimal struct {
+
2915 // Final model buffer
+
2916 buffer *Buffer
+
2917 // Final model buffer offset
+
2918 offset int
+
2919}
+
2920
+
2921// Create a new decimal final model
+
2922func NewFinalModelDecimal(buffer *Buffer, offset int) *FinalModelDecimal {
+
2923 return &FinalModelDecimal{buffer: buffer, offset: offset}
+
2924}
+
2925
+
2926// Get the allocation size
+
2927func (fm *FinalModelDecimal) FBEAllocationSize(value Decimal) int { return fm.FBESize() }
+
2928
+
2929// Get the final size
+
2930func (fm *FinalModelDecimal) FBESize() int { return 16 }
+
2931
+
2932// Get the final offset
+
2933func (fm *FinalModelDecimal) FBEOffset() int { return fm.offset }
+
2934// Set the final offset
+
2935func (fm *FinalModelDecimal) SetFBEOffset(value int) { fm.offset = value }
+
2936
+
2937// Shift the current final offset
+
2938func (fm *FinalModelDecimal) FBEShift(size int) { fm.offset += size }
+
2939// Unshift the current final offset
+
2940func (fm *FinalModelDecimal) FBEUnshift(size int) { fm.offset -= size }
+
2941
+
2942// Check if the decimal value is valid
+
2943func (fm *FinalModelDecimal) Verify() int {
+
2944 if (fm.buffer.Offset() + fm.FBEOffset() + fm.FBESize()) > fm.buffer.Size() {
+
2945 return MaxInt
+
2946 }
+
2947
+
2948 return fm.FBESize()
+
2949}
+
2950
+
2951// Get the decimal value
+
2952func (fm *FinalModelDecimal) Get() (Decimal, int, error) {
+
2953 if (fm.buffer.Offset() + fm.FBEOffset() + fm.FBESize()) > fm.buffer.Size() {
+
2954 return DecimalZero(), 0, errors.New("model is broken")
+
2955 }
+
2956
+
2957 // Read decimal parts
+
2958 low := ReadUInt32(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset())
+
2959 mid := ReadUInt32(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset() + 4)
+
2960 high := ReadUInt32(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset() + 8)
+
2961 flags := ReadUInt32(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset() + 12)
+
2962
+
2963 // Calculate decimal value
+
2964 negative := (flags & 0x80000000) != 0
+
2965 scale := (flags & 0x7FFFFFFF) >> 16
+
2966 result := decimal.New(int64(high), 0).Mul(lowScaleFinal)
+
2967 result = result.Add(decimal.New(int64(mid), 0).Mul(midScaleFinal))
+
2968 result = result.Add(decimal.New(int64(low), 0))
+
2969 result = result.Shift(-int32(scale))
+
2970 if negative {
+
2971 result = result.Neg()
+
2972 }
+
2973
+
2974 return Decimal{result}, fm.FBESize(), nil
+
2975}
+
2976
+
2977// Set the decimal value
+
2978func (fm *FinalModelDecimal) Set(value Decimal) (int, error) {
+
2979 if (fm.buffer.Offset() + fm.FBEOffset() + fm.FBESize()) > fm.buffer.Size() {
+
2980 return 0, errors.New("model is broken")
+
2981 }
+
2982
+
2983 // Extract decimal parts
+
2984 negative := value.IsNegative()
+
2985 number := value.Coefficient()
+
2986 scale := -value.Exponent()
+
2987
+
2988 // Check for decimal number overflow
+
2989 bits := number.BitLen()
+
2990 if (bits < 0) || (bits > 96) {
+
2991 // Value too big for .NET Decimal (bit length is limited to [0, 96])
+
2992 WriteCount(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset(), 0, fm.FBESize())
+
2993 return fm.FBESize(), errors.New("value too big for .NET Decimal (bit length is limited to [0, 96])")
+
2994 }
+
2995
+
2996 // Check for decimal scale overflow
+
2997 if (scale < 0) || (scale > 28) {
+
2998 // Value scale exceeds .NET Decimal limit of [0, 28]
+
2999 WriteCount(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset(), 0, fm.FBESize())
+
3000 return fm.FBESize(), errors.New("value scale exceeds .NET Decimal limit of [0, 28]")
+
3001 }
+
3002
+
3003 // Write unscaled value to bytes 0-11
+
3004 bytes := number.Bytes()
+
3005 for i := range bytes {
+
3006 WriteByte(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset() + i, bytes[len(bytes) - i - 1])
+
3007 }
+
3008 WriteCount(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset() + len(bytes), 0, 12 - len(bytes))
+
3009
+
3010 // Write scale at byte 14
+
3011 WriteByte(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset() + 14, byte(scale))
+
3012
+
3013 // Write signum at byte 15
+
3014 if negative {
+
3015 WriteByte(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset() + 15, 0x80)
+
3016 } else {
+
3017 WriteByte(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset() + 15, 0)
+
3018 }
+
3019 return fm.FBESize(), nil
+
3020}
+
3021
+
3022var lowScaleFinal, midScaleFinal decimal.Decimal
+
3023
+
3024func init() {
+
3025 var low, mid big.Int
+
3026 low.SetString("18446744073709551616", 10)
+
3027 mid.SetString("4294967296", 10)
+
3028 lowScaleFinal = decimal.NewFromBigInt(&low, 0)
+
3029 midScaleFinal = decimal.NewFromBigInt(&mid, 0)
+
3030}
+
3031)CODE";
+
3032
+
3033 // Prepare code template
+
3034 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
3035
+
3036 Write(code);
+
3037
+
3038 // Generate footer
+
3039 GenerateFooter();
+
3040
+
3041 // Store the file
+
3042 WriteEnd();
+
3043 Store(file);
+
3044}
+
3045
+
3046void GeneratorGo::GenerateFBEFinalModelTimestamp(const std::string& package)
+
3047{
+
3048 CppCommon::Path path = CppCommon::Path(_output) / package;
+
3049
+
3050 // Generate the file
+
3051 CppCommon::Path file = path / ("FinalModelTimestamp.go");
+
3052 WriteBegin();
+
3053
+
3054 // Generate headers
+
3055 GenerateHeader("FBE");
+
3056
+
3057 std::string code = R"CODE(
+
3058package fbe
+
3059
+
3060import "errors"
+
3061
+
3062// Fast Binary Encoding timestamp final model
+
3063type FinalModelTimestamp struct {
+
3064 // Final model buffer
+
3065 buffer *Buffer
+
3066 // Final model buffer offset
+
3067 offset int
+
3068}
+
3069
+
3070// Create a new timestamp final model
+
3071func NewFinalModelTimestamp(buffer *Buffer, offset int) *FinalModelTimestamp {
+
3072 return &FinalModelTimestamp{buffer: buffer, offset: offset}
+
3073}
+
3074
+
3075// Get the allocation size
+
3076func (fm *FinalModelTimestamp) FBEAllocationSize(value Timestamp) int { return fm.FBESize() }
+
3077
+
3078// Get the final size
+
3079func (fm *FinalModelTimestamp) FBESize() int { return 8 }
+
3080
+
3081// Get the final offset
+
3082func (fm *FinalModelTimestamp) FBEOffset() int { return fm.offset }
+
3083// Set the final offset
+
3084func (fm *FinalModelTimestamp) SetFBEOffset(value int) { fm.offset = value }
+
3085
+
3086// Shift the current final offset
+
3087func (fm *FinalModelTimestamp) FBEShift(size int) { fm.offset += size }
+
3088// Unshift the current final offset
+
3089func (fm *FinalModelTimestamp) FBEUnshift(size int) { fm.offset -= size }
+
3090
+
3091// Check if the timestamp value is valid
+
3092func (fm *FinalModelTimestamp) Verify() int {
+
3093 if (fm.buffer.Offset() + fm.FBEOffset() + fm.FBESize()) > fm.buffer.Size() {
+
3094 return MaxInt
+
3095 }
+
3096
+
3097 return fm.FBESize()
+
3098}
+
3099
+
3100// Get the timestamp value
+
3101func (fm *FinalModelTimestamp) Get() (Timestamp, int, error) {
+
3102 if (fm.buffer.Offset() + fm.FBEOffset() + fm.FBESize()) > fm.buffer.Size() {
+
3103 return TimestampEpoch(), 0, errors.New("model is broken")
+
3104 }
+
3105
+
3106 return ReadTimestamp(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset()), fm.FBESize(), nil
+
3107}
+
3108
+
3109// Set the timestamp value
+
3110func (fm *FinalModelTimestamp) Set(value Timestamp) (int, error) {
+
3111 if (fm.buffer.Offset() + fm.FBEOffset() + fm.FBESize()) > fm.buffer.Size() {
+
3112 return 0, errors.New("model is broken")
+
3113 }
+
3114
+
3115 WriteTimestamp(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset(), value)
+
3116 return fm.FBESize(), nil
+
3117}
+
3118)CODE";
+
3119
+
3120 // Prepare code template
+
3121 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
3122
+
3123 Write(code);
+
3124
+
3125 // Generate footer
+
3126 GenerateFooter();
+
3127
+
3128 // Store the file
+
3129 WriteEnd();
+
3130 Store(file);
+
3131}
+
3132
+
3133void GeneratorGo::GenerateFBEFinalModelUUID(const std::string& package)
+
3134{
+
3135 CppCommon::Path path = CppCommon::Path(_output) / package;
+
3136
+
3137 // Generate the file
+
3138 CppCommon::Path file = path / ("FinalModelUUID.go");
+
3139 WriteBegin();
+
3140
+
3141 // Generate headers
+
3142 GenerateHeader("FBE");
+
3143
+
3144 std::string code = R"CODE(
+
3145package fbe
+
3146
+
3147import "errors"
+
3148
+
3149// Fast Binary Encoding UUID final model
+
3150type FinalModelUUID struct {
+
3151 // Final model buffer
+
3152 buffer *Buffer
+
3153 // Final model buffer offset
+
3154 offset int
+
3155}
+
3156
+
3157// Create a new UUID final model
+
3158func NewFinalModelUUID(buffer *Buffer, offset int) *FinalModelUUID {
+
3159 return &FinalModelUUID{buffer: buffer, offset: offset}
+
3160}
+
3161
+
3162// Get the allocation size
+
3163func (fm *FinalModelUUID) FBEAllocationSize(value UUID) int { return fm.FBESize() }
+
3164
+
3165// Get the final size
+
3166func (fm *FinalModelUUID) FBESize() int { return 16 }
+
3167
+
3168// Get the final offset
+
3169func (fm *FinalModelUUID) FBEOffset() int { return fm.offset }
+
3170// Set the final offset
+
3171func (fm *FinalModelUUID) SetFBEOffset(value int) { fm.offset = value }
+
3172
+
3173// Shift the current final offset
+
3174func (fm *FinalModelUUID) FBEShift(size int) { fm.offset += size }
+
3175// Unshift the current final offset
+
3176func (fm *FinalModelUUID) FBEUnshift(size int) { fm.offset -= size }
+
3177
+
3178// Check if the UUID value is valid
+
3179func (fm *FinalModelUUID) Verify() int {
+
3180 if (fm.buffer.Offset() + fm.FBEOffset() + fm.FBESize()) > fm.buffer.Size() {
+
3181 return MaxInt
+
3182 }
+
3183
+
3184 return fm.FBESize()
+
3185}
+
3186
+
3187// Get the UUID value
+
3188func (fm *FinalModelUUID) Get() (UUID, int, error) {
+
3189 if (fm.buffer.Offset() + fm.FBEOffset() + fm.FBESize()) > fm.buffer.Size() {
+
3190 return UUIDNil(), 0, errors.New("model is broken")
+
3191 }
+
3192
+
3193 return ReadUUID(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset()), fm.FBESize(), nil
+
3194}
+
3195
+
3196// Set the UUID value
+
3197func (fm *FinalModelUUID) Set(value UUID) (int, error) {
+
3198 if (fm.buffer.Offset() + fm.FBEOffset() + fm.FBESize()) > fm.buffer.Size() {
+
3199 return 0, errors.New("model is broken")
+
3200 }
+
3201
+
3202 WriteUUID(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset(), value)
+
3203 return fm.FBESize(), nil
+
3204}
+
3205)CODE";
+
3206
+
3207 // Prepare code template
+
3208 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
3209
+
3210 Write(code);
+
3211
+
3212 // Generate footer
+
3213 GenerateFooter();
+
3214
+
3215 // Store the file
+
3216 WriteEnd();
+
3217 Store(file);
+
3218}
+
3219
+
3220void GeneratorGo::GenerateFBEFinalModelBytes(const std::string& package)
+
3221{
+
3222 CppCommon::Path path = CppCommon::Path(_output) / package;
+
3223
+
3224 // Generate the file
+
3225 CppCommon::Path file = path / ("FinalModelBytes.go");
+
3226 WriteBegin();
+
3227
+
3228 // Generate headers
+
3229 GenerateHeader("FBE");
+
3230
+
3231 std::string code = R"CODE(
+
3232package fbe
+
3233
+
3234import "errors"
+
3235
+
3236// Fast Binary Encoding bytes final model
+
3237type FinalModelBytes struct {
+
3238 // Final model buffer
+
3239 buffer *Buffer
+
3240 // Final model buffer offset
+
3241 offset int
+
3242}
+
3243
+
3244// Create a new bytes final model
+
3245func NewFinalModelBytes(buffer *Buffer, offset int) *FinalModelBytes {
+
3246 return &FinalModelBytes{buffer: buffer, offset: offset}
+
3247}
+
3248
+
3249// Get the allocation size
+
3250func (fm *FinalModelBytes) FBEAllocationSize(value []byte) int { return 4 + len(value) }
+
3251
+
3252// Get the final offset
+
3253func (fm *FinalModelBytes) FBEOffset() int { return fm.offset }
+
3254// Set the final offset
+
3255func (fm *FinalModelBytes) SetFBEOffset(value int) { fm.offset = value }
+
3256
+
3257// Shift the current final offset
+
3258func (fm *FinalModelBytes) FBEShift(size int) { fm.offset += size }
+
3259// Unshift the current final offset
+
3260func (fm *FinalModelBytes) FBEUnshift(size int) { fm.offset -= size }
+
3261
+
3262// Check if the bytes value is valid
+
3263func (fm *FinalModelBytes) Verify() int {
+
3264 if (fm.buffer.Offset() + fm.FBEOffset() + 4) > fm.buffer.Size() {
+
3265 return MaxInt
+
3266 }
+
3267
+
3268 fbeBytesSize := int(ReadUInt32(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset()))
+
3269 if (fm.buffer.Offset() + fm.FBEOffset() + 4 + fbeBytesSize) > fm.buffer.Size() {
+
3270 return MaxInt
+
3271 }
+
3272
+
3273 return 4 + fbeBytesSize
+
3274}
+
3275
+
3276// Get the bytes value
+
3277func (fm *FinalModelBytes) Get() ([]byte, int, error) {
+
3278 if (fm.buffer.Offset() + fm.FBEOffset() + 4) > fm.buffer.Size() {
+
3279 return make([]byte, 0), 0, nil
+
3280 }
+
3281
+
3282 fbeBytesSize := int(ReadUInt32(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset()))
+
3283 if (fm.buffer.Offset() + fm.FBEOffset() + 4 + fbeBytesSize) > fm.buffer.Size() {
+
3284 return make([]byte, 0), 4, errors.New("model is broken")
+
3285 }
+
3286
+
3287 return ReadBytes(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset() + 4, fbeBytesSize), 4 + fbeBytesSize, nil
+
3288}
+
3289
+
3290// Set the bytes value
+
3291func (fm *FinalModelBytes) Set(value []byte) (int, error) {
+
3292 if (fm.buffer.Offset() + fm.FBEOffset() + 4) > fm.buffer.Size() {
+
3293 return 0, errors.New("model is broken")
+
3294 }
+
3295
+
3296 fbeBytesSize := len(value)
+
3297 if (fm.buffer.Offset() + fm.FBEOffset() + 4 + fbeBytesSize) > fm.buffer.Size() {
+
3298 return 4, errors.New("model is broken")
+
3299 }
+
3300
+
3301 WriteUInt32(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset(), uint32(fbeBytesSize))
+
3302 WriteBytes(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset() + 4, value)
+
3303 return 4 + fbeBytesSize, nil
+
3304}
+
3305)CODE";
+
3306
+
3307 // Prepare code template
+
3308 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
3309
+
3310 Write(code);
+
3311
+
3312 // Generate footer
+
3313 GenerateFooter();
+
3314
+
3315 // Store the file
+
3316 WriteEnd();
+
3317 Store(file);
+
3318}
+
3319
+
3320void GeneratorGo::GenerateFBEFinalModelString(const std::string& package)
+
3321{
+
3322 CppCommon::Path path = CppCommon::Path(_output) / package;
+
3323
+
3324 // Generate the file
+
3325 CppCommon::Path file = path / ("FinalModelString.go");
+
3326 WriteBegin();
+
3327
+
3328 // Generate headers
+
3329 GenerateHeader("FBE");
+
3330
+
3331 std::string code = R"CODE(
+
3332package fbe
+
3333
+
3334import "errors"
+
3335
+
3336// Fast Binary Encoding string final model
+
3337type FinalModelString struct {
+
3338 // Final model buffer
+
3339 buffer *Buffer
+
3340 // Final model buffer offset
+
3341 offset int
+
3342}
+
3343
+
3344// Create a new string final model
+
3345func NewFinalModelString(buffer *Buffer, offset int) *FinalModelString {
+
3346 return &FinalModelString{buffer: buffer, offset: offset}
+
3347}
+
3348
+
3349// Get the allocation size
+
3350func (fm *FinalModelString) FBEAllocationSize(value string) int { return 4 + 3 * (len(value) + 1) }
+
3351
+
3352// Get the final offset
+
3353func (fm *FinalModelString) FBEOffset() int { return fm.offset }
+
3354// Set the final offset
+
3355func (fm *FinalModelString) SetFBEOffset(value int) { fm.offset = value }
+
3356
+
3357// Shift the current final offset
+
3358func (fm *FinalModelString) FBEShift(size int) { fm.offset += size }
+
3359// Unshift the current final offset
+
3360func (fm *FinalModelString) FBEUnshift(size int) { fm.offset -= size }
+
3361
+
3362// Check if the string value is valid
+
3363func (fm *FinalModelString) Verify() int {
+
3364 if (fm.buffer.Offset() + fm.FBEOffset() + 4) > fm.buffer.Size() {
+
3365 return MaxInt
+
3366 }
+
3367
+
3368 fbeStringSize := int(ReadUInt32(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset()))
+
3369 if (fm.buffer.Offset() + fm.FBEOffset() + 4 + fbeStringSize) > fm.buffer.Size() {
+
3370 return MaxInt
+
3371 }
+
3372
+
3373 return 4 + fbeStringSize
+
3374}
+
3375
+
3376// Get the string value
+
3377func (fm *FinalModelString) Get() (string, int, error) {
+
3378 if (fm.buffer.Offset() + fm.FBEOffset() + 4) > fm.buffer.Size() {
+
3379 return "", 0, nil
+
3380 }
+
3381
+
3382 fbeStringSize := int(ReadUInt32(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset()))
+
3383 if (fm.buffer.Offset() + fm.FBEOffset() + 4 + fbeStringSize) > fm.buffer.Size() {
+
3384 return "", 4, errors.New("model is broken")
+
3385 }
+
3386
+
3387 data := ReadBytes(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset() + 4, fbeStringSize)
+
3388 return string(data), 4 + fbeStringSize, nil
+
3389}
+
3390
+
3391// Set the string value
+
3392func (fm *FinalModelString) Set(value string) (int, error) {
+
3393 if (fm.buffer.Offset() + fm.FBEOffset() + 4) > fm.buffer.Size() {
+
3394 return 0, errors.New("model is broken")
+
3395 }
+
3396
+
3397 data := []byte(value)
+
3398
+
3399 fbeStringSize := len(data)
+
3400 if (fm.buffer.Offset() + fm.FBEOffset() + 4 + fbeStringSize) > fm.buffer.Size() {
+
3401 return 4, errors.New("model is broken")
+
3402 }
+
3403
+
3404 WriteUInt32(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset(), uint32(fbeStringSize))
+
3405 WriteBytes(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset() + 4, data)
+
3406 return 4 + fbeStringSize, nil
+
3407}
+
3408)CODE";
+
3409
+
3410 // Prepare code template
+
3411 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
3412
+
3413 Write(code);
+
3414
+
3415 // Generate footer
+
3416 GenerateFooter();
+
3417
+
3418 // Store the file
+
3419 WriteEnd();
+
3420 Store(file);
+
3421}
+
3422
+
3423void GeneratorGo::GenerateFBEFinalModelOptional(const std::shared_ptr<Package>& p, const std::string& name, const std::string& model, const StructField& field, const CppCommon::Path& path)
+
3424{
+
3425 // Generate the output file
+
3426 CppCommon::Path output = path / ("FinalModelOptional" + name + ".go");
+
3427 WriteBegin();
+
3428
+
3429 // Generate headers
+
3430 GenerateHeader("FBE");
+
3431
+
3432 // Generate package
+
3433 WriteLine();
+
3434 WriteLineIndent("package " + *p->name);
+
3435
+
3436 // Generate imports
+
3437 WriteLine();
+
3438 GenerateImports(p);
+
3439
+
3440 std::string code = R"CODE(
+
3441// Fast Binary Encoding optional _NAME_ final model
+
3442type FinalModelOptional_NAME_ struct {
+
3443 // Final model buffer
+
3444 buffer *fbe.Buffer
+
3445 // Final model buffer offset
+
3446 offset int
+
3447
+
3448 // Base final model value
+
3449 value *_MODEL_
+
3450}
+
3451
+
3452// Create a new optional _NAME_ final model
+
3453func NewFinalModelOptional_NAME_(buffer *fbe.Buffer, offset int) *FinalModelOptional_NAME_ {
+
3454 fbeResult := FinalModelOptional_NAME_{buffer: buffer, offset: offset}
+
3455 fbeResult.value = _MODEL_NEW_(buffer, 0)
+
3456 return &fbeResult
+
3457}
+
3458
+
3459// Get the optional final model value
+
3460func (fm *FinalModelOptional_NAME_) Value() *_MODEL_ { return fm.value }
+
3461
+
3462// Get the allocation size
+
3463func (fm *FinalModelOptional_NAME_) FBEAllocationSize(fbeValue _TYPE_ARG_) int {
+
3464 if fbeValue != nil {
+
3465 return 1 + fm.value.FBEAllocationSize(_VALUE_)
+
3466 } else {
+
3467 return 1
+
3468 }
+
3469}
+
3470
+
3471// Get the final offset
+
3472func (fm *FinalModelOptional_NAME_) FBEOffset() int { return fm.offset }
+
3473// Set the final offset
+
3474func (fm *FinalModelOptional_NAME_) SetFBEOffset(value int) { fm.offset = value }
+
3475
+
3476// Shift the current final offset
+
3477func (fm *FinalModelOptional_NAME_) FBEShift(size int) { fm.offset += size }
+
3478// Unshift the current final offset
+
3479func (fm *FinalModelOptional_NAME_) FBEUnshift(size int) { fm.offset -= size }
+
3480
+
3481// Check if the object contains a value
+
3482func (fm *FinalModelOptional_NAME_) HasValue() bool {
+
3483 if (fm.buffer.Offset() + fm.FBEOffset() + 1) > fm.buffer.Size() {
+
3484 return false
+
3485 }
+
3486
+
3487 fbeHasValue := fbe.ReadUInt8(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset())
+
3488 return fbeHasValue != 0
+
3489}
+
3490
+
3491// Check if the optional value is valid
+
3492func (fm *FinalModelOptional_NAME_) Verify() int {
+
3493 if (fm.buffer.Offset() + fm.FBEOffset() + 1) > fm.buffer.Size() {
+
3494 return fbe.MaxInt
+
3495 }
+
3496
+
3497 fbeHasValue := fbe.ReadUInt8(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset())
+
3498 if fbeHasValue == 0 {
+
3499 return 1
+
3500 }
+
3501
+
3502 fm.buffer.Shift(fm.FBEOffset() + 1)
+
3503 fbeResult := fm.value.Verify()
+
3504 fm.buffer.Unshift(fm.FBEOffset() + 1)
+
3505 return 1 + fbeResult
+
3506}
+
3507
+
3508// Get the optional value
+
3509func (fm *FinalModelOptional_NAME_) Get() (_TYPE_ARG_, int, error) {
+
3510 var fbeValue _TYPE_ARG_ = nil
+
3511
+
3512 if (fm.buffer.Offset() + fm.FBEOffset() + 1) > fm.buffer.Size() {
+
3513 return fbeValue, 0, errors.New("model is broken")
+
3514 }
+
3515
+
3516 if !fm.HasValue() {
+
3517 return fbeValue, 1, nil
+
3518 }
+
3519
+
3520 var fbeResult int
+
3521 var err error
+
3522
+
3523 fbeValue = _TYPE_NEW_
+
3524
+
3525 fm.buffer.Shift(fm.FBEOffset() + 1)
+
3526 _GET_VALUE_
+
3527 fm.buffer.Unshift(fm.FBEOffset() + 1)
+
3528 return fbeValue, 1 + fbeResult, err
+
3529}
+
3530
+
3531// Set the optional value
+
3532func (fm *FinalModelOptional_NAME_) Set(fbeValue _TYPE_ARG_) (int, error) {
+
3533 if (fm.buffer.Offset() + fm.FBEOffset() + 1) > fm.buffer.Size() {
+
3534 return 0, errors.New("model is broken")
+
3535 }
+
3536
+
3537 fbeHasValue := uint8(0)
+
3538 if fbeValue != nil {
+
3539 fbeHasValue = uint8(1)
+
3540 }
+
3541 fbe.WriteUInt8(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset(), fbeHasValue)
+
3542 if fbeHasValue == 0 {
+
3543 return 1, nil
+
3544 }
+
3545
+
3546 fm.buffer.Shift(fm.FBEOffset() + 1)
+
3547 _SET_VALUE_
+
3548 fm.buffer.Unshift(fm.FBEOffset() + 1)
+
3549 return 1 + fbeResult, err
+
3550}
+
3551)CODE";
+
3552
+
3553 // Prepare code template
+
3554 code = std::regex_replace(code, std::regex("_NAME_"), name);
+
3555 code = std::regex_replace(code, std::regex("_TYPE_ARG_"), ConvertTypeName(*field.type, field.optional));
+
3556 code = std::regex_replace(code, std::regex("_TYPE_NEW_"), IsGoType(*field.type) ? ConvertOptional(*field.type) : (ConvertNewName(*field.type) + "()"));
+
3557 code = std::regex_replace(code, std::regex("_TYPE_"), ConvertTypeFieldType(*field.type, field.optional));
+
3558 code = std::regex_replace(code, std::regex("_MODEL_NEW_"), ConvertNewName(model));
+
3559 code = std::regex_replace(code, std::regex("_MODEL_"), model);
+
3560 code = std::regex_replace(code, std::regex("_GET_VALUE_"), IsGoType(*field.type) ? "*fbeValue, fbeResult, err = fm.value.Get()" : "fbeResult, err = fm.value.GetValue(fbeValue)");
+
3561 code = std::regex_replace(code, std::regex("_SET_VALUE_"), IsGoType(*field.type) ? "fbeResult, err := fm.value.Set(*fbeValue)" : "fbeResult, err := fm.value.Set(fbeValue)");
+
3562 code = std::regex_replace(code, std::regex("_VALUE_"), IsGoType(*field.type) ? "*fbeValue" : "fbeValue");
+
3563 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
3564
+
3565 Write(code);
+
3566
+
3567 // Generate footer
+
3568 GenerateFooter();
+
3569
+
3570 // Store the output file
+
3571 WriteEnd();
+
3572 Store(output);
+
3573}
+
3574
+
3575void GeneratorGo::GenerateFBEFinalModelArray(const std::shared_ptr<Package>& p, const std::string& name, const std::string& model, const StructField& field, const CppCommon::Path& path)
+
3576{
+
3577 // Generate the output file
+
3578 CppCommon::Path output = path / ("FinalModelArray" + name + ".go");
+
3579 WriteBegin();
+
3580
+
3581 // Generate headers
+
3582 GenerateHeader("FBE");
+
3583
+
3584 // Generate package
+
3585 WriteLine();
+
3586 WriteLineIndent("package " + *p->name);
+
3587
+
3588 // Generate imports
+
3589 WriteLine();
+
3590 GenerateImports(p);
+
3591
+
3592 std::string code = R"CODE(
+
3593// Fast Binary Encoding _NAME_ array final model
+
3594type FinalModelArray_NAME_ struct {
+
3595 // Final model buffer
+
3596 buffer *fbe.Buffer
+
3597 // Final model buffer offset
+
3598 offset int
+
3599
+
3600 // Array item final model
+
3601 model *_MODEL_
+
3602 // Array size
+
3603 size int
+
3604}
+
3605
+
3606// Create a new _NAME_ array final model
+
3607func NewFinalModelArray_NAME_(buffer *fbe.Buffer, offset int, size int) *FinalModelArray_NAME_ {
+
3608 fbeResult := FinalModelArray_NAME_{buffer: buffer, offset: offset}
+
3609 fbeResult.model = _MODEL_NEW_(buffer, offset)
+
3610 fbeResult.size = size
+
3611 return &fbeResult
+
3612}
+
3613
+
3614// Get the allocation size
+
3615func (fm *FinalModelArray_NAME_) FBEAllocationSize(values []_TYPE_) int {
+
3616 result := 0
+
3617
+
3618 size := len(values)
+
3619 if size > fm.size {
+
3620 size = fm.size
+
3621 }
+
3622
+
3623 for i := 0; i < size; i++ {
+
3624 result += fm.model.FBEAllocationSize(_SET_VALUE_)
+
3625 }
+
3626
+
3627 return result
+
3628}
+
3629
+
3630// Get the final offset
+
3631func (fm *FinalModelArray_NAME_) FBEOffset() int { return fm.offset }
+
3632// Set the final offset
+
3633func (fm *FinalModelArray_NAME_) SetFBEOffset(value int) { fm.offset = value }
+
3634
+
3635// Shift the current final offset
+
3636func (fm *FinalModelArray_NAME_) FBEShift(size int) { fm.offset += size }
+
3637// Unshift the current final offset
+
3638func (fm *FinalModelArray_NAME_) FBEUnshift(size int) { fm.offset -= size }
+
3639
+
3640// Get the array offset
+
3641func (fm *FinalModelArray_NAME_) Offset() int { return 0 }
+
3642// Get the array size
+
3643func (fm *FinalModelArray_NAME_) Size() int { return fm.size }
+
3644
+
3645// Check if the array is valid
+
3646func (fm *FinalModelArray_NAME_) Verify() int {
+
3647 if (fm.buffer.Offset() + fm.FBEOffset()) > fm.buffer.Size() {
+
3648 return fbe.MaxInt
+
3649 }
+
3650
+
3651 result := 0
+
3652 fm.model.SetFBEOffset(fm.FBEOffset())
+
3653 for i := 0; i < fm.size; i++ {
+
3654 offset := fm.model.Verify()
+
3655 if offset == fbe.MaxInt {
+
3656 return fbe.MaxInt
+
3657 }
+
3658 fm.model.FBEShift(offset)
+
3659 result += offset
+
3660 }
+
3661 return result
+
3662}
+
3663
+
3664// Get the array
+
3665func (fm *FinalModelArray_NAME_) Get() ([]_TYPE_, int, error) {
+
3666 values := make([]_TYPE_, 0, fm.size)
+
3667
+
3668 if (fm.buffer.Offset() + fm.FBEOffset()) > fm.buffer.Size() {
+
3669 return values, 0, errors.New("model is broken")
+
3670 }
+
3671
+
3672 result := 0
+
3673 fm.model.SetFBEOffset(fm.FBEOffset())
+
3674 for i := 0; i < fm.size; i++ {
+
3675 value, offset, err := fm.model.Get()
+
3676 if err != nil {
+
3677 return values, result, err
+
3678 }
+
3679 values = append(values, _GET_VALUE_)
+
3680 fm.model.FBEShift(offset)
+
3681 result += offset
+
3682 }
+
3683 return values, result, nil
+
3684}
+
3685
+
3686// Set the array
+
3687func (fm *FinalModelArray_NAME_) Set(values []_TYPE_) (int, error) {
+
3688 if (fm.buffer.Offset() + fm.FBEOffset()) > fm.buffer.Size() {
+
3689 return 0, errors.New("model is broken")
+
3690 }
+
3691
+
3692 size := len(values)
+
3693 if size > fm.size {
+
3694 size = fm.size
+
3695 }
+
3696
+
3697 result := 0
+
3698 fm.model.SetFBEOffset(fm.FBEOffset())
+
3699 for i := 0; i < size; i++ {
+
3700 offset, err := fm.model.Set(_SET_VALUE_)
+
3701 if err != nil {
+
3702 return result, err
+
3703 }
+
3704 fm.model.FBEShift(offset)
+
3705 result += offset
+
3706 }
+
3707 return result, nil
+
3708}
+
3709)CODE";
+
3710
+
3711 // Prepare code template
+
3712 code = std::regex_replace(code, std::regex("_NAME_"), name);
+
3713 code = std::regex_replace(code, std::regex("_TYPE_"), ConvertTypeFieldType(*field.type, field.optional));
+
3714 code = std::regex_replace(code, std::regex("_MODEL_NEW_"), ConvertNewName(model));
+
3715 code = std::regex_replace(code, std::regex("_MODEL_"), model);
+
3716 code = std::regex_replace(code, std::regex("_GET_VALUE_"), (IsGoType(*field.type) || field.optional) ? "value" : "*value");
+
3717 code = std::regex_replace(code, std::regex("_SET_VALUE_"), (IsGoType(*field.type) || field.optional) ? "values[i]" : "&values[i]");
+
3718 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
3719
+
3720 Write(code);
+
3721
+
3722 // Generate footer
+
3723 GenerateFooter();
+
3724
+
3725 // Store the output file
+
3726 WriteEnd();
+
3727 Store(output);
+
3728}
+
3729
+
3730void GeneratorGo::GenerateFBEFinalModelVector(const std::shared_ptr<Package>& p, const std::string& name, const std::string& model, const StructField& field, const CppCommon::Path& path)
+
3731{
+
3732 // Generate the output file
+
3733 CppCommon::Path output = path / ("FinalModelVector" + name + ".go");
+
3734 WriteBegin();
+
3735
+
3736 // Generate headers
+
3737 GenerateHeader("FBE");
+
3738
+
3739 // Generate package
+
3740 WriteLine();
+
3741 WriteLineIndent("package " + *p->name);
+
3742
+
3743 // Generate imports
+
3744 WriteLine();
+
3745 GenerateImports(p);
+
3746
+
3747 std::string code = R"CODE(
+
3748// Fast Binary Encoding _NAME_ vector final model
+
3749type FinalModelVector_NAME_ struct {
+
3750 // Final model buffer
+
3751 buffer *fbe.Buffer
+
3752 // Final model buffer offset
+
3753 offset int
+
3754
+
3755 // Vector item final model
+
3756 model *_MODEL_
+
3757}
+
3758
+
3759// Create a new _NAME_ vector final model
+
3760func NewFinalModelVector_NAME_(buffer *fbe.Buffer, offset int) *FinalModelVector_NAME_ {
+
3761 fbeResult := FinalModelVector_NAME_{buffer: buffer, offset: offset}
+
3762 fbeResult.model = _MODEL_NEW_(buffer, offset)
+
3763 return &fbeResult
+
3764}
+
3765
+
3766// Get the allocation size
+
3767func (fm *FinalModelVector_NAME_) FBEAllocationSize(values []_TYPE_) int {
+
3768 size := 4
+
3769 for _, value := range values {
+
3770 size += fm.model.FBEAllocationSize(_SET_VALUE_)
+
3771 }
+
3772 return size
+
3773}
+
3774
+
3775// Get the final offset
+
3776func (fm *FinalModelVector_NAME_) FBEOffset() int { return fm.offset }
+
3777// Set the final offset
+
3778func (fm *FinalModelVector_NAME_) SetFBEOffset(value int) { fm.offset = value }
+
3779
+
3780// Shift the current final offset
+
3781func (fm *FinalModelVector_NAME_) FBEShift(size int) { fm.offset += size }
+
3782// Unshift the current final offset
+
3783func (fm *FinalModelVector_NAME_) FBEUnshift(size int) { fm.offset -= size }
+
3784
+
3785// Check if the vector is valid
+
3786func (fm *FinalModelVector_NAME_) Verify() int {
+
3787 if (fm.buffer.Offset() + fm.FBEOffset() + 4) > fm.buffer.Size() {
+
3788 return fbe.MaxInt
+
3789 }
+
3790
+
3791 fbeVectorSize := int(fbe.ReadUInt32(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset()))
+
3792
+
3793 size := 4
+
3794 fm.model.SetFBEOffset(fm.FBEOffset() + 4)
+
3795 for i := fbeVectorSize; i > 0; i-- {
+
3796 offset := fm.model.Verify()
+
3797 if offset == fbe.MaxInt {
+
3798 return fbe.MaxInt
+
3799 }
+
3800 fm.model.FBEShift(offset)
+
3801 size += offset
+
3802 }
+
3803 return size
+
3804}
+
3805
+
3806// Get the vector
+
3807func (fm *FinalModelVector_NAME_) Get() ([]_TYPE_, int, error) {
+
3808 values := make([]_TYPE_, 0)
+
3809
+
3810 if (fm.buffer.Offset() + fm.FBEOffset() + 4) > fm.buffer.Size() {
+
3811 return values, 0, errors.New("model is broken")
+
3812 }
+
3813
+
3814 fbeVectorSize := int(fbe.ReadUInt32(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset()))
+
3815 if fbeVectorSize == 0 {
+
3816 return values, 4, nil
+
3817 }
+
3818
+
3819 values = make([]_TYPE_, 0, fbeVectorSize)
+
3820
+
3821 size := 4
+
3822 fm.model.SetFBEOffset(fm.FBEOffset() + 4)
+
3823 for i := 0; i < fbeVectorSize; i++ {
+
3824 value, offset, err := fm.model.Get()
+
3825 if err != nil {
+
3826 return values, size, err
+
3827 }
+
3828 values = append(values, _GET_VALUE_)
+
3829 fm.model.FBEShift(offset)
+
3830 size += offset
+
3831 }
+
3832 return values, size, nil
+
3833}
+
3834
+
3835// Set the vector
+
3836func (fm *FinalModelVector_NAME_) Set(values []_TYPE_) (int, error) {
+
3837 if (fm.buffer.Offset() + fm.FBEOffset() + 4) > fm.buffer.Size() {
+
3838 return 0, errors.New("model is broken")
+
3839 }
+
3840
+
3841 fbe.WriteUInt32(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset(), uint32(len(values)))
+
3842
+
3843 size := 4
+
3844 fm.model.SetFBEOffset(fm.FBEOffset() + 4)
+
3845 for _, value := range values {
+
3846 offset, err := fm.model.Set(_SET_VALUE_)
+
3847 if err != nil {
+
3848 return size, err
+
3849 }
+
3850 fm.model.FBEShift(offset)
+
3851 size += offset
+
3852 }
+
3853 return size, nil
+
3854}
+
3855)CODE";
+
3856
+
3857 // Prepare code template
+
3858 code = std::regex_replace(code, std::regex("_NAME_"), name);
+
3859 code = std::regex_replace(code, std::regex("_TYPE_"), ConvertTypeFieldType(*field.type, field.optional));
+
3860 code = std::regex_replace(code, std::regex("_MODEL_NEW_"), ConvertNewName(model));
+
3861 code = std::regex_replace(code, std::regex("_MODEL_"), model);
+
3862 code = std::regex_replace(code, std::regex("_GET_VALUE_"), (IsGoType(*field.type) || field.optional) ? "value" : "*value");
+
3863 code = std::regex_replace(code, std::regex("_SET_VALUE_"), (IsGoType(*field.type) || field.optional) ? "value" : "&value");
+
3864 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
3865
+
3866 Write(code);
+
3867
+
3868 // Generate footer
+
3869 GenerateFooter();
+
3870
+
3871 // Store the output file
+
3872 WriteEnd();
+
3873 Store(output);
+
3874}
+
3875
+
3876void GeneratorGo::GenerateFBEFinalModelSet(const std::shared_ptr<Package>& p, const std::string& name, const std::string& model, const StructField& field, const CppCommon::Path& path)
+
3877{
+
3878 // Generate the output file
+
3879 CppCommon::Path output = path / ("FinalModelSet" + name + ".go");
+
3880 WriteBegin();
+
3881
+
3882 // Generate headers
+
3883 GenerateHeader("FBE");
+
3884
+
3885 // Generate package
+
3886 WriteLine();
+
3887 WriteLineIndent("package " + *p->name);
+
3888
+
3889 // Generate imports
+
3890 WriteLine();
+
3891 GenerateImports(p);
+
3892
+
3893 std::string code = R"CODE(
+
3894// Fast Binary Encoding _NAME_ set final model
+
3895type FinalModelSet_NAME_ struct {
+
3896 // Final model buffer
+
3897 buffer *fbe.Buffer
+
3898 // Final model buffer offset
+
3899 offset int
+
3900
+
3901 // Set item final model
+
3902 model *_MODEL_
+
3903}
+
3904
+
3905// Create a new _NAME_ set final model
+
3906func NewFinalModelSet_NAME_(buffer *fbe.Buffer, offset int) *FinalModelSet_NAME_ {
+
3907 fbeResult := FinalModelSet_NAME_{buffer: buffer, offset: offset}
+
3908 fbeResult.model = _MODEL_NEW_(buffer, offset)
+
3909 return &fbeResult
+
3910}
+
3911
+
3912// Get the allocation size
+
3913func (fm *FinalModelSet_NAME_) FBEAllocationSize(values _TYPE_) int {
+
3914 size := 4
+
3915 for _, value := range values {
+
3916 size += fm.model.FBEAllocationSize(_SET_VALUE_)
+
3917 }
+
3918 return size
+
3919}
+
3920
+
3921// Get the final offset
+
3922func (fm *FinalModelSet_NAME_) FBEOffset() int { return fm.offset }
+
3923// Set the final offset
+
3924func (fm *FinalModelSet_NAME_) SetFBEOffset(value int) { fm.offset = value }
+
3925
+
3926// Shift the current final offset
+
3927func (fm *FinalModelSet_NAME_) FBEShift(size int) { fm.offset += size }
+
3928// Unshift the current final offset
+
3929func (fm *FinalModelSet_NAME_) FBEUnshift(size int) { fm.offset -= size }
+
3930
+
3931// Check if the set value is valid
+
3932func (fm *FinalModelSet_NAME_) Verify() int {
+
3933 if (fm.buffer.Offset() + fm.FBEOffset() + 4) > fm.buffer.Size() {
+
3934 return fbe.MaxInt
+
3935 }
+
3936
+
3937 fbeSetSize := int(fbe.ReadUInt32(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset()))
+
3938
+
3939 size := 4
+
3940 fm.model.SetFBEOffset(fm.FBEOffset() + 4)
+
3941 for i := fbeSetSize; i > 0; i-- {
+
3942 offset := fm.model.Verify()
+
3943 if offset == fbe.MaxInt {
+
3944 return fbe.MaxInt
+
3945 }
+
3946 fm.model.FBEShift(offset)
+
3947 size += offset
+
3948 }
+
3949 return size
+
3950}
+
3951
+
3952// Get the set value
+
3953func (fm *FinalModelSet_NAME_) Get() (_TYPE_, int, error) {
+
3954 values := make(_TYPE_)
+
3955
+
3956 if (fm.buffer.Offset() + fm.FBEOffset() + 4) > fm.buffer.Size() {
+
3957 return values, 0, errors.New("model is broken")
+
3958 }
+
3959
+
3960 fbeSetSize := int(fbe.ReadUInt32(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset()))
+
3961 if fbeSetSize == 0 {
+
3962 return values, 4, nil
+
3963 }
+
3964
+
3965 size := 4
+
3966 fm.model.SetFBEOffset(fm.FBEOffset() + 4)
+
3967 for i := 0; i < fbeSetSize; i++ {
+
3968 value, offset, err := fm.model.Get()
+
3969 if err != nil {
+
3970 return values, size, err
+
3971 }
+
3972 values[_GET_KEY_] = _GET_VALUE_
+
3973 fm.model.FBEShift(offset)
+
3974 size += offset
+
3975 }
+
3976 return values, size, nil
+
3977}
+
3978
+
3979// Set the set value
+
3980func (fm *FinalModelSet_NAME_) Set(values _TYPE_) (int, error) {
+
3981 if (fm.buffer.Offset() + fm.FBEOffset() + 4) > fm.buffer.Size() {
+
3982 return 0, errors.New("model is broken")
+
3983 }
+
3984
+
3985 fbe.WriteUInt32(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset(), uint32(len(values)))
+
3986
+
3987 size := 4
+
3988 fm.model.SetFBEOffset(fm.FBEOffset() + 4)
+
3989 for _, value := range values {
+
3990 offset, err := fm.model.Set(_SET_VALUE_)
+
3991 if err != nil {
+
3992 return size, err
+
3993 }
+
3994 fm.model.FBEShift(offset)
+
3995 size += offset
+
3996 }
+
3997 return size, nil
+
3998}
+
3999)CODE";
+
4000
+
4001 // Prepare code template
+
4002 code = std::regex_replace(code, std::regex("_NAME_"), name);
+
4003 code = std::regex_replace(code, std::regex("_TYPE_"), "map[" + ConvertKeyName(*field.key) + "]" + ConvertTypeName(*field.type, field.optional));
+
4004 code = std::regex_replace(code, std::regex("_MODEL_NEW_"), ConvertNewName(model));
+
4005 code = std::regex_replace(code, std::regex("_MODEL_"), model);
+
4006 code = std::regex_replace(code, std::regex("_GET_KEY_"), IsGoType(*field.type) ? "value" : "value.Key()");
+
4007 code = std::regex_replace(code, std::regex("_GET_VALUE_"), (IsGoType(*field.type) || field.optional) ? "value" : "*value");
+
4008 code = std::regex_replace(code, std::regex("_SET_VALUE_"), (IsGoType(*field.type) || field.optional) ? "value" : "&value");
+
4009 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
4010
+
4011 Write(code);
+
4012
+
4013 // Generate footer
+
4014 GenerateFooter();
+
4015
+
4016 // Store the output file
+
4017 WriteEnd();
+
4018 Store(output);
+
4019}
+
4020
+
4021void GeneratorGo::GenerateFBEFinalModelMap(const std::shared_ptr<Package>& p, const std::string& key_name, const std::string& key_model, const std::string& value_name, const std::string& value_model, const StructField& field, const CppCommon::Path& path)
+
4022{
+
4023 // Generate the output file
+
4024 CppCommon::Path output = path / ("FinalModelMap" + key_name + value_name + ".go");
+
4025 WriteBegin();
+
4026
+
4027 // Generate headers
+
4028 GenerateHeader("FBE");
+
4029
+
4030 // Generate package
+
4031 WriteLine();
+
4032 WriteLineIndent("package " + *p->name);
+
4033
+
4034 // Generate imports
+
4035 WriteLine();
+
4036 GenerateImports(p);
+
4037
+
4038 std::string code = R"CODE(
+
4039// Fast Binary Encoding _KEY_NAME_->_VALUE_NAME_ map final model
+
4040type FinalModelMap_KEY_NAME__VALUE_NAME_ struct {
+
4041 // Final model buffer
+
4042 buffer *fbe.Buffer
+
4043 // Final model buffer offset
+
4044 offset int
+
4045
+
4046 // Map key final model
+
4047 modelKey *_MODEL_KEY_
+
4048 // Map value final model
+
4049 modelValue *_MODEL_VALUE_
+
4050}
+
4051
+
4052// Create a new _KEY_NAME_->_VALUE_NAME_ map final model
+
4053func NewFinalModelMap_KEY_NAME__VALUE_NAME_(buffer *fbe.Buffer, offset int) *FinalModelMap_KEY_NAME__VALUE_NAME_ {
+
4054 fbeResult := FinalModelMap_KEY_NAME__VALUE_NAME_{buffer: buffer, offset: offset}
+
4055 fbeResult.modelKey = _MODEL_KEY_NEW_(buffer, offset)
+
4056 fbeResult.modelValue = _MODEL_VALUE_NEW_(buffer, offset)
+
4057 return &fbeResult
+
4058}
+
4059
+
4060// Get the allocation size
+
4061func (fm *FinalModelMap_KEY_NAME__VALUE_NAME_) FBEAllocationSize(values _TYPE_) int {
+
4062 size := 4
+
4063 for _KEY_, value := range values {
+
4064 size += fm.modelKey.FBEAllocationSize(_SET_KEY_)
+
4065 size += fm.modelValue.FBEAllocationSize(_SET_VALUE_)
+
4066 }
+
4067 return size
+
4068}
+
4069
+
4070// Get the final offset
+
4071func (fm *FinalModelMap_KEY_NAME__VALUE_NAME_) FBEOffset() int { return fm.offset }
+
4072// Set the final offset
+
4073func (fm *FinalModelMap_KEY_NAME__VALUE_NAME_) SetFBEOffset(value int) { fm.offset = value }
+
4074
+
4075// Shift the current final offset
+
4076func (fm *FinalModelMap_KEY_NAME__VALUE_NAME_) FBEShift(size int) { fm.offset += size }
+
4077// Unshift the current final offset
+
4078func (fm *FinalModelMap_KEY_NAME__VALUE_NAME_) FBEUnshift(size int) { fm.offset -= size }
+
4079
+
4080// Check if the map is valid
+
4081func (fm *FinalModelMap_KEY_NAME__VALUE_NAME_) Verify() int {
+
4082 if (fm.buffer.Offset() + fm.FBEOffset() + 4) > fm.buffer.Size() {
+
4083 return fbe.MaxInt
+
4084 }
+
4085
+
4086 fbeSetSize := int(fbe.ReadUInt32(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset()))
+
4087
+
4088 size := 4
+
4089 fm.modelKey.SetFBEOffset(fm.FBEOffset() + 4)
+
4090 fm.modelValue.SetFBEOffset(fm.FBEOffset() + 4)
+
4091 for i := fbeSetSize; i > 0; i-- {
+
4092 offsetKey := fm.modelKey.Verify()
+
4093 if offsetKey == fbe.MaxInt {
+
4094 return fbe.MaxInt
+
4095 }
+
4096 fm.modelKey.FBEShift(offsetKey)
+
4097 fm.modelValue.FBEShift(offsetKey)
+
4098 size += offsetKey
+
4099 offsetValue := fm.modelValue.Verify()
+
4100 if offsetValue == fbe.MaxInt {
+
4101 return fbe.MaxInt
+
4102 }
+
4103 fm.modelKey.FBEShift(offsetValue)
+
4104 fm.modelValue.FBEShift(offsetValue)
+
4105 size += offsetValue
+
4106 }
+
4107 return size
+
4108}
+
4109
+
4110// Get the map
+
4111func (fm *FinalModelMap_KEY_NAME__VALUE_NAME_) Get() (_TYPE_, int, error) {
+
4112 values := make(_TYPE_)
+
4113
+
4114 if (fm.buffer.Offset() + fm.FBEOffset() + 4) > fm.buffer.Size() {
+
4115 return values, 0, errors.New("model is broken")
+
4116 }
+
4117
+
4118 fbeSetSize := int(fbe.ReadUInt32(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset()))
+
4119 if fbeSetSize == 0 {
+
4120 return values, 4, nil
+
4121 }
+
4122
+
4123 size := 4
+
4124 fm.modelKey.SetFBEOffset(fm.FBEOffset() + 4)
+
4125 fm.modelValue.SetFBEOffset(fm.FBEOffset() + 4)
+
4126 for i := 0; i < fbeSetSize; i++ {
+
4127 key, offset, err := fm.modelKey.Get()
+
4128 if err != nil {
+
4129 return values, size, err
+
4130 }
+
4131 fm.modelKey.FBEShift(offset)
+
4132 fm.modelValue.FBEShift(offset)
+
4133 size += offset
+
4134 value, offset, err := fm.modelValue.Get()
+
4135 if err != nil {
+
4136 return values, size, err
+
4137 }
+
4138 fm.modelKey.FBEShift(offset)
+
4139 fm.modelValue.FBEShift(offset)
+
4140 size += offset
+
4141 values[_GET_KEY_] = _GET_VALUE_
+
4142 }
+
4143 return values, size, nil
+
4144}
+
4145
+
4146// Set the map
+
4147func (fm *FinalModelMap_KEY_NAME__VALUE_NAME_) Set(values _TYPE_) (int, error) {
+
4148 if (fm.buffer.Offset() + fm.FBEOffset() + 4) > fm.buffer.Size() {
+
4149 return 0, errors.New("model is broken")
+
4150 }
+
4151
+
4152 fbe.WriteUInt32(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset(), uint32(len(values)))
+
4153
+
4154 size := 4
+
4155 fm.modelKey.SetFBEOffset(fm.FBEOffset() + 4)
+
4156 fm.modelValue.SetFBEOffset(fm.FBEOffset() + 4)
+
4157 for _KEY_, value := range values {
+
4158 offsetKey, err := fm.modelKey.Set(_SET_KEY_)
+
4159 if err != nil {
+
4160 return size, err
+
4161 }
+
4162 fm.modelKey.FBEShift(offsetKey)
+
4163 fm.modelValue.FBEShift(offsetKey)
+
4164 offsetValue, err := fm.modelValue.Set(_SET_VALUE_)
+
4165 if err != nil {
+
4166 return size, err
+
4167 }
+
4168 fm.modelKey.FBEShift(offsetValue)
+
4169 fm.modelValue.FBEShift(offsetValue)
+
4170 size += offsetKey + offsetValue
+
4171 }
+
4172 return size, nil
+
4173}
+
4174)CODE";
+
4175
+
4176 // Prepare code template
+
4177 code = std::regex_replace(code, std::regex("_KEY_NAME_"), key_name);
+
4178 code = std::regex_replace(code, std::regex("_VALUE_NAME_"), value_name);
+
4179 code = std::regex_replace(code, std::regex("_TYPE_"), ConvertTypeName(field));
+
4180 code = std::regex_replace(code, std::regex("_MODEL_KEY_NEW_"), ConvertNewName(key_model));
+
4181 code = std::regex_replace(code, std::regex("_MODEL_VALUE_NEW_"), ConvertNewName(value_model));
+
4182 code = std::regex_replace(code, std::regex("_MODEL_KEY_"), key_model);
+
4183 code = std::regex_replace(code, std::regex("_MODEL_VALUE_"), value_model);
+
4184 code = std::regex_replace(code, std::regex("_GET_KEY_"), IsGoType(*field.key) ? "key" : "key.Key()");
+
4185 code = std::regex_replace(code, std::regex("_GET_VALUE_"), IsGoType(*field.key) ? ((IsGoType(*field.type) || field.optional) ? "value" : "*value") : ("struct{Key " + ConvertTypeName(*field.key, false) + "; Value " + ConvertTypeName(*field.type, field.optional) + "}{*key, " + ((IsGoType(*field.type) || field.optional) ? "value" : "*value") + "}"));
+
4186 code = std::regex_replace(code, std::regex("_SET_KEY_"), IsGoType(*field.key) ? "key" : "&value.Key");
+
4187 code = std::regex_replace(code, std::regex("_SET_VALUE_"), IsGoType(*field.key) ? ((IsGoType(*field.type) || field.optional) ? "value" : "&value") : ((IsGoType(*field.type) || field.optional) ? "value.Value" : "&value.Value"));
+
4188 code = std::regex_replace(code, std::regex("_KEY_"), IsGoType(*field.key) ? "key" : "_");
+
4189 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
4190
+
4191 Write(code);
+
4192
+
4193 // Generate footer
+
4194 GenerateFooter();
+
4195
+
4196 // Store the output file
+
4197 WriteEnd();
+
4198 Store(output);
+
4199}
+
4200
+
4201void GeneratorGo::GenerateFBEFinalModelEnumFlags(const std::string& package, const std::string& name, const std::string& type)
+
4202{
+
4203 CppCommon::Path path = CppCommon::Path(_output) / package;
+
4204
+
4205 // Generate the file
+
4206 CppCommon::Path file = path / ("FinalModel" + name + ".go");
+
4207 WriteBegin();
+
4208
+
4209 // Generate header
+
4210 GenerateHeader(CppCommon::Path(_input).filename().string());
+
4211
+
4212 // Generate package
+
4213 WriteLine();
+
4214 WriteLineIndent("package " + package);
+
4215
+
4216 // Generate imports
+
4217 WriteLine();
+
4218 WriteLineIndent("import \"errors\"");
+
4219 WriteLineIndent("import \"../fbe\"");
+
4220
+
4221 std::string code = R"CODE(
+
4222// Fast Binary Encoding _NAME_ final model
+
4223type FinalModel_NAME_ struct {
+
4224 // Final model buffer
+
4225 buffer *fbe.Buffer
+
4226 // Final model buffer offset
+
4227 offset int
+
4228}
+
4229
+
4230// Create a new _NAME_ final model
+
4231func NewFinalModel_NAME_(buffer *fbe.Buffer, offset int) *FinalModel_NAME_ {
+
4232 return &FinalModel_NAME_{buffer: buffer, offset: offset}
+
4233}
+
4234
+
4235// Get the allocation size
+
4236func (fm *FinalModel_NAME_) FBEAllocationSize(value *_NAME_) int { return fm.FBESize() }
+
4237
+
4238// Get the final size
+
4239func (fm *FinalModel_NAME_) FBESize() int { return _SIZE_ }
+
4240
+
4241// Get the final offset
+
4242func (fm *FinalModel_NAME_) FBEOffset() int { return fm.offset }
+
4243// Set the final offset
+
4244func (fm *FinalModel_NAME_) SetFBEOffset(value int) { fm.offset = value }
+
4245
+
4246// Shift the current final offset
+
4247func (fm *FinalModel_NAME_) FBEShift(size int) { fm.offset += size }
+
4248// Unshift the current final offset
+
4249func (fm *FinalModel_NAME_) FBEUnshift(size int) { fm.offset -= size }
+
4250
+
4251// Check if the value is valid
+
4252func (fm *FinalModel_NAME_) Verify() int {
+
4253 if (fm.buffer.Offset() + fm.FBEOffset() + fm.FBESize()) > fm.buffer.Size() {
+
4254 return fbe.MaxInt
+
4255 }
+
4256
+
4257 return fm.FBESize()
+
4258}
+
4259
+
4260// Get the value
+
4261func (fm *FinalModel_NAME_) Get() (*_NAME_, int, error) {
+
4262 var value _NAME_
+
4263 size, err := fm.GetValueDefault(&value, _NAME_(0))
+
4264 return &value, size, err
+
4265}
+
4266
+
4267// Get the value with provided default value
+
4268func (fm *FinalModel_NAME_) GetDefault(defaults _NAME_) (*_NAME_, int, error) {
+
4269 var value _NAME_
+
4270 size, err := fm.GetValueDefault(&value, defaults)
+
4271 return &value, size, err
+
4272}
+
4273
+
4274// Get the value by the given pointer
+
4275func (fm *FinalModel_NAME_) GetValue(value *_NAME_) (int, error) {
+
4276 return fm.GetValueDefault(value, _NAME_(0))
+
4277}
+
4278
+
4279// Get the value by the given pointer with provided default value
+
4280func (fm *FinalModel_NAME_) GetValueDefault(value *_NAME_, defaults _NAME_) (int, error) {
+
4281 if (fm.buffer.Offset() + fm.FBEOffset() + fm.FBESize()) > fm.buffer.Size() {
+
4282 *value = defaults
+
4283 return 0, errors.New("model is broken")
+
4284 }
+
4285
+
4286 *value = _NAME_(fbe.Read_BASE_(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset()))
+
4287 return fm.FBESize(), nil
+
4288}
+
4289
+
4290// Set the value by the given pointer
+
4291func (fm *FinalModel_NAME_) Set(value *_NAME_) (int, error) {
+
4292 return fm.SetValue(*value)
+
4293}
+
4294
+
4295// Set the value
+
4296func (fm *FinalModel_NAME_) SetValue(value _NAME_) (int, error) {
+
4297 if (fm.buffer.Offset() + fm.FBEOffset() + fm.FBESize()) > fm.buffer.Size() {
+
4298 return 0, errors.New("model is broken")
+
4299 }
+
4300
+
4301 fbe.Write_BASE_(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset(), _TYPE_(value))
+
4302 return fm.FBESize(), nil
+
4303}
+
4304)CODE";
+
4305
+
4306 // Prepare code template
+
4307 code = std::regex_replace(code, std::regex("_NAME_"), name);
+
4308 code = std::regex_replace(code, std::regex("_TYPE_"), ConvertEnumType(type));
+
4309 code = std::regex_replace(code, std::regex("_BASE_"), ConvertEnumBase(type));
+
4310 code = std::regex_replace(code, std::regex("_SIZE_"), ConvertEnumSize(type));
+
4311 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
4312
+
4313 Write(code);
+
4314
+
4315 // Generate footer
+
4316 GenerateFooter();
+
4317
+
4318 // Store the file
+
4319 WriteEnd();
+
4320 Store(file);
+
4321}
+
4322
+
4323void GeneratorGo::GenerateFBESender(const std::string& package)
+
4324{
+
4325 CppCommon::Path path = CppCommon::Path(_output) / package;
+
4326
+
4327 // Generate the file
+
4328 CppCommon::Path file = path / "Sender.go";
+
4329 WriteBegin();
+
4330
+
4331 // Generate headers
+
4332 GenerateHeader("FBE");
+
4333
+
4334 std::string code = R"CODE(
+
4335package fbe
+
4336
+
4337// Send message interface
+
4338type OnSend interface {
+
4339 OnSend(buffer []byte) (int, error)
+
4340}
+
4341
+
4342// Send message function
+
4343type OnSendFunc func(buffer []byte) (int, error)
+
4344func (f OnSendFunc) OnSend(buffer []byte) (int, error) {
+
4345 return f(buffer)
+
4346}
+
4347
+
4348// Send log message interface
+
4349type OnSendLog interface {
+
4350 OnSendLog(message string)
+
4351}
+
4352
+
4353// Send log message function
+
4354type OnSendLogFunc func(message string)
+
4355func (f OnSendLogFunc) OnSendLog(message string) {
+
4356 f(message)
+
4357}
+
4358
+
4359// Fast Binary Encoding base sender
+
4360type Sender struct {
+
4361 // Sender bytes buffer
+
4362 buffer *Buffer
+
4363 // Logging flag
+
4364 logging bool
+
4365 // Final protocol flag
+
4366 final bool
+
4367
+
4368 // Send message handler
+
4369 HandlerOnSend OnSend
+
4370 // Send log message handler
+
4371 HandlerOnSendLog OnSendLog
+
4372}
+
4373
+
4374// Create a new base sender
+
4375func NewSender(buffer *Buffer, final bool) *Sender {
+
4376 sender := &Sender{buffer: buffer, logging: false, final: final}
+
4377 sender.SetupHandlerOnSendFunc(func(buffer []byte) (int, error) { panic("send handler is not provided") })
+
4378 sender.SetupHandlerOnSendLogFunc(func(message string) {})
+
4379 return sender
+
4380}
+
4381
+
4382// Get the bytes buffer
+
4383func (s *Sender) Buffer() *Buffer { return s.buffer }
+
4384
+
4385// Get the final protocol flag
+
4386func (s *Sender) Final() bool { return s.final }
+
4387
+
4388// Get the logging flag
+
4389func (s *Sender) Logging() bool { return s.logging }
+
4390// Set the logging flag
+
4391func (s *Sender) SetLogging(logging bool) { s.logging = logging }
+
4392
+
4393// Setup handlers
+
4394func (s *Sender) SetupHandlers(handlers interface{}) {
+
4395 if handler, ok := handlers.(OnSend); ok {
+
4396 s.SetupHandlerOnSend(handler)
+
4397 }
+
4398 if handler, ok := handlers.(OnSendLog); ok {
+
4399 s.SetupHandlerOnSendLog(handler)
+
4400 }
+
4401}
+
4402
+
4403// Setup send message handler
+
4404func (s *Sender) SetupHandlerOnSend(handler OnSend) { s.HandlerOnSend = handler }
+
4405// Setup send message handler function
+
4406func (s *Sender) SetupHandlerOnSendFunc(function func(buffer []byte) (int, error)) { s.HandlerOnSend = OnSendFunc(function) }
+
4407// Setup send log message handler
+
4408func (s *Sender) SetupHandlerOnSendLog(handler OnSendLog) { s.HandlerOnSendLog = handler }
+
4409// Setup send log message handler function
+
4410func (s *Sender) SetupHandlerOnSendLogFunc(function func(message string)) { s.HandlerOnSendLog = OnSendLogFunc(function) }
+
4411
+
4412// Reset the sender buffer
+
4413func (s *Sender) Reset() { s.buffer.Reset() }
+
4414
+
4415// Send serialized buffer.
+
4416// Direct call of the method requires knowledge about internals of FBE models serialization.
+
4417// Use it with care!
+
4418func (s *Sender) SendSerialized(serialized int) (int, error) {
+
4419 if serialized <= 0 {
+
4420 return 0, nil
+
4421 }
+
4422
+
4423 // Shift the send buffer
+
4424 s.buffer.Shift(serialized)
+
4425
+
4426 // Send the value
+
4427 sent, err := s.HandlerOnSend.OnSend(s.buffer.Data()[:s.buffer.Size()])
+
4428 s.buffer.Remove(0, sent)
+
4429 return sent, err
+
4430}
+
4431)CODE";
+
4432
+
4433 // Prepare code template
+
4434 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
4435
+
4436 Write(code);
+
4437
+
4438 // Generate footer
+
4439 GenerateFooter();
+
4440
+
4441 // Store the file
+
4442 WriteEnd();
+
4443 Store(file);
+
4444}
+
4445
+
4446void GeneratorGo::GenerateFBEReceiver(const std::string& package)
+
4447{
+
4448 CppCommon::Path path = CppCommon::Path(_output) / package;
+
4449
+
4450 // Generate the file
+
4451 CppCommon::Path file = path / "Receiver.go";
+
4452 WriteBegin();
+
4453
+
4454 // Generate headers
+
4455 GenerateHeader("FBE");
+
4456
+
4457 std::string code = R"CODE(
+
4458package fbe
+
4459
+
4460// Receive message interface
+
4461type OnReceive interface {
+
4462 OnReceive(fbeType int, buffer []byte) (bool, error)
+
4463}
+
4464
+
4465// Receive message function
+
4466type OnReceiveFunc func(fbeType int, buffer []byte) (bool, error)
+
4467func (f OnReceiveFunc) OnReceive(fbeType int, buffer []byte) (bool, error) {
+
4468 return f(fbeType, buffer)
+
4469}
+
4470
+
4471// Receive log message interface
+
4472type OnReceiveLog interface {
+
4473 OnReceiveLog(message string)
+
4474}
+
4475
+
4476// Receive log message function
+
4477type OnReceiveLogFunc func(message string)
+
4478func (f OnReceiveLogFunc) OnReceiveLog(message string) {
+
4479 f(message)
+
4480}
+
4481
+
4482// Fast Binary Encoding base receiver
+
4483type Receiver struct {
+
4484 // Receiver bytes buffer
+
4485 buffer *Buffer
+
4486 // Logging flag
+
4487 logging bool
+
4488 // Final protocol flag
+
4489 final bool
+
4490
+
4491 // Receive message handler
+
4492 HandlerOnReceive OnReceive
+
4493 // Receive log message handler
+
4494 HandlerOnReceiveLog OnReceiveLog
+
4495}
+
4496
+
4497// Create a new base receiver
+
4498func NewReceiver(buffer *Buffer, final bool) *Receiver {
+
4499 receiver := &Receiver{buffer: buffer, logging: false, final: final}
+
4500 receiver.SetupHandlerOnReceiveFunc(func(fbeType int, buffer []byte) (bool, error) { panic("receive handler is not provided") })
+
4501 receiver.SetupHandlerOnReceiveLogFunc(func(message string) {})
+
4502 return receiver
+
4503}
+
4504
+
4505// Get the bytes buffer
+
4506func (r *Receiver) Buffer() *Buffer { return r.buffer }
+
4507
+
4508// Get the final protocol flag
+
4509func (r *Receiver) Final() bool { return r.final }
+
4510
+
4511// Get the logging flag
+
4512func (r *Receiver) Logging() bool { return r.logging }
+
4513// Set the logging flag
+
4514func (r *Receiver) SetLogging(logging bool) { r.logging = logging }
+
4515
+
4516// Setup handlers
+
4517func (r *Receiver) SetupHandlers(handlers interface{}) {
+
4518 if handler, ok := handlers.(OnReceive); ok {
+
4519 r.SetupHandlerOnReceive(handler)
+
4520 }
+
4521 if handler, ok := handlers.(OnReceiveLog); ok {
+
4522 r.SetupHandlerOnReceiveLog(handler)
+
4523 }
+
4524}
+
4525
+
4526// Setup receive message handler
+
4527func (r *Receiver) SetupHandlerOnReceive(handler OnReceive) { r.HandlerOnReceive = handler }
+
4528// Setup receive message handler function
+
4529func (r *Receiver) SetupHandlerOnReceiveFunc(function func(fbeType int, buffer []byte) (bool, error)) { r.HandlerOnReceive = OnReceiveFunc(function) }
+
4530// Setup receive log message handler
+
4531func (r *Receiver) SetupHandlerOnReceiveLog(handler OnReceiveLog) { r.HandlerOnReceiveLog = handler }
+
4532// Setup receive log message handler function
+
4533func (r *Receiver) SetupHandlerOnReceiveLogFunc(function func(message string)) { r.HandlerOnReceiveLog = OnReceiveLogFunc(function) }
+
4534
+
4535// Reset the receiver buffer
+
4536func (r *Receiver) Reset() { r.buffer.Reset() }
+
4537
+
4538// Receive bytes memory buffer
+
4539func (r *Receiver) Receive(buffer []byte) error {
+
4540 size := len(buffer)
+
4541 if size <= 0 {
+
4542 return nil
+
4543 }
+
4544
+
4545 // Storage buffer
+
4546 offset0 := r.buffer.offset
+
4547 offset1 := r.buffer.size
+
4548 size1 := r.buffer.size
+
4549
+
4550 // Receive buffer
+
4551 offset2 := 0
+
4552 size2 := size
+
4553
+
4554 // While receive buffer is available to handle...
+
4555 for offset2 < size2 {
+
4556 var messageBuffer []byte = nil
+
4557 messageOffset := 0
+
4558 messageSize := 0
+
4559
+
4560 // Try to receive message size
+
4561 messageSizeCopied := false
+
4562 messageSizeFound := false
+
4563 for !messageSizeFound {
+
4564 // Look into the storage buffer
+
4565 if offset0 < size1 {
+
4566 count := min(size1 - offset0, 4)
+
4567 if count == 4 {
+
4568 messageSizeCopied = true
+
4569 messageSizeFound = true
+
4570 messageSize = int(ReadUInt32(r.buffer.data, r.buffer.offset + offset0))
+
4571 offset0 += 4
+
4572 break
+
4573 } else {
+
4574 // Fill remaining data from the receive buffer
+
4575 if offset2 < size2 {
+
4576 count := min(size2 - offset2, 4 - count)
+
4577
+
4578 // Allocate and refresh the storage buffer
+
4579 r.buffer.Allocate(count)
+
4580 size1 += count
+
4581
+
4582 copy(r.buffer.data[offset1:offset1 + count], buffer[offset2:offset2 + count])
+
4583
+
4584 offset1 += count
+
4585 offset2 += count
+
4586 continue
+
4587 } else {
+
4588 break
+
4589 }
+
4590 }
+
4591 }
+
4592
+
4593 // Look into the receive buffer
+
4594 if offset2 < size2 {
+
4595 count := min(size2 - offset2, 4)
+
4596 if count == 4 {
+
4597 messageSizeFound = true
+
4598 messageSize = int(ReadUInt32(buffer, offset2))
+
4599 offset2 += 4
+
4600 break
+
4601 } else {
+
4602 // Allocate and refresh the storage buffer
+
4603 r.buffer.Allocate(count)
+
4604 size1 += count
+
4605
+
4606 copy(r.buffer.data[offset1:offset1 + count], buffer[offset2:offset2 + count])
+
4607 offset1 += count
+
4608 offset2 += count
+
4609 continue
+
4610 }
+
4611 } else {
+
4612 break
+
4613 }
+
4614 }
+
4615
+
4616 if !messageSizeFound {
+
4617 return nil
+
4618 }
+
4619
+
4620 // Check the message full size
+
4621 minSize := 4 + 4 + 4 + 4
+
4622 if r.final {
+
4623 minSize = 4 + 4
+
4624 }
+
4625 if messageSize < minSize {
+
4626 return nil
+
4627 }
+
4628
+
4629 // Try to receive message body
+
4630 messageFound := false
+
4631 for !messageFound {
+
4632 // Look into the storage buffer
+
4633 if offset0 < size1 {
+
4634 count := min(size1 - offset0, messageSize - 4)
+
4635 if count == (messageSize - 4) {
+
4636 messageFound = true
+
4637 messageBuffer = r.buffer.data
+
4638 messageOffset = offset0 - 4
+
4639 offset0 += messageSize - 4
+
4640 break
+
4641 } else {
+
4642 // Fill remaining data from the receive buffer
+
4643 if offset2 < size2 {
+
4644 // Copy message size into the storage buffer
+
4645 if !messageSizeCopied {
+
4646 // Allocate and refresh the storage buffer
+
4647 r.buffer.Allocate(4)
+
4648 size1 += 4
+
4649
+
4650 WriteUInt32(r.buffer.data, r.buffer.offset + offset0, uint32(messageSize))
+
4651 offset0 += 4
+
4652 offset1 += 4
+
4653
+
4654 messageSizeCopied = true
+
4655 }
+
4656
+
4657 count = min(size2 - offset2, messageSize - 4 - count)
+
4658
+
4659 // Allocate and refresh the storage buffer
+
4660 r.buffer.Allocate(count)
+
4661 size1 += count
+
4662
+
4663 copy(r.buffer.data[offset1:offset1 + count], buffer[offset2:offset2 + count])
+
4664 offset1 += count
+
4665 offset2 += count
+
4666 continue
+
4667 } else {
+
4668 break
+
4669 }
+
4670 }
+
4671 }
+
4672
+
4673 // Look into the receive buffer
+
4674 if offset2 < size2 {
+
4675 count := min(size2 - offset2, messageSize - 4)
+
4676 if !messageSizeCopied && (count == (messageSize - 4)) {
+
4677 messageFound = true
+
4678 messageBuffer = buffer
+
4679 messageOffset = offset2 - 4
+
4680 offset2 += messageSize - 4
+
4681 break
+
4682 } else {
+
4683 // Copy message size into the storage buffer
+
4684 if !messageSizeCopied {
+
4685 // Allocate and refresh the storage buffer
+
4686 r.buffer.Allocate(4)
+
4687 size1 += 4
+
4688
+
4689 WriteUInt32(r.buffer.data, r.buffer.offset + offset0, uint32(messageSize))
+
4690 offset0 += 4
+
4691 offset1 += 4
+
4692
+
4693 messageSizeCopied = true
+
4694 }
+
4695
+
4696 // Allocate and refresh the storage buffer
+
4697 r.buffer.Allocate(count)
+
4698 size1 += count
+
4699
+
4700 copy(r.buffer.data[offset1:offset1 + count], buffer[offset2:offset2 + count])
+
4701 offset1 += count
+
4702 offset2 += count
+
4703 continue
+
4704 }
+
4705 } else {
+
4706 break
+
4707 }
+
4708 }
+
4709
+
4710 if !messageFound {
+
4711 // Copy message size into the storage buffer
+
4712 if !messageSizeCopied {
+
4713 // Allocate and refresh the storage buffer
+
4714 r.buffer.Allocate(4)
+
4715 size1 += 4
+
4716
+
4717 WriteUInt32(r.buffer.data, r.buffer.offset + offset0, uint32(messageSize))
+
4718 offset0 += 4
+
4719 offset1 += 4
+
4720
+
4721 messageSizeCopied = true
+
4722 }
+
4723 return nil
+
4724 }
+
4725
+
4726 // Read the message parameters
+
4727 var fbeStructSize = 0
+
4728 var fbeStructType = 0
+
4729 if r.final {
+
4730 fbeStructSize = int(ReadUInt32(messageBuffer, messageOffset))
+
4731 fbeStructType = int(ReadUInt32(messageBuffer, messageOffset + 4))
+
4732 } else {
+
4733 fbeStructOffset := int(ReadUInt32(messageBuffer, messageOffset + 4))
+
4734 fbeStructSize = int(ReadUInt32(messageBuffer, messageOffset + fbeStructOffset))
+
4735 fbeStructType = int(ReadUInt32(messageBuffer, messageOffset + fbeStructOffset+ 4))
+
4736 }
+
4737 _ = fbeStructSize
+
4738
+
4739 // Handle the message
+
4740 if _, err := r.HandlerOnReceive.OnReceive(fbeStructType, messageBuffer[messageOffset:messageOffset + messageSize]); err != nil {
+
4741 return err
+
4742 }
+
4743
+
4744 // Reset the storage buffer
+
4745 r.buffer.Reset()
+
4746
+
4747 // Refresh the storage buffer
+
4748 offset0 = r.buffer.offset
+
4749 offset1 = r.buffer.size
+
4750 size1 = r.buffer.size
+
4751 }
+
4752 return nil
+
4753}
+
4754
+
4755// Receive buffer
+
4756func (r *Receiver) ReceiveBuffer(buffer *Buffer) error {
+
4757 return r.Receive(buffer.data)
+
4758}
+
4759
+
4760// Min utility function
+
4761func min(a, b int) int {
+
4762 if a < b {
+
4763 return a
+
4764 }
+
4765 return b
+
4766}
+
4767)CODE";
+
4768
+
4769 // Prepare code template
+
4770 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
4771
+
4772 Write(code);
+
4773
+
4774 // Generate footer
+
4775 GenerateFooter();
+
4776
+
4777 // Store the file
+
4778 WriteEnd();
+
4779 Store(file);
+
4780}
+
4781
+
4782void GeneratorGo::GenerateImports(const std::shared_ptr<Package>& p)
+
4783{
+
4784 // Generate fbe import
+
4785 WriteLineIndent("import \"errors\"");
+
4786 WriteLineIndent("import \"../fbe\"");
+
4787
+
4788 // Generate packages import
+
4789 if (p->import)
+
4790 for (const auto& import : p->import->imports)
+
4791 WriteLineIndent("import \"../" + *import + "\"");
+
4792
+
4793 // Generate workaround for Go unused imports issue
+
4794 WriteLine();
+
4795 WriteLineIndent("// Workaround for Go unused imports issue");
+
4796 WriteLineIndent("var _ = errors.New");
+
4797 WriteLineIndent("var _ = fbe.Version");
+
4798 if (p->import)
+
4799 for (const auto& import : p->import->imports)
+
4800 WriteLineIndent("var _ = " + *import + ".Version");
+
4801}
+
4802
+
4803void GeneratorGo::GenerateContainers(const std::shared_ptr<Package>& p, const CppCommon::Path& path, bool final)
+
4804{
+
4805 if (p->body)
+
4806 {
+
4807 // Check all structs in the package
+
4808 for (const auto& s : p->body->structs)
+
4809 {
+
4810 if (s->body)
+
4811 {
+
4812 // Check all fields in the struct
+
4813 for (const auto& field : s->body->fields)
+
4814 {
+
4815 if (field->array)
+
4816 {
+
4817 if (final)
+
4818 GenerateFBEFinalModelArray(p, (field->optional ? "Optional" : "") + ConvertTypeFieldName(*field->type), ConvertTypeFieldDeclaration(*field->type, field->optional, final), *field, path);
+
4819 else
+
4820 GenerateFBEFieldModelArray(p, (field->optional ? "Optional" : "") + ConvertTypeFieldName(*field->type), ConvertTypeFieldDeclaration(*field->type, field->optional, final), *field, path);
+
4821 }
+
4822 if (field->vector || field->list)
+
4823 {
+
4824 if (final)
+
4825 GenerateFBEFinalModelVector(p, (field->optional ? "Optional" : "") + ConvertTypeFieldName(*field->type), ConvertTypeFieldDeclaration(*field->type, field->optional, final), *field, path);
+
4826 else
+
4827 GenerateFBEFieldModelVector(p, (field->optional ? "Optional" : "") + ConvertTypeFieldName(*field->type), ConvertTypeFieldDeclaration(*field->type, field->optional, final), *field, path);
+
4828 }
+
4829 if (field->set)
+
4830 {
+
4831 if (final)
+
4832 GenerateFBEFinalModelSet(p, (field->optional ? "Optional" : "") + ConvertTypeFieldName(*field->type), ConvertTypeFieldDeclaration(*field->type, field->optional, final), *field, path);
+
4833 else
+
4834 GenerateFBEFieldModelSet(p, (field->optional ? "Optional" : "") + ConvertTypeFieldName(*field->type), ConvertTypeFieldDeclaration(*field->type, field->optional, final), *field, path);
+
4835 }
+
4836 if (field->map || field->hash)
+
4837 {
+
4838 if (final)
+
4839 GenerateFBEFinalModelMap(p, ConvertTypeFieldName(*field->key), ConvertTypeFieldDeclaration(*field->key, false, final), (field->optional ? "Optional" : "") + ConvertTypeFieldName(*field->type), ConvertTypeFieldDeclaration(*field->type, field->optional, final), *field, path);
+
4840 else
+
4841 GenerateFBEFieldModelMap(p, ConvertTypeFieldName(*field->key), ConvertTypeFieldDeclaration(*field->key, false, final), (field->optional ? "Optional" : "") + ConvertTypeFieldName(*field->type), ConvertTypeFieldDeclaration(*field->type, field->optional, final), *field, path);
+
4842 }
+
4843 if (field->optional)
+
4844 {
+
4845 if (final)
+
4846 GenerateFBEFinalModelOptional(p, ConvertTypeFieldName(*field->type), ConvertTypeFieldDeclaration(*field->type, false, final), *field, path);
+
4847 else
+
4848 GenerateFBEFieldModelOptional(p, ConvertTypeFieldName(*field->type), ConvertTypeFieldDeclaration(*field->type, false, final), *field, path);
+
4849 }
+
4850 }
+
4851 }
+
4852 }
+
4853 }
+
4854}
+
4855
+
4856void GeneratorGo::GeneratePackage(const std::shared_ptr<Package>& p)
+
4857{
+
4858 CppCommon::Path path = CppCommon::Path(_output) / *p->name;
+
4859
+
4860 // Create package path
+
4861 CppCommon::Directory::CreateTree(path);
+
4862
+
4863 // Generate package version
+
4864 GenerateFBEVersion(*p->name, CppCommon::Path(_input).filename().string());
+
4865
+
4866 // Generate namespace
+
4867 if (p->body)
+
4868 {
+
4869 // Generate child enums
+
4870 for (const auto& child_e : p->body->enums)
+
4871 GenerateEnum(p, child_e, path);
+
4872
+
4873 // Generate child flags
+
4874 for (const auto& child_f : p->body->flags)
+
4875 GenerateFlags(p, child_f, path);
+
4876
+
4877 // Generate child structs
+
4878 for (const auto& child_s : p->body->structs)
+
4879 GenerateStruct(p, child_s, path);
+
4880 }
+
4881
+
4882 // Generate containers
+
4883 GenerateContainers(p, path, false);
+
4884 if (Final())
+
4885 GenerateContainers(p, path, true);
+
4886
+
4887 // Generate protocol
+
4888 if (Proto())
+
4889 {
+
4890 // Generate protocol version
+
4891 GenerateProtocolVersion(p, path);
+
4892
+
4893 // Generate sender & receiver
+
4894 GenerateSender(p, path, false);
+
4895 GenerateReceiver(p, path, false);
+
4896 GenerateProxy(p, path, false);
+
4897 if (Final())
+
4898 {
+
4899 GenerateSender(p, path, true);
+
4900 GenerateReceiver(p, path, true);
+
4901 }
+
4902 }
+
4903}
+
4904
+
4905void GeneratorGo::GenerateEnum(const std::shared_ptr<Package>& p, const std::shared_ptr<EnumType>& e, const CppCommon::Path& path)
+
4906{
+
4907 std::string enum_name = ConvertToUpper(*e->name);
+
4908
+
4909 // Generate the output file
+
4910 CppCommon::Path output = path / (enum_name + ".go");
+
4911 WriteBegin();
+
4912
+
4913 // Generate header
+
4914 GenerateHeader(CppCommon::Path(_input).filename().string());
+
4915
+
4916 // Generate package
+
4917 WriteLine();
+
4918 WriteLineIndent("package " + *p->name);
+
4919
+
4920 // Generate imports
+
4921 WriteLine();
+
4922 GenerateImports(p);
+
4923
+
4924 std::string enum_type = (e->base && !e->base->empty()) ? *e->base : "int32";
+
4925
+
4926 // Generate enum key
+
4927 WriteLine();
+
4928 WriteLineIndent("// " + enum_name + " enum key");
+
4929 WriteLineIndent("type " + enum_name + "Key " + ConvertEnumType(enum_type));
+
4930
+
4931 // Generate enum key String() method
+
4932 WriteLine();
+
4933 WriteLineIndent("// Convert " + enum_name + " enum key to string");
+
4934 WriteLineIndent("func (k " + enum_name + "Key) String() string {");
+
4935 Indent(1);
+
4936 WriteLineIndent("return " + enum_name + "(k).String()");
+
4937 Indent(-1);
+
4938 WriteLineIndent("}");
+
4939
+
4940 // Generate enum type
+
4941 WriteLine();
+
4942 WriteLineIndent("// " + enum_name + " enum");
+
4943 WriteLineIndent("type " + enum_name + " " + ConvertEnumType(enum_type));
+
4944
+
4945 // Generate enum body
+
4946 if (e->body)
+
4947 {
+
4948 WriteLine();
+
4949 WriteLineIndent("// " + enum_name + " enum values");
+
4950 WriteLineIndent("//noinspection GoSnakeCaseUsage");
+
4951 WriteLineIndent("const (");
+
4952 Indent(1);
+
4953
+
4954 int index = 0;
+
4955 std::string last = ConvertEnumConstant(enum_name, "int32", "0");
+
4956 for (const auto& value : e->body->values)
+
4957 {
+
4958 WriteIndent(enum_name + "_" + *value->name + " = " + enum_name + "(");
+
4959 if (value->value)
+
4960 {
+
4961 if (value->value->constant && !value->value->constant->empty())
+
4962 {
+
4963 index = 0;
+
4964 last = ConvertEnumConstant(enum_name, enum_type, *value->value->constant);
+
4965 Write(last + " + " + std::to_string(index++));
+
4966 }
+
4967 else if (value->value->reference && !value->value->reference->empty())
+
4968 {
+
4969 index = 0;
+
4970 last = ConvertEnumConstant(enum_name, "", *value->value->reference);
+
4971 Write(last);
+
4972 }
+
4973 }
+
4974 else
+
4975 Write(last + " + " + std::to_string(index++));
+
4976 Write(")");
+
4977 WriteLine();
+
4978 }
+
4979
+
4980 Indent(-1);
+
4981 WriteLineIndent(")");
+
4982 }
+
4983
+
4984 // Generate enum constructor
+
4985 WriteLine();
+
4986 WriteLineIndent("// Create a new " + enum_name + " enum");
+
4987 WriteLineIndent("func New" + enum_name + "() *" + enum_name + " {");
+
4988 Indent(1);
+
4989 WriteLineIndent("return new(" + enum_name + ")");
+
4990 Indent(-1);
+
4991 WriteLineIndent("}");
+
4992
+
4993 // Generate enum constructor from the given value
+
4994 WriteLine();
+
4995 WriteLineIndent("// Create a new " + enum_name + " enum from the given value");
+
4996 WriteLineIndent("func New" + enum_name + "FromValue(value " + ConvertEnumType(enum_type) + ") *" + enum_name + " {");
+
4997 Indent(1);
+
4998 WriteLineIndent("result := " + enum_name + "(value)");
+
4999 WriteLineIndent("return &result");
+
5000 Indent(-1);
+
5001 WriteLineIndent("}");
+
5002
+
5003 // Generate enum Key() method
+
5004 WriteLine();
+
5005 WriteLineIndent("// Get the enum key");
+
5006 WriteLineIndent("func (e " + enum_name + ") Key() " + enum_name + "Key {");
+
5007 Indent(1);
+
5008 WriteLineIndent("return " + enum_name + "Key(e)");
+
5009 Indent(-1);
+
5010 WriteLineIndent("}");
+
5011
+
5012 // Generate enum Optional() method
+
5013 WriteLine();
+
5014 WriteLineIndent("// Convert enum to optional");
+
5015 WriteLineIndent("func (e *" + enum_name + ") Optional() *" + enum_name + " {");
+
5016 Indent(1);
+
5017 WriteLineIndent("return e");
+
5018 Indent(-1);
+
5019 WriteLineIndent("}");
+
5020
+
5021 // Generate enum String() method
+
5022 WriteLine();
+
5023 WriteLineIndent("// Convert enum to string");
+
5024 WriteLineIndent("func (e " + enum_name + ") String() string {");
+
5025 Indent(1);
+
5026 if (e->body && !e->body->values.empty())
+
5027 {
+
5028 for (auto it = e->body->values.begin(); it != e->body->values.end(); ++it)
+
5029 {
+
5030 WriteLineIndent("if e == " + enum_name + "_" + *(*it)->name + " {");
+
5031 Indent(1);
+
5032 WriteLineIndent("return \"" + *(*it)->name + "\"");
+
5033 Indent(-1);
+
5034 WriteLineIndent("}");
+
5035 }
+
5036 WriteLineIndent("return \"<unknown>\"");
+
5037 }
+
5038 else
+
5039 WriteLineIndent("return \"<empty>\"");
+
5040 Indent(-1);
+
5041 WriteLineIndent("}");
+
5042
+
5043 if (JSON())
+
5044 {
+
5045 // Generate enum MarshalJSON() method
+
5046 WriteLine();
+
5047 WriteLineIndent("// Convert enum to JSON");
+
5048 WriteLineIndent("func (e " + enum_name + ") MarshalJSON() ([]byte, error) {");
+
5049 Indent(1);
+
5050 WriteLineIndent("value := " + ConvertEnumType(enum_type) + "(e)");
+
5051 WriteLineIndent("return fbe.Json.Marshal(&value)");
+
5052 Indent(-1);
+
5053 WriteLineIndent("}");
+
5054
+
5055 // Generate enum UnmarshalJSON() method
+
5056 WriteLine();
+
5057 WriteLineIndent("// Convert JSON to enum");
+
5058 WriteLineIndent("func (e *" + enum_name + ") UnmarshalJSON(buffer []byte) error {");
+
5059 Indent(1);
+
5060 WriteLineIndent("var result " + ConvertEnumType(enum_type));
+
5061 WriteLineIndent("err := fbe.Json.Unmarshal(buffer, &result)");
+
5062 WriteLineIndent("if err != nil {");
+
5063 Indent(1);
+
5064 WriteLineIndent("return err");
+
5065 Indent(-1);
+
5066 WriteLineIndent("}");
+
5067 WriteLineIndent("*e = " + enum_name + "(result)");
+
5068 WriteLineIndent("return nil");
+
5069 Indent(-1);
+
5070 WriteLineIndent("}");
+
5071 }
+
5072
+
5073 // Generate footer
+
5074 GenerateFooter();
+
5075
+
5076 // Store the output file
+
5077 WriteEnd();
+
5078 Store(output);
+
5079
+
5080 // Generate enum field model
+
5081 GenerateFBEFieldModelEnumFlags(*p->name, enum_name, enum_type);
+
5082
+
5083 // Generate enum final model
+
5084 if (Final())
+
5085 GenerateFBEFinalModelEnumFlags(*p->name, enum_name, enum_type);
+
5086}
+
5087
+
5088void GeneratorGo::GenerateFlags(const std::shared_ptr<Package>& p, const std::shared_ptr<FlagsType>& f, const CppCommon::Path& path)
+
5089{
+
5090 std::string flags_name = ConvertToUpper(*f->name);
+
5091
+
5092 // Generate the output file
+
5093 CppCommon::Path output = path / (flags_name + ".go");
+
5094 WriteBegin();
+
5095
+
5096 // Generate header
+
5097 GenerateHeader(CppCommon::Path(_input).filename().string());
+
5098
+
5099 // Generate package
+
5100 WriteLine();
+
5101 WriteLineIndent("package " + *p->name);
+
5102
+
5103 // Generate imports
+
5104 WriteLine();
+
5105 WriteLineIndent("import \"strings\"");
+
5106 GenerateImports(p);
+
5107
+
5108 std::string flags_type = (f->base && !f->base->empty()) ? *f->base : "int32";
+
5109
+
5110 // Generate flags key
+
5111 WriteLine();
+
5112 WriteLineIndent("// " + flags_name + " flags key");
+
5113 WriteLineIndent("type " + flags_name + "Key " + ConvertEnumType(flags_type));
+
5114
+
5115 // Generate flags key String() method
+
5116 WriteLine();
+
5117 WriteLineIndent("// Convert " + flags_name + " flags key to string");
+
5118 WriteLineIndent("func (k " + flags_name + "Key) String() string {");
+
5119 Indent(1);
+
5120 WriteLineIndent("return " + flags_name + "(k).String()");
+
5121 Indent(-1);
+
5122 WriteLineIndent("}");
+
5123
+
5124 // Generate flags type
+
5125 WriteLine();
+
5126 WriteLineIndent("// " + flags_name + " flags");
+
5127 WriteLineIndent("type " + flags_name + " " + ConvertEnumType(flags_type));
+
5128
+
5129 // Generate flags body
+
5130 if (f->body)
+
5131 {
+
5132 WriteLine();
+
5133 WriteLineIndent("// " + flags_name + " flags values");
+
5134 WriteLineIndent("//noinspection GoSnakeCaseUsage");
+
5135 WriteLineIndent("const (");
+
5136 Indent(1);
+
5137
+
5138 for (const auto& value : f->body->values)
+
5139 {
+
5140 WriteIndent(flags_name + "_" + *value->name + " = " + flags_name + "(");
+
5141 if (value->value)
+
5142 {
+
5143 if (value->value->constant && !value->value->constant->empty())
+
5144 Write(ConvertEnumConstant(flags_name, flags_type, *value->value->constant));
+
5145 else if (value->value->reference && !value->value->reference->empty())
+
5146 Write(ConvertEnumConstant(flags_name, "", *value->value->reference));
+
5147 }
+
5148 Write(")");
+
5149 WriteLine();
+
5150 }
+
5151
+
5152 Indent(-1);
+
5153 WriteLineIndent(")");
+
5154 }
+
5155
+
5156 // Generate flags constructor
+
5157 WriteLine();
+
5158 WriteLineIndent("// Create a new " + flags_name + " flags");
+
5159 WriteLineIndent("func New" + flags_name + "() *" + flags_name + " {");
+
5160 Indent(1);
+
5161 WriteLineIndent("return new(" + flags_name + ")");
+
5162 Indent(-1);
+
5163 WriteLineIndent("}");
+
5164
+
5165 // Generate flags constructor from the given flags
+
5166 WriteLine();
+
5167 WriteLineIndent("// Create a new " + flags_name + " flags from the given flags");
+
5168 WriteLineIndent("func New" + flags_name + "FromValue(flags " + ConvertEnumType(flags_type) + ") *" + flags_name + " {");
+
5169 Indent(1);
+
5170 WriteLineIndent("result := " + flags_name + "(flags)");
+
5171 WriteLineIndent("return &result");
+
5172 Indent(-1);
+
5173 WriteLineIndent("}");
+
5174
+
5175 // Generate flags HasFlags() method
+
5176 WriteLine();
+
5177 WriteLineIndent("// Is flags set?");
+
5178 WriteLineIndent("func (f " + flags_name + ") HasFlags(flags " + flags_name + ") bool {");
+
5179 Indent(1);
+
5180 WriteLineIndent("return ((f & flags) != 0) && ((f & flags) == flags)");
+
5181 Indent(-1);
+
5182 WriteLineIndent("}");
+
5183
+
5184 // Generate flags SetFlags() method
+
5185 WriteLine();
+
5186 WriteLineIndent("// Set flags");
+
5187 WriteLineIndent("func (f *" + flags_name + ") SetFlags(flags " + flags_name + ") *" + flags_name + " {");
+
5188 Indent(1);
+
5189 WriteLineIndent("*f |= flags");
+
5190 WriteLineIndent("return f");
+
5191 Indent(-1);
+
5192 WriteLineIndent("}");
+
5193
+
5194 // Generate flags RemoveFlags() method
+
5195 WriteLine();
+
5196 WriteLineIndent("// Remove flags");
+
5197 WriteLineIndent("func (f *" + flags_name + ") RemoveFlags(flags " + flags_name + ") *" + flags_name + " {");
+
5198 Indent(1);
+
5199 WriteLineIndent("*f &^= flags");
+
5200 WriteLineIndent("return f");
+
5201 Indent(-1);
+
5202 WriteLineIndent("}");
+
5203
+
5204 // Generate flags Key() method
+
5205 WriteLine();
+
5206 WriteLineIndent("// Get the flags key");
+
5207 WriteLineIndent("func (f " + flags_name + ") Key() " + flags_name + "Key {");
+
5208 Indent(1);
+
5209 WriteLineIndent("return " + flags_name + "Key(f)");
+
5210 Indent(-1);
+
5211 WriteLineIndent("}");
+
5212
+
5213 // Generate flags Optional() method
+
5214 WriteLine();
+
5215 WriteLineIndent("// Convert flags to optional");
+
5216 WriteLineIndent("func (f *" + flags_name + ") Optional() *" + flags_name + " {");
+
5217 Indent(1);
+
5218 WriteLineIndent("return f");
+
5219 Indent(-1);
+
5220 WriteLineIndent("}");
+
5221
+
5222 // Generate flags String() method
+
5223 WriteLine();
+
5224 WriteLineIndent("// Convert flags to string");
+
5225 WriteLineIndent("//noinspection GoBoolExpressions");
+
5226 WriteLineIndent("func (f " + flags_name + ") String() string {");
+
5227 Indent(1);
+
5228 WriteLineIndent("var sb strings.Builder");
+
5229 if (f->body && !f->body->values.empty())
+
5230 {
+
5231 WriteLineIndent("first := true");
+
5232 for (auto it = f->body->values.begin(); it != f->body->values.end(); ++it)
+
5233 {
+
5234 std::string flag = flags_name + "_" + *(*it)->name;
+
5235 WriteLineIndent("if ((f & " + flag + ") != 0) && ((f & " + flag + ") == " + flag + ") {");
+
5236 Indent(1);
+
5237 WriteLineIndent("if first {");
+
5238 Indent(1);
+
5239 WriteLineIndent("first = false");
+
5240 Indent(-1);
+
5241 WriteLineIndent("} else {");
+
5242 Indent(1);
+
5243 WriteLineIndent("sb.WriteRune('|')");
+
5244 Indent(-1);
+
5245 WriteLineIndent("}");
+
5246 WriteLineIndent("sb.WriteString(\"" + *(*it)->name + "\")");
+
5247 Indent(-1);
+
5248 WriteLineIndent("}");
+
5249 }
+
5250 }
+
5251 WriteLineIndent("return sb.String()");
+
5252 Indent(-1);
+
5253 WriteLineIndent("}");
+
5254
+
5255 if (JSON())
+
5256 {
+
5257 // Generate flags MarshalJSON() method
+
5258 WriteLine();
+
5259 WriteLineIndent("// Convert flags to JSON");
+
5260 WriteLineIndent("func (f " + flags_name + ") MarshalJSON() ([]byte, error) {");
+
5261 Indent(1);
+
5262 WriteLineIndent("value := " + ConvertEnumType(flags_type) + "(f)");
+
5263 WriteLineIndent("return fbe.Json.Marshal(&value)");
+
5264 Indent(-1);
+
5265 WriteLineIndent("}");
+
5266
+
5267 // Generate flags UnmarshalJSON() method
+
5268 WriteLine();
+
5269 WriteLineIndent("// Convert JSON to flags");
+
5270 WriteLineIndent("func (f *" + flags_name + ") UnmarshalJSON(buffer []byte) error {");
+
5271 Indent(1);
+
5272 WriteLineIndent("var result " + ConvertEnumType(flags_type));
+
5273 WriteLineIndent("err := fbe.Json.Unmarshal(buffer, &result)");
+
5274 WriteLineIndent("if err != nil {");
+
5275 Indent(1);
+
5276 WriteLineIndent("return err");
+
5277 Indent(-1);
+
5278 WriteLineIndent("}");
+
5279 WriteLineIndent("*f = " + flags_name + "(result)");
+
5280 WriteLineIndent("return nil");
+
5281 Indent(-1);
+
5282 WriteLineIndent("}");
+
5283 }
+
5284
+
5285 // Generate footer
+
5286 GenerateFooter();
+
5287
+
5288 // Store the output file
+
5289 WriteEnd();
+
5290 Store(output);
+
5291
+
5292 // Generate flags field model
+
5293 GenerateFBEFieldModelEnumFlags(*p->name, flags_name, flags_type);
+
5294
+
5295 // Generate flags final model
+
5296 if (Final())
+
5297 GenerateFBEFinalModelEnumFlags(*p->name, flags_name, flags_type);
+
5298}
+
5299
+
5300void GeneratorGo::GenerateStruct(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s, const CppCommon::Path& path)
+
5301{
+
5302 std::string struct_name = ConvertToUpper(*s->name);
+
5303
+
5304 // Generate the output file
+
5305 CppCommon::Path output = path / (struct_name + ".go");
+
5306 WriteBegin();
+
5307
+
5308 // Generate header
+
5309 GenerateHeader(CppCommon::Path(_input).filename().string());
+
5310
+
5311 // Generate package
+
5312 WriteLine();
+
5313 WriteLineIndent("package " + *p->name);
+
5314
+
5315 // Generate imports
+
5316 WriteLine();
+
5317 WriteLineIndent("import \"fmt\"");
+
5318 WriteLineIndent("import \"strconv\"");
+
5319 WriteLineIndent("import \"strings\"");
+
5320 GenerateImports(p);
+
5321
+
5322 // Generate workaround for Go unused imports issue
+
5323 WriteLine();
+
5324 WriteLineIndent("// Workaround for Go unused imports issue");
+
5325 WriteLineIndent("var _ = fmt.Print");
+
5326 WriteLineIndent("var _ = strconv.FormatInt");
+
5327
+
5328 std::string base_type = (s->base && !s->base->empty()) ? ConvertTypeName(*s->base, false) : "";
+
5329
+
5330 // Generate struct key
+
5331 WriteLine();
+
5332 WriteLineIndent("// " + struct_name + " key");
+
5333 WriteLineIndent("type " + struct_name + "Key struct {");
+
5334 Indent(1);
+
5335 if (!base_type.empty())
+
5336 WriteLineIndent(base_type + "Key");
+
5337 if (s->body)
+
5338 for (const auto& field : s->body->fields)
+
5339 if (field->keys)
+
5340 WriteLineIndent(ConvertToUpper(*field->name) + " " + ConvertTypeName(*field));
+
5341 Indent(-1);
+
5342 WriteLineIndent("}");
+
5343
+
5344 // Generate struct key String() method
+
5345 WriteLine();
+
5346 WriteLineIndent("// Convert " + struct_name + " flags key to string");
+
5347 WriteLineIndent("func (k *" + struct_name + "Key) String() string {");
+
5348 Indent(1);
+
5349 WriteLineIndent("var sb strings.Builder");
+
5350 WriteLineIndent("sb.WriteString(\"" + *s->name + "Key(\")");
+
5351 bool first = true;
+
5352 if (!base_type.empty())
+
5353 {
+
5354 WriteLineIndent("sb.WriteString(k." + ConvertBaseName(base_type) + "Key.String())");
+
5355 first = false;
+
5356 }
+
5357 if (s->body)
+
5358 {
+
5359 for (const auto& field : s->body->fields)
+
5360 {
+
5361 if (field->keys)
+
5362 {
+
5363 WriteLineIndent("sb.WriteString(\"" + std::string(first ? "" : ",") + *field->name + "=\")");
+
5364 if (field->attributes && field->attributes->hidden)
+
5365 WriteLineIndent("sb.WriteString(\"***\")");
+
5366 else if (field->array)
+
5367 {
+
5368 WriteLineIndent("if true {");
+
5369 Indent(1);
+
5370 WriteLineIndent("first := true");
+
5371 WriteLineIndent("sb.WriteString(\"[\" + strconv.FormatInt(int64(len(k." + ConvertToUpper(*field->name) + ")), 10) + \"][\")");
+
5372 WriteLineIndent("for _, v := range k." + ConvertToUpper(*field->name) + " {");
+
5373 Indent(1);
+
5374 WriteOutputStreamValue(*field->type, "v", field->optional, true);
+
5375 WriteLineIndent("first = false");
+
5376 Indent(-1);
+
5377 WriteLineIndent("}");
+
5378 WriteLineIndent("sb.WriteString(\"]\")");
+
5379 Indent(-1);
+
5380 WriteLineIndent("} else {");
+
5381 Indent(1);
+
5382 WriteLineIndent("sb.WriteString(\"" + std::string(first ? "" : ",") + *field->name + "=[0][]\")");
+
5383 Indent(-1);
+
5384 WriteLineIndent("}");
+
5385 }
+
5386 else if (field->vector)
+
5387 {
+
5388 WriteLineIndent("if k." + ConvertToUpper(*field->name) + " != nil {");
+
5389 Indent(1);
+
5390 WriteLineIndent("first := true");
+
5391 WriteLineIndent("sb.WriteString(\"[\" + strconv.FormatInt(int64(len(k." + ConvertToUpper(*field->name) + ")), 10) + \"][\")");
+
5392 WriteLineIndent("for _, v := range k." + ConvertToUpper(*field->name) + " {");
+
5393 Indent(1);
+
5394 WriteOutputStreamValue(*field->type, "v", field->optional, true);
+
5395 WriteLineIndent("first = false");
+
5396 Indent(-1);
+
5397 WriteLineIndent("}");
+
5398 WriteLineIndent("sb.WriteString(\"]\")");
+
5399 Indent(-1);
+
5400 WriteLineIndent("} else {");
+
5401 Indent(1);
+
5402 WriteLineIndent("sb.WriteString(\"" + std::string(first ? "" : ",") + *field->name + "=[0][]\")");
+
5403 Indent(-1);
+
5404 WriteLineIndent("}");
+
5405 }
+
5406 else if (field->list)
+
5407 {
+
5408 WriteLineIndent("if k." + ConvertToUpper(*field->name) + " != nil {");
+
5409 Indent(1);
+
5410 WriteLineIndent("first := true");
+
5411 WriteLineIndent("sb.WriteString(\"[\" + strconv.FormatInt(int64(len(k." + ConvertToUpper(*field->name) + ")), 10) + \"]<\")");
+
5412 WriteLineIndent("for _, v := range k." + ConvertToUpper(*field->name) + " {");
+
5413 Indent(1);
+
5414 WriteOutputStreamValue(*field->type, "v", field->optional, true);
+
5415 WriteLineIndent("first = false");
+
5416 Indent(-1);
+
5417 WriteLineIndent("}");
+
5418 WriteLineIndent("sb.WriteString(\">\")");
+
5419 Indent(-1);
+
5420 WriteLineIndent("} else {");
+
5421 Indent(1);
+
5422 WriteLineIndent("sb.WriteString(\"" + std::string(first ? "" : ",") + *field->name + "=[0]<>\")");
+
5423 Indent(-1);
+
5424 WriteLineIndent("}");
+
5425 }
+
5426 else if (field->set)
+
5427 {
+
5428 WriteLineIndent("if k." + ConvertToUpper(*field->name) + " != nil {");
+
5429 Indent(1);
+
5430 WriteLineIndent("first := true");
+
5431 WriteLineIndent("sb.WriteString(\"[\" + strconv.FormatInt(int64(k." + ConvertToUpper(*field->name) + ".Size()), 10) + \"]{\")");
+
5432 WriteLineIndent("for _, v := range k." + ConvertToUpper(*field->name) + " {");
+
5433 Indent(1);
+
5434 WriteOutputStreamValue(*field->type, "v", field->optional, true);
+
5435 WriteLineIndent("first = false");
+
5436 Indent(-1);
+
5437 WriteLineIndent("}");
+
5438 WriteLineIndent("sb.WriteString(\"}\")");
+
5439 Indent(-1);
+
5440 WriteLineIndent("} else {");
+
5441 Indent(1);
+
5442 WriteLineIndent("sb.WriteString(\"" + std::string(first ? "" : ",") + *field->name + "=[0]{}\")");
+
5443 Indent(-1);
+
5444 WriteLineIndent("}");
+
5445 }
+
5446 else if (field->map)
+
5447 {
+
5448 WriteLineIndent("if k." + ConvertToUpper(*field->name) + " != nil {");
+
5449 Indent(1);
+
5450 WriteLineIndent("first := true");
+
5451 WriteLineIndent("sb.WriteString(\"[\" + strconv.FormatInt(int64(len(k." + ConvertToUpper(*field->name) + ")), 10) + \"]<{\")");
+
5452 WriteLineIndent("for " + std::string(IsGoType(*field->key) ? "k" : "_") + ", v := range k." + ConvertToUpper(*field->name) + " {");
+
5453 Indent(1);
+
5454 WriteOutputStreamValue(*field->key, (IsGoType(*field->key) ? "k" : "v.Key"), false, true);
+
5455 WriteLineIndent("sb.WriteString(\"->\")");
+
5456 WriteOutputStreamValue(*field->type, (IsGoType(*field->key) ? "v" : "v.Value"), field->optional, false);
+
5457 WriteLineIndent("first = false");
+
5458 Indent(-1);
+
5459 WriteLineIndent("}");
+
5460 WriteLineIndent("sb.WriteString(\"}>\")");
+
5461 Indent(-1);
+
5462 WriteLineIndent("} else {");
+
5463 Indent(1);
+
5464 WriteLineIndent("sb.WriteString(\"" + std::string(first ? "" : ",") + *field->name + "=[0]<{}>\")");
+
5465 Indent(-1);
+
5466 WriteLineIndent("}");
+
5467 }
+
5468 else if (field->hash)
+
5469 {
+
5470 WriteLineIndent("if k." + ConvertToUpper(*field->name) + " != nil {");
+
5471 Indent(1);
+
5472 WriteLineIndent("first := true");
+
5473 WriteLineIndent("sb.WriteString(\"[\" + strconv.FormatInt(int64(len(k." + ConvertToUpper(*field->name) + ")), 10) + \"][{\")");
+
5474 WriteLineIndent("for " + std::string(IsGoType(*field->key) ? "k" : "_") + ", v := range k." + ConvertToUpper(*field->name) + " {");
+
5475 Indent(1);
+
5476 WriteOutputStreamValue(*field->key, (IsGoType(*field->key) ? "k" : "v.Key"), false, true);
+
5477 WriteLineIndent("sb.WriteString(\"->\")");
+
5478 WriteOutputStreamValue(*field->type, (IsGoType(*field->key) ? "v" : "v.Value"), field->optional, false);
+
5479 WriteLineIndent("first = false");
+
5480 Indent(-1);
+
5481 WriteLineIndent("}");
+
5482 WriteLineIndent("sb.WriteString(\"}]\")");
+
5483 Indent(-1);
+
5484 WriteLineIndent("} else {");
+
5485 Indent(1);
+
5486 WriteLineIndent("sb.WriteString(\"" + std::string(first ? "" : ",") + *field->name + "=[0][{}]\")");
+
5487 Indent(-1);
+
5488 WriteLineIndent("}");
+
5489 }
+
5490 else
+
5491 WriteOutputStreamValue(*field->type, "k." + ConvertToUpper(*field->name), field->optional, false);
+
5492 first = false;
+
5493 }
+
5494 }
+
5495 }
+
5496 WriteLineIndent("sb.WriteString(\")\")");
+
5497 WriteLineIndent("return sb.String()");
+
5498 Indent(-1);
+
5499 WriteLineIndent("}");
+
5500
+
5501 // Generate struct body
+
5502 WriteLine();
+
5503 WriteLineIndent("// " + struct_name + " struct");
+
5504 WriteLineIndent("type " + struct_name + " struct {");
+
5505 Indent(1);
+
5506 if (!base_type.empty())
+
5507 WriteLineIndent("*" + base_type);
+
5508 if (s->body)
+
5509 for (const auto& field : s->body->fields)
+
5510 WriteLineIndent(ConvertToUpper(*field->name) + " " + ConvertTypeName(*field) + " `json:\"" + *field->name + "\"`");
+
5511 Indent(-1);
+
5512 WriteLineIndent("}");
+
5513
+
5514 // Generate struct constructor
+
5515 WriteLine();
+
5516 WriteLineIndent("// Create a new " + struct_name + " struct");
+
5517 WriteLineIndent("func New" + struct_name + "() *" + struct_name + " {");
+
5518 Indent(1);
+
5519 WriteLineIndent("return &" + struct_name + "{");
+
5520 Indent(1);
+
5521 if (!base_type.empty())
+
5522 WriteLineIndent(ConvertBaseName(base_type) + ": " + ConvertNewName(base_type) + "(),");
+
5523 if (s->body)
+
5524 {
+
5525 for (const auto& field : s->body->fields)
+
5526 {
+
5527 WriteIndent(ConvertToUpper(*field->name) + ": ");
+
5528 if (field->value)
+
5529 Write(ConvertConstant(*field->type, *field->value, field->optional));
+
5530 else
+
5531 Write(ConvertDefault(*field));
+
5532 WriteLine(",");
+
5533 }
+
5534 }
+
5535 Indent(-1);
+
5536 WriteLineIndent("}");
+
5537 Indent(-1);
+
5538 WriteLineIndent("}");
+
5539
+
5540 // Generate struct constructor from the given field values
+
5541 WriteLine();
+
5542 WriteLineIndent("// Create a new " + struct_name + " struct from the given field values");
+
5543 WriteIndent("func New" + struct_name + "FromFieldValues(");
+
5544 first = true;
+
5545 if (!base_type.empty())
+
5546 {
+
5547 Write("Parent *" + base_type);
+
5548 first = false;
+
5549 }
+
5550 if (s->body)
+
5551 {
+
5552 for (const auto& field : s->body->fields)
+
5553 {
+
5554 Write(std::string(first ? "" : ", ") + ConvertToUpper(*field->name) + " " + ConvertTypeName(*field));
+
5555 first = false;
+
5556 }
+
5557 }
+
5558 WriteLine(") *" + struct_name + " {");
+
5559 Indent(1);
+
5560 WriteIndent("return &" + struct_name + "{");
+
5561 first = true;
+
5562 if (!base_type.empty())
+
5563 {
+
5564 Write("Parent");
+
5565 first = false;
+
5566 }
+
5567 if (s->body)
+
5568 {
+
5569 for (const auto& field : s->body->fields)
+
5570 {
+
5571 Write(std::string(first ? "" : ", ") + ConvertToUpper(*field->name));
+
5572 first = false;
+
5573 }
+
5574 }
+
5575 WriteLine("}");
+
5576 Indent(-1);
+
5577 WriteLineIndent("}");
+
5578
+
5579 if (JSON())
+
5580 {
+
5581 // Generate struct JSON constructor
+
5582 WriteLine();
+
5583 WriteLineIndent("// Create a new " + struct_name + " struct from JSON");
+
5584 WriteLineIndent("func New" + struct_name + "FromJSON(buffer []byte) (*" + struct_name + ", error) {");
+
5585 Indent(1);
+
5586 WriteLineIndent("result := *New" + struct_name + "()");
+
5587 WriteLineIndent("err := fbe.Json.Unmarshal(buffer, &result)");
+
5588 WriteLineIndent("if err != nil {");
+
5589 Indent(1);
+
5590 WriteLineIndent("return nil, err");
+
5591 Indent(-1);
+
5592 WriteLineIndent("}");
+
5593 WriteLineIndent("return &result, nil");
+
5594 Indent(-1);
+
5595 WriteLineIndent("}");
+
5596 }
+
5597
+
5598 // Generate struct Copy() method
+
5599 WriteLine();
+
5600 WriteLineIndent("// Struct shallow copy");
+
5601 WriteLineIndent("func (s *" + struct_name + ") Copy() *" + struct_name + " {");
+
5602 Indent(1);
+
5603 WriteLineIndent("var result = *s");
+
5604 WriteLineIndent("return &result");
+
5605 Indent(-1);
+
5606 WriteLineIndent("}");
+
5607
+
5608 // Generate struct Clone() method
+
5609 WriteLine();
+
5610 WriteLineIndent("// Struct deep clone");
+
5611 WriteLineIndent("func (s *" + struct_name + ") Clone() *" + struct_name + " {");
+
5612 Indent(1);
+
5613 WriteLineIndent("// Serialize the struct to the FBE stream");
+
5614 WriteLineIndent("writer := New" + struct_name + "Model(fbe.NewEmptyBuffer())");
+
5615 WriteLineIndent("_, _ = writer.Serialize(s)");
+
5616 WriteLine();
+
5617 WriteLineIndent("// Deserialize the struct from the FBE stream");
+
5618 WriteLineIndent("reader := New" + struct_name + "Model(writer.Buffer())");
+
5619 WriteLineIndent("result, _, _ := reader.Deserialize()");
+
5620 WriteLineIndent("return result");
+
5621 Indent(-1);
+
5622 WriteLineIndent("}");
+
5623
+
5624 // Generate struct Key() method
+
5625 WriteLine();
+
5626 WriteLineIndent("// Get the struct key");
+
5627 WriteLineIndent("func (s *" + struct_name + ") Key() " + struct_name + "Key {");
+
5628 Indent(1);
+
5629 WriteLineIndent("return " + struct_name + "Key{");
+
5630 Indent(1);
+
5631 if (!base_type.empty())
+
5632 WriteLineIndent(ConvertBaseName(base_type) + "Key: s." + ConvertBaseName(base_type) + ".Key(),");
+
5633 if (s->body)
+
5634 for (const auto& field : s->body->fields)
+
5635 if (field->keys)
+
5636 WriteLineIndent(ConvertToUpper(*field->name) + ": s." + ConvertToUpper(*field->name) + ",");
+
5637 Indent(-1);
+
5638 WriteLineIndent("}");
+
5639 Indent(-1);
+
5640 WriteLineIndent("}");
+
5641
+
5642 // Generate struct Optional() method
+
5643 WriteLine();
+
5644 WriteLineIndent("// Convert struct to optional");
+
5645 WriteLineIndent("func (s *" + struct_name + ") Optional() *" + struct_name + " {");
+
5646 Indent(1);
+
5647 WriteLineIndent("return s");
+
5648 Indent(-1);
+
5649 WriteLineIndent("}");
+
5650
+
5651 // Generate struct FBE type property
+
5652 WriteLine();
+
5653 WriteLineIndent("// Get the FBE type");
+
5654 if (s->base && !s->base->empty() && (s->type == 0))
+
5655 WriteLineIndent("func (s *" + struct_name + ") FBEType() int { return s." + ConvertBaseName(base_type) + ".FBEType() }");
+
5656 else
+
5657 WriteLineIndent("func (s *" + struct_name + ") FBEType() int { return " + std::to_string(s->type) + " }");
+
5658
+
5659 // Generate struct String() method
+
5660 WriteLine();
+
5661 WriteLineIndent("// Convert struct to string");
+
5662 WriteLineIndent("func (s *" + struct_name + ") String() string {");
+
5663 Indent(1);
+
5664 WriteLineIndent("var sb strings.Builder");
+
5665 WriteLineIndent("sb.WriteString(\"" + *s->name + "(\")");
+
5666 first = true;
+
5667 if (!base_type.empty())
+
5668 {
+
5669 WriteLineIndent("sb.WriteString(s." + ConvertBaseName(base_type) + ".String())");
+
5670 first = false;
+
5671 }
+
5672 if (s->body)
+
5673 {
+
5674 for (const auto& field : s->body->fields)
+
5675 {
+
5676 WriteLineIndent("sb.WriteString(\"" + std::string(first ? "" : ",") + *field->name + "=\")");
+
5677 if (field->attributes && field->attributes->hidden)
+
5678 WriteLineIndent("sb.WriteString(\"***\")");
+
5679 else if (field->array)
+
5680 {
+
5681 WriteLineIndent("if true {");
+
5682 Indent(1);
+
5683 WriteLineIndent("first := true");
+
5684 WriteLineIndent("sb.WriteString(\"[\" + strconv.FormatInt(int64(len(s." + ConvertToUpper(*field->name) + ")), 10) + \"][\")");
+
5685 WriteLineIndent("for _, v := range s." + ConvertToUpper(*field->name) + " {");
+
5686 Indent(1);
+
5687 WriteOutputStreamValue(*field->type, "v", field->optional, true);
+
5688 WriteLineIndent("first = false");
+
5689 Indent(-1);
+
5690 WriteLineIndent("}");
+
5691 WriteLineIndent("sb.WriteString(\"]\")");
+
5692 Indent(-1);
+
5693 WriteLineIndent("} else {");
+
5694 Indent(1);
+
5695 WriteLineIndent("sb.WriteString(\"" + std::string(first ? "" : ",") + *field->name + "=[0][]\")");
+
5696 Indent(-1);
+
5697 WriteLineIndent("}");
+
5698 }
+
5699 else if (field->vector)
+
5700 {
+
5701 WriteLineIndent("if s." + ConvertToUpper(*field->name) + " != nil {");
+
5702 Indent(1);
+
5703 WriteLineIndent("first := true");
+
5704 WriteLineIndent("sb.WriteString(\"[\" + strconv.FormatInt(int64(len(s." + ConvertToUpper(*field->name) + ")), 10) + \"][\")");
+
5705 WriteLineIndent("for _, v := range s." + ConvertToUpper(*field->name) + " {");
+
5706 Indent(1);
+
5707 WriteOutputStreamValue(*field->type, "v", field->optional, true);
+
5708 WriteLineIndent("first = false");
+
5709 Indent(-1);
+
5710 WriteLineIndent("}");
+
5711 WriteLineIndent("sb.WriteString(\"]\")");
+
5712 Indent(-1);
+
5713 WriteLineIndent("} else {");
+
5714 Indent(1);
+
5715 WriteLineIndent("sb.WriteString(\"" + std::string(first ? "" : ",") + *field->name + "=[0][]\")");
+
5716 Indent(-1);
+
5717 WriteLineIndent("}");
+
5718 }
+
5719 else if (field->list)
+
5720 {
+
5721 WriteLineIndent("if s." + ConvertToUpper(*field->name) + " != nil {");
+
5722 Indent(1);
+
5723 WriteLineIndent("first := true");
+
5724 WriteLineIndent("sb.WriteString(\"[\" + strconv.FormatInt(int64(len(s." + ConvertToUpper(*field->name) + ")), 10) + \"]<\")");
+
5725 WriteLineIndent("for _, v := range s." + ConvertToUpper(*field->name) + " {");
+
5726 Indent(1);
+
5727 WriteOutputStreamValue(*field->type, "v", field->optional, true);
+
5728 WriteLineIndent("first = false");
+
5729 Indent(-1);
+
5730 WriteLineIndent("}");
+
5731 WriteLineIndent("sb.WriteString(\">\")");
+
5732 Indent(-1);
+
5733 WriteLineIndent("} else {");
+
5734 Indent(1);
+
5735 WriteLineIndent("sb.WriteString(\"" + std::string(first ? "" : ",") + *field->name + "=[0]<>\")");
+
5736 Indent(-1);
+
5737 WriteLineIndent("}");
+
5738 }
+
5739 else if (field->set)
+
5740 {
+
5741 WriteLineIndent("if s." + ConvertToUpper(*field->name) + " != nil {");
+
5742 Indent(1);
+
5743 WriteLineIndent("first := true");
+
5744 WriteLineIndent("sb.WriteString(\"[\" + strconv.FormatInt(int64(s." + ConvertToUpper(*field->name) + ".Size()), 10) + \"]{\")");
+
5745 WriteLineIndent("for _, v := range s." + ConvertToUpper(*field->name) + " {");
+
5746 Indent(1);
+
5747 WriteOutputStreamValue(*field->type, "v", field->optional, true);
+
5748 WriteLineIndent("first = false");
+
5749 Indent(-1);
+
5750 WriteLineIndent("}");
+
5751 WriteLineIndent("sb.WriteString(\"}\")");
+
5752 Indent(-1);
+
5753 WriteLineIndent("} else {");
+
5754 Indent(1);
+
5755 WriteLineIndent("sb.WriteString(\"" + std::string(first ? "" : ",") + *field->name + "=[0]{}\")");
+
5756 Indent(-1);
+
5757 WriteLineIndent("}");
+
5758 }
+
5759 else if (field->map)
+
5760 {
+
5761 WriteLineIndent("if s." + ConvertToUpper(*field->name) + " != nil {");
+
5762 Indent(1);
+
5763 WriteLineIndent("first := true");
+
5764 WriteLineIndent("sb.WriteString(\"[\" + strconv.FormatInt(int64(len(s." + ConvertToUpper(*field->name) + ")), 10) + \"]<{\")");
+
5765 WriteLineIndent("for " + std::string(IsGoType(*field->key) ? "k" : "_") + ", v := range s." + ConvertToUpper(*field->name) + " {");
+
5766 Indent(1);
+
5767 WriteOutputStreamValue(*field->key, (IsGoType(*field->key) ? "k" : "v.Key"), false, true);
+
5768 WriteLineIndent("sb.WriteString(\"->\")");
+
5769 WriteOutputStreamValue(*field->type, (IsGoType(*field->key) ? "v" : "v.Value"), field->optional, false);
+
5770 WriteLineIndent("first = false");
+
5771 Indent(-1);
+
5772 WriteLineIndent("}");
+
5773 WriteLineIndent("sb.WriteString(\"}>\")");
+
5774 Indent(-1);
+
5775 WriteLineIndent("} else {");
+
5776 Indent(1);
+
5777 WriteLineIndent("sb.WriteString(\"" + std::string(first ? "" : ",") + *field->name + "=[0]<{}>\")");
+
5778 Indent(-1);
+
5779 WriteLineIndent("}");
+
5780 }
+
5781 else if (field->hash)
+
5782 {
+
5783 WriteLineIndent("if s." + ConvertToUpper(*field->name) + " != nil {");
+
5784 Indent(1);
+
5785 WriteLineIndent("first := true");
+
5786 WriteLineIndent("sb.WriteString(\"[\" + strconv.FormatInt(int64(len(s." + ConvertToUpper(*field->name) + ")), 10) + \"][{\")");
+
5787 WriteLineIndent("for " + std::string(IsGoType(*field->key) ? "k" : "_") + ", v := range s." + ConvertToUpper(*field->name) + " {");
+
5788 Indent(1);
+
5789 WriteOutputStreamValue(*field->key, (IsGoType(*field->key) ? "k" : "v.Key"), false, true);
+
5790 WriteLineIndent("sb.WriteString(\"->\")");
+
5791 WriteOutputStreamValue(*field->type, (IsGoType(*field->key) ? "v" : "v.Value"), field->optional, false);
+
5792 WriteLineIndent("first = false");
+
5793 Indent(-1);
+
5794 WriteLineIndent("}");
+
5795 WriteLineIndent("sb.WriteString(\"}]\")");
+
5796 Indent(-1);
+
5797 WriteLineIndent("} else {");
+
5798 Indent(1);
+
5799 WriteLineIndent("sb.WriteString(\"" + std::string(first ? "" : ",") + *field->name + "=[0][{}]\")");
+
5800 Indent(-1);
+
5801 WriteLineIndent("}");
+
5802 }
+
5803 else
+
5804 WriteOutputStreamValue(*field->type, "s." + ConvertToUpper(*field->name), field->optional, false);
+
5805 first = false;
+
5806 }
+
5807 }
+
5808 WriteLineIndent("sb.WriteString(\")\")");
+
5809 WriteLineIndent("return sb.String()");
+
5810 Indent(-1);
+
5811 WriteLineIndent("}");
+
5812
+
5813 if (JSON())
+
5814 {
+
5815 // Generate struct JSON() method
+
5816 WriteLine();
+
5817 WriteLineIndent("// Convert struct to JSON");
+
5818 WriteLineIndent("func (s *" + struct_name + ") JSON() ([]byte, error) {");
+
5819 Indent(1);
+
5820 WriteLineIndent("return fbe.Json.Marshal(s)");
+
5821 Indent(-1);
+
5822 WriteLineIndent("}");
+
5823 }
+
5824
+
5825 // Generate set wrappers
+
5826 if (s->body)
+
5827 {
+
5828 for (const auto& field : s->body->fields)
+
5829 {
+
5830 if (field->set)
+
5831 {
+
5832 WriteLine();
+
5833 WriteLineIndent("// Set wrapper for the field " + ConvertToUpper(*field->name));
+
5834 WriteLineIndent("type set" + ConvertToUpper(*field->name) + " map[" + ConvertKeyName(*field->key) + "]" + ConvertTypeName(*field->type, field->optional));
+
5835
+
5836 if (JSON())
+
5837 {
+
5838 // Generate set wrapper IsEmpty() method
+
5839 WriteLine();
+
5840 WriteLineIndent("// Is the set empty?");
+
5841 WriteLineIndent("func (s set" + ConvertToUpper(*field->name) + ") IsEmpty() bool {");
+
5842 Indent(1);
+
5843 WriteLineIndent("return s.Size() > 0");
+
5844 Indent(-1);
+
5845 WriteLineIndent("}");
+
5846
+
5847 // Generate set wrapper Size() method
+
5848 WriteLine();
+
5849 WriteLineIndent("// Get the set size");
+
5850 WriteLineIndent("func (s set" + ConvertToUpper(*field->name) + ") Size() int {");
+
5851 Indent(1);
+
5852 WriteLineIndent("return len(s)");
+
5853 Indent(-1);
+
5854 WriteLineIndent("}");
+
5855
+
5856 // Generate set wrapper Add() method
+
5857 WriteLine();
+
5858 WriteLineIndent("// Add the given item to the set");
+
5859 WriteLineIndent("func (s set" + ConvertToUpper(*field->name) + ") Add(item " + ConvertTypeName(*field->type, field->optional) + ") {");
+
5860 Indent(1);
+
5861 if (IsGoType(*field->key))
+
5862 WriteLineIndent("s[item] = item");
+
5863 else
+
5864 WriteLineIndent("s[item.Key()] = item");
+
5865 Indent(-1);
+
5866 WriteLineIndent("}");
+
5867
+
5868 // Generate set wrapper Contains() method
+
5869 WriteLine();
+
5870 WriteLineIndent("// Contains the given item in the set?");
+
5871 WriteLineIndent("func (s set" + ConvertToUpper(*field->name) + ") Contains(item " + ConvertTypeName(*field->type, field->optional) + ") bool {");
+
5872 Indent(1);
+
5873 if (IsGoType(*field->key))
+
5874 WriteLineIndent("_, exists := s[item]");
+
5875 else
+
5876 WriteLineIndent("_, exists := s[item.Key()]");
+
5877 Indent(-1);
+
5878 WriteLineIndent("return exists");
+
5879 WriteLineIndent("}");
+
5880
+
5881 // Generate set wrapper Remove() method
+
5882 WriteLine();
+
5883 WriteLineIndent("// Remove the given item from the set");
+
5884 WriteLineIndent("func (s set" + ConvertToUpper(*field->name) + ") Remove(item " + ConvertTypeName(*field->type, field->optional) + ") {");
+
5885 Indent(1);
+
5886 if (IsGoType(*field->key))
+
5887 WriteLineIndent("delete(s, item)");
+
5888 else
+
5889 WriteLineIndent("delete(s, item.Key())");
+
5890 Indent(-1);
+
5891 WriteLineIndent("}");
+
5892
+
5893 // Generate set wrapper Clear() method
+
5894 WriteLine();
+
5895 WriteLineIndent("// Clear the set");
+
5896 WriteLineIndent("func (s set" + ConvertToUpper(*field->name) + ") Clear() {");
+
5897 Indent(1);
+
5898 WriteLineIndent("for i := range s {");
+
5899 Indent(1);
+
5900 WriteLineIndent("delete(s, i)");
+
5901 Indent(-1);
+
5902 WriteLineIndent("}");
+
5903 Indent(-1);
+
5904 WriteLineIndent("}");
+
5905
+
5906 // Generate set wrapper Enumerate() method
+
5907 WriteLine();
+
5908 WriteLineIndent("// Enumerate the set");
+
5909 WriteLineIndent("func (s set" + ConvertToUpper(*field->name) + ") Enumerate() []" + ConvertTypeName(*field->type, field->optional) + " {");
+
5910 Indent(1);
+
5911 WriteLineIndent("array := make([]" + ConvertTypeName(*field->type, field->optional) + ", 0)");
+
5912 WriteLineIndent("for _, v := range s {");
+
5913 Indent(1);
+
5914 WriteLineIndent("array = append(array, v)");
+
5915 Indent(-1);
+
5916 WriteLineIndent("}");
+
5917 WriteLineIndent("return array");
+
5918 Indent(-1);
+
5919 WriteLineIndent("}");
+
5920
+
5921 // Generate set wrapper Subset() method
+
5922 WriteLine();
+
5923 WriteLineIndent("// Is the current set a subset of the given set?");
+
5924 WriteLineIndent("func (s set" + ConvertToUpper(*field->name) + ") Subset(set set" + ConvertToUpper(*field->name) + ") bool {");
+
5925 Indent(1);
+
5926 WriteLineIndent("result := true");
+
5927 WriteLineIndent("for _, v := range s {");
+
5928 Indent(1);
+
5929 WriteLineIndent("if !set.Contains(v) {");
+
5930 Indent(1);
+
5931 WriteLineIndent("result = false");
+
5932 WriteLineIndent("break");
+
5933 Indent(-1);
+
5934 WriteLineIndent("}");
+
5935 Indent(-1);
+
5936 WriteLineIndent("}");
+
5937 WriteLineIndent("return result");
+
5938 Indent(-1);
+
5939 WriteLineIndent("}");
+
5940
+
5941 // Generate set wrapper Union() method
+
5942 WriteLine();
+
5943 WriteLineIndent("// Union of the current set and the given set");
+
5944 WriteLineIndent("func (s set" + ConvertToUpper(*field->name) + ") Union(set set" + ConvertToUpper(*field->name) + ") set" + ConvertToUpper(*field->name) + " {");
+
5945 Indent(1);
+
5946 WriteLineIndent("result := make(set" + ConvertToUpper(*field->name) + ")");
+
5947 WriteLineIndent("for _, v := range s {");
+
5948 Indent(1);
+
5949 WriteLineIndent("result.Add(v)");
+
5950 Indent(-1);
+
5951 WriteLineIndent("}");
+
5952 WriteLineIndent("for _, v := range set {");
+
5953 Indent(1);
+
5954 WriteLineIndent("result.Add(v)");
+
5955 Indent(-1);
+
5956 WriteLineIndent("}");
+
5957 WriteLineIndent("return result");
+
5958 Indent(-1);
+
5959 WriteLineIndent("}");
+
5960
+
5961 // Generate set wrapper Intersection() method
+
5962 WriteLine();
+
5963 WriteLineIndent("// Intersection of the current set and the given set");
+
5964 WriteLineIndent("func (s set" + ConvertToUpper(*field->name) + ") Intersection(set set" + ConvertToUpper(*field->name) + ") set" + ConvertToUpper(*field->name) + " {");
+
5965 Indent(1);
+
5966 WriteLineIndent("result := make(set" + ConvertToUpper(*field->name) + ")");
+
5967 WriteLineIndent("for _, v := range set {");
+
5968 Indent(1);
+
5969 WriteLineIndent("if s.Contains(v) {");
+
5970 Indent(1);
+
5971 WriteLineIndent("result.Add(v)");
+
5972 Indent(-1);
+
5973 WriteLineIndent("}");
+
5974 Indent(-1);
+
5975 WriteLineIndent("}");
+
5976 WriteLineIndent("return result");
+
5977 Indent(-1);
+
5978 WriteLineIndent("}");
+
5979
+
5980 // Generate set wrapper Difference() method
+
5981 WriteLine();
+
5982 WriteLineIndent("// Difference between the current set and the given set");
+
5983 WriteLineIndent("func (s set" + ConvertToUpper(*field->name) + ") Difference(set set" + ConvertToUpper(*field->name) + ") set" + ConvertToUpper(*field->name) + " {");
+
5984 Indent(1);
+
5985 WriteLineIndent("result := make(set" + ConvertToUpper(*field->name) + ")");
+
5986 WriteLineIndent("for _, v := range set {");
+
5987 Indent(1);
+
5988 WriteLineIndent("if !s.Contains(v) {");
+
5989 Indent(1);
+
5990 WriteLineIndent("result.Add(v)");
+
5991 Indent(-1);
+
5992 WriteLineIndent("}");
+
5993 Indent(-1);
+
5994 WriteLineIndent("}");
+
5995 WriteLineIndent("for _, v := range s {");
+
5996 Indent(1);
+
5997 WriteLineIndent("if !set.Contains(v) {");
+
5998 Indent(1);
+
5999 WriteLineIndent("result.Add(v)");
+
6000 Indent(-1);
+
6001 WriteLineIndent("}");
+
6002 Indent(-1);
+
6003 WriteLineIndent("}");
+
6004 WriteLineIndent("return result");
+
6005 Indent(-1);
+
6006 WriteLineIndent("}");
+
6007
+
6008 // Generate set wrapper MarshalJSON() method
+
6009 WriteLine();
+
6010 WriteLineIndent("// Convert set to JSON");
+
6011 WriteLineIndent("func (s set" + ConvertToUpper(*field->name) + ") MarshalJSON() ([]byte, error) {");
+
6012 Indent(1);
+
6013 WriteLineIndent("array := make([]" + ConvertTypeName(*field->type, field->optional) + ", 0)");
+
6014 WriteLineIndent("for _, v := range s {");
+
6015 Indent(1);
+
6016 WriteLineIndent("array = append(array, v)");
+
6017 Indent(-1);
+
6018 WriteLineIndent("}");
+
6019 WriteLineIndent("return fbe.Json.Marshal(&array)");
+
6020 Indent(-1);
+
6021 WriteLineIndent("}");
+
6022
+
6023 // Generate set wrapper UnmarshalJSON() method
+
6024 WriteLine();
+
6025 WriteLineIndent("// Convert JSON to set");
+
6026 WriteLineIndent("func (s *set" + ConvertToUpper(*field->name) + ") UnmarshalJSON(body []byte) error {");
+
6027 Indent(1);
+
6028 WriteLineIndent("var array []" + ConvertTypeName(*field->type, field->optional));
+
6029 WriteLineIndent("err := fbe.Json.Unmarshal(body, &array)");
+
6030 WriteLineIndent("if err != nil {");
+
6031 Indent(1);
+
6032 WriteLineIndent("return err");
+
6033 Indent(-1);
+
6034 WriteLineIndent("} else {");
+
6035 Indent(1);
+
6036 WriteLineIndent("for _, v := range array {");
+
6037 Indent(1);
+
6038 if (IsGoType(*field->key))
+
6039 WriteLineIndent("(*s)[v] = v");
+
6040 else
+
6041 WriteLineIndent("(*s)[v.Key()] = v");
+
6042 Indent(-1);
+
6043 WriteLineIndent("}");
+
6044 Indent(-1);
+
6045 WriteLineIndent("}");
+
6046 WriteLineIndent("return nil");
+
6047 Indent(-1);
+
6048 WriteLineIndent("}");
+
6049 }
+
6050 }
+
6051 }
+
6052 }
+
6053
+
6054 // Generate footer
+
6055 GenerateFooter();
+
6056
+
6057 // Store the output file
+
6058 WriteEnd();
+
6059 Store(output);
+
6060
+
6061 // Generate struct field model
+
6062 GenerateStructFieldModel(p, s, path);
+
6063
+
6064 // Generate struct model
+
6065 GenerateStructModel(p, s, path);
+
6066
+
6067 // Generate struct final models
+
6068 if (Final())
+
6069 {
+
6070 GenerateStructFinalModel(p, s, path);
+
6071 GenerateStructModelFinal(p, s, path);
+
6072 }
+
6073}
+
6074
+
6075void GeneratorGo::GenerateStructFieldModel(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s, const CppCommon::Path& path)
+
6076{
+
6077 std::string struct_name = ConvertToUpper(*s->name);
+
6078 std::string field_model_name = "FieldModel" + struct_name;
+
6079
+
6080 // Generate the output file
+
6081 CppCommon::Path output = path / (field_model_name + ".go");
+
6082 WriteBegin();
+
6083
+
6084 // Generate header
+
6085 GenerateHeader(CppCommon::Path(_input).filename().string());
+
6086
+
6087 // Generate package
+
6088 WriteLine();
+
6089 WriteLineIndent("package " + *p->name);
+
6090
+
6091 // Generate imports
+
6092 WriteLine();
+
6093 GenerateImports(p);
+
6094
+
6095 std::string base_type = (s->base && !s->base->empty()) ? ConvertTypeName(*s->base, false) : "";
+
6096 std::string base_field_model = (s->base && !s->base->empty()) ? ConvertModelName(*s->base, "FieldModel") : "";
+
6097 std::string base_field_name = "FieldModel" + ConvertBaseName(base_type);
+
6098
+
6099 // Generate struct field model type
+
6100 WriteLine();
+
6101 WriteLineIndent("// Fast Binary Encoding " + struct_name + " field model");
+
6102 WriteLineIndent("type " + field_model_name + " struct {");
+
6103 Indent(1);
+
6104 WriteLineIndent("// Field model buffer");
+
6105 WriteLineIndent("buffer *fbe.Buffer");
+
6106 WriteLineIndent("// Field model buffer offset");
+
6107 WriteLineIndent("offset int");
+
6108 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
6109 {
+
6110 WriteLine();
+
6111 if (!base_type.empty())
+
6112 WriteLineIndent("*" + base_field_model);
+
6113 if (s->body)
+
6114 for (const auto& field : s->body->fields)
+
6115 WriteLineIndent(ConvertToUpper(*field->name) + " *" + ConvertTypeFieldDeclaration(*field, false));
+
6116 }
+
6117 Indent(-1);
+
6118 WriteLineIndent("}");
+
6119
+
6120 // Generate struct field model constructor
+
6121 WriteLine();
+
6122 WriteLineIndent("// Create a new " + struct_name + " field model");
+
6123 WriteLineIndent("func New" + field_model_name + "(buffer *fbe.Buffer, offset int) *" + field_model_name + " {");
+
6124 Indent(1);
+
6125 std::string prev_offset("4");
+
6126 std::string prev_size("4");
+
6127 WriteLineIndent("fbeResult := " + field_model_name + "{buffer: buffer, offset: offset}");
+
6128 if (!base_type.empty())
+
6129 {
+
6130 WriteLineIndent("fbeResult." + base_field_name + " = " + ConvertModelName(*s->base, "NewFieldModel") + "(buffer, " + prev_offset + " + " + prev_size + ")");
+
6131 prev_offset = "fbeResult." + base_field_name + ".FBEOffset()";
+
6132 prev_size = "fbeResult." + base_field_name + ".FBEBody() - 4 - 4";
+
6133 }
+
6134 if (s->body)
+
6135 {
+
6136 for (const auto& field : s->body->fields)
+
6137 {
+
6138 WriteLineIndent("fbeResult." + ConvertToUpper(*field->name) + " = " + ConvertTypeFieldInitialization(*field, prev_offset + " + " + prev_size, false));
+
6139 prev_offset = "fbeResult." + ConvertToUpper(*field->name) + ".FBEOffset()";
+
6140 prev_size = "fbeResult." + ConvertToUpper(*field->name) + ".FBESize()";
+
6141 }
+
6142 }
+
6143 WriteLineIndent("return &fbeResult");
+
6144 Indent(-1);
+
6145 WriteLineIndent("}");
+
6146
+
6147 // Generate struct field model FBESize() method
+
6148 WriteLine();
+
6149 WriteLineIndent("// Get the field size");
+
6150 WriteLineIndent("func (fm *" + field_model_name + ") FBESize() int { return 4 }");
+
6151
+
6152 // Generate struct field model FBEBody() method
+
6153 WriteLine();
+
6154 WriteLineIndent("// Get the field body size");
+
6155 WriteLineIndent("func (fm *" + field_model_name + ") FBEBody() int {");
+
6156 Indent(1);
+
6157 WriteLineIndent("fbeResult := 4 + 4 +");
+
6158 Indent(1);
+
6159 if (!base_type.empty())
+
6160 WriteLineIndent("fm." + base_field_name + ".FBEBody() - 4 - 4 +");
+
6161 if (s->body)
+
6162 for (const auto& field : s->body->fields)
+
6163 WriteLineIndent("fm." + ConvertToUpper(*field->name) + ".FBESize() +");
+
6164 WriteLineIndent("0");
+
6165 Indent(-1);
+
6166 WriteLineIndent("return fbeResult");
+
6167 Indent(-1);
+
6168 WriteLineIndent("}");
+
6169
+
6170 // Generate struct field model FBEExtra() method
+
6171 WriteLine();
+
6172 WriteLineIndent("// Get the field extra size");
+
6173 WriteLineIndent("func (fm *" + field_model_name + ") FBEExtra() int {");
+
6174 Indent(1);
+
6175 WriteLineIndent("if (fm.buffer.Offset() + fm.FBEOffset() + fm.FBESize()) > fm.buffer.Size() {");
+
6176 Indent(1);
+
6177 WriteLineIndent("return 0");
+
6178 Indent(-1);
+
6179 WriteLineIndent("}");
+
6180 WriteLine();
+
6181 WriteLineIndent("fbeStructOffset := int(fbe.ReadUInt32(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset()))");
+
6182 WriteLineIndent("if (fbeStructOffset == 0) || ((fm.buffer.Offset() + fbeStructOffset + 4) > fm.buffer.Size()) {");
+
6183 Indent(1);
+
6184 WriteLineIndent("return 0");
+
6185 Indent(-1);
+
6186 WriteLineIndent("}");
+
6187 WriteLine();
+
6188 WriteLineIndent("fm.buffer.Shift(fbeStructOffset)");
+
6189 WriteLine();
+
6190 WriteLineIndent("fbeResult := fm.FBEBody() +");
+
6191 Indent(1);
+
6192 if (!base_type.empty())
+
6193 WriteLineIndent("fm." + base_field_name + ".FBEExtra() + ");
+
6194 if (s->body)
+
6195 for (const auto& field : s->body->fields)
+
6196 WriteLineIndent("fm." + ConvertToUpper(*field->name) + ".FBEExtra() +");
+
6197 WriteLineIndent("0");
+
6198 Indent(-1);
+
6199 WriteLine();
+
6200 WriteLineIndent("fm.buffer.Unshift(fbeStructOffset)");
+
6201 WriteLine();
+
6202 WriteLineIndent("return fbeResult");
+
6203 Indent(-1);
+
6204 WriteLineIndent("}");
+
6205
+
6206 // Generate struct field model FBEType() method
+
6207 WriteLine();
+
6208 WriteLineIndent("// Get the field type");
+
6209 if (s->base && !s->base->empty() && (s->type == 0))
+
6210 WriteLineIndent("func (fm *" + field_model_name + ") FBEType() int { return fm." + base_field_name + ".FBEType() }");
+
6211 else
+
6212 WriteLineIndent("func (fm *" + field_model_name + ") FBEType() int { return " + std::to_string(s->type) + " }");
+
6213
+
6214 // Generate struct field model FBEOffset() methods
+
6215 WriteLine();
+
6216 WriteLineIndent("// Get the field offset");
+
6217 WriteLineIndent("func (fm *" + field_model_name + ") FBEOffset() int { return fm.offset }");
+
6218 WriteLineIndent("// Set the field offset");
+
6219 WriteLineIndent("func (fm *" + field_model_name + ") SetFBEOffset(value int) { fm.offset = value }");
+
6220
+
6221 // Generate struct field model FBEShift() methods
+
6222 WriteLine();
+
6223 WriteLineIndent("// Shift the current field offset");
+
6224 WriteLineIndent("func (fm *" + field_model_name + ") FBEShift(size int) { fm.offset += size }");
+
6225 WriteLineIndent("// Unshift the current field offset");
+
6226 WriteLineIndent("func (fm *" + field_model_name + ") FBEUnshift(size int) { fm.offset -= size }");
+
6227
+
6228 // Generate struct field model Verify() methods
+
6229 WriteLine();
+
6230 WriteLineIndent("// Check if the struct value is valid");
+
6231 WriteLineIndent("func (fm *" + field_model_name + ") Verify() bool { return fm.VerifyType(true) }");
+
6232 WriteLine();
+
6233 WriteLineIndent("// Check if the struct value and its type are valid");
+
6234 WriteLineIndent("func (fm *" + field_model_name + ") VerifyType(fbeVerifyType bool) bool {");
+
6235 Indent(1);
+
6236 WriteLineIndent("if (fm.buffer.Offset() + fm.FBEOffset() + fm.FBESize()) > fm.buffer.Size() {");
+
6237 Indent(1);
+
6238 WriteLineIndent("return true");
+
6239 Indent(-1);
+
6240 WriteLineIndent("}");
+
6241 WriteLine();
+
6242 WriteLineIndent("fbeStructOffset := int(fbe.ReadUInt32(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset()))");
+
6243 WriteLineIndent("if (fbeStructOffset == 0) || ((fm.buffer.Offset() + fbeStructOffset + 4 + 4) > fm.buffer.Size()) {");
+
6244 Indent(1);
+
6245 WriteLineIndent("return false");
+
6246 Indent(-1);
+
6247 WriteLineIndent("}");
+
6248 WriteLine();
+
6249 WriteLineIndent("fbeStructSize := int(fbe.ReadUInt32(fm.buffer.Data(), fm.buffer.Offset() + fbeStructOffset))");
+
6250 WriteLineIndent("if fbeStructSize < (4 + 4) {");
+
6251 Indent(1);
+
6252 WriteLineIndent("return false");
+
6253 Indent(-1);
+
6254 WriteLineIndent("}");
+
6255 WriteLine();
+
6256 WriteLineIndent("fbeStructType := int(fbe.ReadUInt32(fm.buffer.Data(), fm.buffer.Offset() + fbeStructOffset + 4))");
+
6257 WriteLineIndent("if fbeVerifyType && (fbeStructType != fm.FBEType()) {");
+
6258 Indent(1);
+
6259 WriteLineIndent("return false");
+
6260 Indent(-1);
+
6261 WriteLineIndent("}");
+
6262 WriteLine();
+
6263 WriteLineIndent("fm.buffer.Shift(fbeStructOffset)");
+
6264 WriteLineIndent("fbeResult := fm.VerifyFields(fbeStructSize)");
+
6265 WriteLineIndent("fm.buffer.Unshift(fbeStructOffset)");
+
6266 WriteLineIndent("return fbeResult");
+
6267 Indent(-1);
+
6268 WriteLineIndent("}");
+
6269 WriteLine();
+
6270 WriteLineIndent("// // Check if the struct value fields are valid");
+
6271 WriteLineIndent("func (fm *" + field_model_name + ") VerifyFields(fbeStructSize int) bool {");
+
6272 Indent(1);
+
6273 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
6274 {
+
6275 WriteLineIndent("fbeCurrentSize := 4 + 4");
+
6276 if (!base_type.empty())
+
6277 {
+
6278 WriteLine();
+
6279 WriteLineIndent("if (fbeCurrentSize + fm." + base_field_name + ".FBEBody() - 4 - 4) > fbeStructSize {");
+
6280 Indent(1);
+
6281 WriteLineIndent("return true");
+
6282 Indent(-1);
+
6283 WriteLineIndent("}");
+
6284 WriteLineIndent("if !fm." + base_field_name + ".VerifyFields(fbeStructSize) {");
+
6285 Indent(1);
+
6286 WriteLineIndent("return false");
+
6287 Indent(-1);
+
6288 WriteLineIndent("}");
+
6289 WriteLineIndent("fbeCurrentSize += fm." + base_field_name + ".FBEBody() - 4 - 4");
+
6290 }
+
6291 if (s->body)
+
6292 {
+
6293 for (const auto& field : s->body->fields)
+
6294 {
+
6295 WriteLine();
+
6296 WriteLineIndent("if (fbeCurrentSize + fm." + ConvertToUpper(*field->name) + ".FBESize()) > fbeStructSize {");
+
6297 Indent(1);
+
6298 WriteLineIndent("return true");
+
6299 Indent(-1);
+
6300 WriteLineIndent("}");
+
6301 WriteLineIndent("if !fm." + ConvertToUpper(*field->name) + ".Verify() {");
+
6302 Indent(1);
+
6303 WriteLineIndent("return false");
+
6304 Indent(-1);
+
6305 WriteLineIndent("}");
+
6306 WriteLineIndent("fbeCurrentSize += fm." + ConvertToUpper(*field->name) + ".FBESize()");
+
6307 }
+
6308 }
+
6309 WriteLine();
+
6310 }
+
6311 WriteLineIndent("return true");
+
6312 Indent(-1);
+
6313 WriteLineIndent("}");
+
6314
+
6315 // Generate struct field model Get() methods
+
6316 WriteLine();
+
6317 WriteLineIndent("// Get the struct value (begin phase)");
+
6318 WriteLineIndent("func (fm *" + field_model_name + ") GetBegin() (int, error) {");
+
6319 Indent(1);
+
6320 WriteLineIndent("if (fm.buffer.Offset() + fm.FBEOffset() + fm.FBESize()) > fm.buffer.Size() {");
+
6321 Indent(1);
+
6322 WriteLineIndent("return 0, nil");
+
6323 Indent(-1);
+
6324 WriteLineIndent("}");
+
6325 WriteLine();
+
6326 WriteLineIndent("fbeStructOffset := int(fbe.ReadUInt32(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset()))");
+
6327 WriteLineIndent("if (fbeStructOffset == 0) || ((fm.buffer.Offset() + fbeStructOffset + 4 + 4) > fm.buffer.Size()) {");
+
6328 Indent(1);
+
6329 WriteLineIndent("return 0, errors.New(\"model is broken\")");
+
6330 Indent(-1);
+
6331 WriteLineIndent("}");
+
6332 WriteLine();
+
6333 WriteLineIndent("fbeStructSize := int(fbe.ReadUInt32(fm.buffer.Data(), fm.buffer.Offset() + fbeStructOffset))");
+
6334 WriteLineIndent("if fbeStructSize < (4 + 4) {");
+
6335 Indent(1);
+
6336 WriteLineIndent("return 0, errors.New(\"model is broken\")");
+
6337 Indent(-1);
+
6338 WriteLineIndent("}");
+
6339 WriteLine();
+
6340 WriteLineIndent("fm.buffer.Shift(fbeStructOffset)");
+
6341 WriteLineIndent("return fbeStructOffset, nil");
+
6342 Indent(-1);
+
6343 WriteLineIndent("}");
+
6344 WriteLine();
+
6345 WriteLineIndent("// Get the struct value (end phase)");
+
6346 WriteLineIndent("func (fm *" + field_model_name + ") GetEnd(fbeBegin int) {");
+
6347 Indent(1);
+
6348 WriteLineIndent("fm.buffer.Unshift(fbeBegin)");
+
6349 Indent(-1);
+
6350 WriteLineIndent("}");
+
6351 WriteLine();
+
6352 WriteLineIndent("// Get the struct value");
+
6353 WriteLineIndent("func (fm *" + field_model_name + ") Get() (*" + struct_name + ", error) {");
+
6354 Indent(1);
+
6355 WriteLineIndent("fbeResult := New" + struct_name + "()");
+
6356 WriteLineIndent("return fbeResult, fm.GetValue(fbeResult)");
+
6357 Indent(-1);
+
6358 WriteLineIndent("}");
+
6359 WriteLine();
+
6360 WriteLineIndent("// Get the struct value by the given pointer");
+
6361 WriteLineIndent("func (fm *" + field_model_name + ") GetValue(fbeValue *" + struct_name + ") error {");
+
6362 Indent(1);
+
6363 WriteLineIndent("fbeBegin, err := fm.GetBegin()");
+
6364 WriteLineIndent("if fbeBegin == 0 {");
+
6365 Indent(1);
+
6366 WriteLineIndent("return err");
+
6367 Indent(-1);
+
6368 WriteLineIndent("}");
+
6369 WriteLine();
+
6370 WriteLineIndent("fbeStructSize := int(fbe.ReadUInt32(fm.buffer.Data(), fm.buffer.Offset()))");
+
6371 WriteLineIndent("fm.GetFields(fbeValue, fbeStructSize)");
+
6372 WriteLineIndent("fm.GetEnd(fbeBegin)");
+
6373 WriteLineIndent("return nil");
+
6374 Indent(-1);
+
6375 WriteLineIndent("}");
+
6376 WriteLine();
+
6377 WriteLineIndent("// Get the struct fields values");
+
6378 WriteLineIndent("func (fm *" + field_model_name + ") GetFields(fbeValue *" + struct_name + ", fbeStructSize int) {");
+
6379 Indent(1);
+
6380 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
6381 {
+
6382 WriteLineIndent("fbeCurrentSize := 4 + 4");
+
6383 if (!base_type.empty())
+
6384 {
+
6385 WriteLine();
+
6386 WriteLineIndent("if (fbeCurrentSize + fm." + base_field_name + ".FBEBody() - 4 - 4) <= fbeStructSize {");
+
6387 Indent(1);
+
6388 WriteLineIndent("fm." + base_field_name + ".GetFields(fbeValue." + ConvertBaseName(base_type) + ", fbeStructSize)");
+
6389 Indent(-1);
+
6390 WriteLineIndent("}");
+
6391 WriteLineIndent("fbeCurrentSize += fm." + base_field_name + ".FBEBody() - 4 - 4");
+
6392 }
+
6393 if (s->body)
+
6394 {
+
6395 for (const auto& field : s->body->fields)
+
6396 {
+
6397 WriteLine();
+
6398 WriteLineIndent("if (fbeCurrentSize + fm." + ConvertToUpper(*field->name) + ".FBESize()) <= fbeStructSize {");
+
6399 Indent(1);
+
6400 if (field->array)
+
6401 {
+
6402 WriteLineIndent("slice, _ := fm." + ConvertToUpper(*field->name) + ".Get()");
+
6403 WriteLineIndent("copy(fbeValue." + ConvertToUpper(*field->name) + "[:], slice)");
+
6404 }
+
6405 else if (field->vector || field->list || field->set || field->map || field->hash || field->optional)
+
6406 WriteLineIndent("fbeValue." + ConvertToUpper(*field->name) + ", _ = fm." + ConvertToUpper(*field->name) + ".Get()");
+
6407 else if (!IsGoType(*field->type))
+
6408 {
+
6409 if (field->value)
+
6410 WriteLineIndent("_ = fm." + ConvertToUpper(*field->name) + ".GetValueDefault(&fbeValue." + ConvertToUpper(*field->name) + ", " + ConvertConstant(*field->type, *field->value, field->optional) + ")");
+
6411 else
+
6412 WriteLineIndent("_ = fm." + ConvertToUpper(*field->name) + ".GetValue(&fbeValue." + ConvertToUpper(*field->name) + ")");
+
6413 }
+
6414 else
+
6415 {
+
6416 if (field->value)
+
6417 WriteLineIndent("fbeValue." + ConvertToUpper(*field->name) + ", _ = fm." + ConvertToUpper(*field->name) + ".GetDefault(" + ConvertConstant(*field->type, *field->value, field->optional) + ")");
+
6418 else
+
6419 WriteLineIndent("fbeValue." + ConvertToUpper(*field->name) + ", _ = fm." + ConvertToUpper(*field->name) + ".Get()");
+
6420 }
+
6421 Indent(-1);
+
6422 WriteLineIndent("} else {");
+
6423 Indent(1);
+
6424 WriteLineIndent("fbeValue." + ConvertToUpper(*field->name) + " = " + ConvertDefault(*field));
+
6425 Indent(-1);
+
6426 WriteLineIndent("}");
+
6427 WriteLineIndent("fbeCurrentSize += fm." + ConvertToUpper(*field->name) + ".FBESize()");
+
6428 }
+
6429 }
+
6430 }
+
6431 Indent(-1);
+
6432 WriteLineIndent("}");
+
6433
+
6434 // Generate struct field model Set() methods
+
6435 WriteLine();
+
6436 WriteLineIndent("// Set the struct value (begin phase)");
+
6437 WriteLineIndent("func (fm *" + field_model_name + ") SetBegin() (int, error) {");
+
6438 Indent(1);
+
6439 WriteLineIndent("if (fm.buffer.Offset() + fm.FBEOffset() + fm.FBESize()) > fm.buffer.Size() {");
+
6440 Indent(1);
+
6441 WriteLineIndent("return 0, errors.New(\"model is broken\")");
+
6442 Indent(-1);
+
6443 WriteLineIndent("}");
+
6444 WriteLine();
+
6445 WriteLineIndent("fbeStructSize := fm.FBEBody()");
+
6446 WriteLineIndent("fbeStructOffset := fm.buffer.Allocate(fbeStructSize) - fm.buffer.Offset()");
+
6447 WriteLineIndent("if (fbeStructOffset <= 0) || ((fm.buffer.Offset() + fbeStructOffset + fbeStructSize) > fm.buffer.Size()) {");
+
6448 Indent(1);
+
6449 WriteLineIndent("return 0, errors.New(\"model is broken\")");
+
6450 Indent(-1);
+
6451 WriteLineIndent("}");
+
6452 WriteLine();
+
6453 WriteLineIndent("fbe.WriteUInt32(fm.buffer.Data(), fm.buffer.Offset() + fm.FBEOffset(), uint32(fbeStructOffset))");
+
6454 WriteLineIndent("fbe.WriteUInt32(fm.buffer.Data(), fm.buffer.Offset() + fbeStructOffset, uint32(fbeStructSize))");
+
6455 WriteLineIndent("fbe.WriteUInt32(fm.buffer.Data(), fm.buffer.Offset() + fbeStructOffset + 4, uint32(fm.FBEType()))");
+
6456 WriteLine();
+
6457 WriteLineIndent("fm.buffer.Shift(fbeStructOffset)");
+
6458 WriteLineIndent("return fbeStructOffset, nil");
+
6459 Indent(-1);
+
6460 WriteLineIndent("}");
+
6461 WriteLine();
+
6462 WriteLineIndent("// Set the struct value (end phase)");
+
6463 WriteLineIndent("func (fm *" + field_model_name + ") SetEnd(fbeBegin int) {");
+
6464 Indent(1);
+
6465 WriteLineIndent("fm.buffer.Unshift(fbeBegin)");
+
6466 Indent(-1);
+
6467 WriteLineIndent("}");
+
6468 WriteLine();
+
6469 WriteLineIndent("// Set the struct value");
+
6470 WriteLineIndent("func (fm *" + field_model_name + ") Set(fbeValue *" + struct_name + ") error {");
+
6471 Indent(1);
+
6472 WriteLineIndent("fbeBegin, err := fm.SetBegin()");
+
6473 WriteLineIndent("if fbeBegin == 0 {");
+
6474 Indent(1);
+
6475 WriteLineIndent("return err");
+
6476 Indent(-1);
+
6477 WriteLineIndent("}");
+
6478 WriteLine();
+
6479 WriteLineIndent("err = fm.SetFields(fbeValue)");
+
6480 WriteLineIndent("fm.SetEnd(fbeBegin)");
+
6481 WriteLineIndent("return err");
+
6482 Indent(-1);
+
6483 WriteLineIndent("}");
+
6484 WriteLine();
+
6485 WriteLineIndent("// Set the struct fields values");
+
6486 WriteLineIndent("func (fm *" + field_model_name + ") SetFields(fbeValue *" + struct_name + ") error {");
+
6487 Indent(1);
+
6488 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
6489 {
+
6490 WriteLineIndent("var err error = nil");
+
6491 WriteLine();
+
6492 if (!base_type.empty())
+
6493 {
+
6494 WriteLineIndent("if err = fm." + base_field_name + ".SetFields(fbeValue." + ConvertBaseName(base_type) + "); err != nil {");
+
6495 Indent(1);
+
6496 WriteLineIndent("return err");
+
6497 Indent(-1);
+
6498 WriteLineIndent("}");
+
6499 }
+
6500 if (s->body)
+
6501 {
+
6502 for (const auto& field : s->body->fields)
+
6503 {
+
6504 if (field->array)
+
6505 WriteLineIndent("if err = fm." + ConvertToUpper(*field->name) + ".Set(fbeValue." + ConvertToUpper(*field->name) + "[:]); err != nil {");
+
6506 else
+
6507 WriteLineIndent("if err = fm." + ConvertToUpper(*field->name) + ".Set(" + ((IsGoType(*field->type) || field->vector || field->list || field->set || field->map || field->hash || field->optional) ? "" : "&") + "fbeValue." + ConvertToUpper(*field->name) + "); err != nil {");
+
6508 Indent(1);
+
6509 WriteLineIndent("return err");
+
6510 Indent(-1);
+
6511 WriteLineIndent("}");
+
6512 }
+
6513 }
+
6514 WriteLineIndent("return err");
+
6515 }
+
6516 else
+
6517 WriteLineIndent("return nil");
+
6518 Indent(-1);
+
6519 WriteLineIndent("}");
+
6520
+
6521 // Generate footer
+
6522 GenerateFooter();
+
6523
+
6524 // Store the output file
+
6525 WriteEnd();
+
6526 Store(output);
+
6527}
+
6528
+
6529void GeneratorGo::GenerateStructModel(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s, const CppCommon::Path& path)
+
6530{
+
6531 std::string struct_name = ConvertToUpper(*s->name);
+
6532 std::string model_name = struct_name + "Model";
+
6533 std::string field_model_name = "FieldModel" + struct_name;
+
6534
+
6535 // Generate the output file
+
6536 CppCommon::Path output = path / (model_name + ".go");
+
6537 WriteBegin();
+
6538
+
6539 // Generate header
+
6540 GenerateHeader(CppCommon::Path(_input).filename().string());
+
6541
+
6542 // Generate package
+
6543 WriteLine();
+
6544 WriteLineIndent("package " + *p->name);
+
6545
+
6546 // Generate imports
+
6547 WriteLine();
+
6548 GenerateImports(p);
+
6549
+
6550 // Generate struct model type
+
6551 WriteLine();
+
6552 WriteLineIndent("// Fast Binary Encoding " + struct_name + " model");
+
6553 WriteLineIndent("type " + model_name + " struct {");
+
6554 Indent(1);
+
6555 WriteLineIndent("// Model buffer");
+
6556 WriteLineIndent("buffer *fbe.Buffer");
+
6557 WriteLine();
+
6558 WriteLineIndent("// Field model");
+
6559 WriteLineIndent("model *" + field_model_name);
+
6560 Indent(-1);
+
6561 WriteLineIndent("}");
+
6562
+
6563 // Generate struct model constructor
+
6564 WriteLine();
+
6565 WriteLineIndent("// Create a new " + struct_name + " model");
+
6566 WriteLineIndent("func New" + model_name + "(buffer *fbe.Buffer) *" + model_name + " {");
+
6567 Indent(1);
+
6568 WriteLineIndent("return &" + model_name + "{buffer: buffer, model: New" + field_model_name + "(buffer, 4)}");
+
6569 Indent(-1);
+
6570 WriteLineIndent("}");
+
6571
+
6572 // Generate struct model Buffer() & Model() methods
+
6573 WriteLine();
+
6574 WriteLineIndent("// Get the model buffer");
+
6575 WriteLineIndent("func (m *" + model_name + ") Buffer() *fbe.Buffer { return m.buffer }");
+
6576 WriteLineIndent("// Get the field model");
+
6577 WriteLineIndent("func (m *" + model_name + ") Model() *" + field_model_name + " { return m.model }");
+
6578
+
6579 // Generate struct model FBESize() & FBEType() methods
+
6580 WriteLine();
+
6581 WriteLineIndent("// Get the model size");
+
6582 WriteLineIndent("func (m *" + model_name + ") FBESize() int { return m.model.FBESize() + m.model.FBEExtra() }");
+
6583 WriteLineIndent("// // Get the model type");
+
6584 WriteLineIndent("func (m *" + model_name + ") FBEType() int { return m.model.FBEType() }");
+
6585
+
6586 // Generate struct model Verify() method
+
6587 WriteLine();
+
6588 WriteLineIndent("// Check if the struct value is valid");
+
6589 WriteLineIndent("func (m *" + model_name + ") Verify() bool {");
+
6590 Indent(1);
+
6591 WriteLineIndent("if (m.buffer.Offset() + m.model.FBEOffset() - 4) > m.buffer.Size() {");
+
6592 Indent(1);
+
6593 WriteLineIndent("return false");
+
6594 Indent(-1);
+
6595 WriteLineIndent("}");
+
6596 WriteLine();
+
6597 WriteLineIndent("fbeFullSize := int(fbe.ReadUInt32(m.buffer.Data(), m.buffer.Offset() + m.model.FBEOffset() - 4))");
+
6598 WriteLineIndent("if fbeFullSize < m.model.FBESize() {");
+
6599 Indent(1);
+
6600 WriteLineIndent("return false");
+
6601 Indent(-1);
+
6602 WriteLineIndent("}");
+
6603 WriteLine();
+
6604 WriteLineIndent("return m.model.Verify()");
+
6605 Indent(-1);
+
6606 WriteLineIndent("}");
+
6607
+
6608 // Generate struct model CreateBegin() method
+
6609 WriteLine();
+
6610 WriteLineIndent("// Create a new model (begin phase)");
+
6611 WriteLineIndent("func (m *" + model_name + ") CreateBegin() int {");
+
6612 Indent(1);
+
6613 WriteLineIndent("fbeBegin := m.buffer.Allocate(4 + m.model.FBESize())");
+
6614 WriteLineIndent("return fbeBegin");
+
6615 Indent(-1);
+
6616 WriteLineIndent("}");
+
6617
+
6618 // Generate struct model CreateEnd() method
+
6619 WriteLine();
+
6620 WriteLineIndent("// Create a new model (end phase)");
+
6621 WriteLineIndent("func (m *" + model_name + ") CreateEnd(fbeBegin int) int {");
+
6622 Indent(1);
+
6623 WriteLineIndent("fbeEnd := m.buffer.Size()");
+
6624 WriteLineIndent("fbeFullSize := fbeEnd - fbeBegin");
+
6625 WriteLineIndent("fbe.WriteUInt32(m.buffer.Data(), m.buffer.Offset() + m.model.FBEOffset() - 4, uint32(fbeFullSize))");
+
6626 WriteLineIndent("return fbeFullSize");
+
6627 Indent(-1);
+
6628 WriteLineIndent("}");
+
6629
+
6630 // Generate struct model Serialize() method
+
6631 WriteLine();
+
6632 WriteLineIndent("// Serialize the struct value");
+
6633 WriteLineIndent("func (m *" + model_name + ") Serialize(value *" + struct_name + ") (int, error) {");
+
6634 Indent(1);
+
6635 WriteLineIndent("fbeBegin := m.CreateBegin()");
+
6636 WriteLineIndent("err := m.model.Set(value)");
+
6637 WriteLineIndent("fbeFullSize := m.CreateEnd(fbeBegin)");
+
6638 WriteLineIndent("return fbeFullSize, err");
+
6639 Indent(-1);
+
6640 WriteLineIndent("}");
+
6641
+
6642 // Generate struct model Deserialize() method
+
6643 WriteLine();
+
6644 WriteLineIndent("// Deserialize the struct value");
+
6645 WriteLineIndent("func (m *" + model_name + ") Deserialize() (*" + struct_name + ", int, error) {");
+
6646 Indent(1);
+
6647 WriteLineIndent("value := New" + struct_name + "()");
+
6648 WriteLineIndent("fbeFullSize, err := m.DeserializeValue(value)");
+
6649 WriteLineIndent("return value, fbeFullSize, err");
+
6650 Indent(-1);
+
6651 WriteLineIndent("}");
+
6652
+
6653 // Generate struct model DeserializeValue() method
+
6654 WriteLine();
+
6655 WriteLineIndent("// Deserialize the struct value by the given pointer");
+
6656 WriteLineIndent("func (m *" + model_name + ") DeserializeValue(value *" + struct_name + ") (int, error) {");
+
6657 Indent(1);
+
6658 WriteLineIndent("if (m.buffer.Offset() + m.model.FBEOffset() - 4) > m.buffer.Size() {");
+
6659 Indent(1);
+
6660 WriteLineIndent("value = New" + struct_name + "()");
+
6661 WriteLineIndent("return 0, nil");
+
6662 Indent(-1);
+
6663 WriteLineIndent("}");
+
6664 WriteLine();
+
6665 WriteLineIndent("fbeFullSize := int(fbe.ReadUInt32(m.buffer.Data(), m.buffer.Offset() + m.model.FBEOffset() - 4))");
+
6666 WriteLineIndent("if fbeFullSize < m.model.FBESize() {");
+
6667 Indent(1);
+
6668 WriteLineIndent("value = New" + struct_name + "()");
+
6669 WriteLineIndent("return 0, errors.New(\"model is broken\")");
+
6670 Indent(-1);
+
6671 WriteLineIndent("}");
+
6672 WriteLine();
+
6673 WriteLineIndent("err := m.model.GetValue(value)");
+
6674 WriteLineIndent("return fbeFullSize, err");
+
6675 Indent(-1);
+
6676 WriteLineIndent("}");
+
6677
+
6678 // Generate struct model Next() method
+
6679 WriteLine();
+
6680 WriteLineIndent("// Move to the next struct value");
+
6681 WriteLineIndent("func (m *" + model_name + ") Next(prev int) {");
+
6682 Indent(1);
+
6683 WriteLineIndent("m.model.FBEShift(prev)");
+
6684 Indent(-1);
+
6685 WriteLineIndent("}");
+
6686
+
6687 // Generate footer
+
6688 GenerateFooter();
+
6689
+
6690 // Store the output file
+
6691 WriteEnd();
+
6692 Store(output);
+
6693}
+
6694
+
6695void GeneratorGo::GenerateStructFinalModel(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s, const CppCommon::Path& path)
+
6696{
+
6697 std::string struct_name = ConvertToUpper(*s->name);
+
6698 std::string final_model_name = "FinalModel" + struct_name;
+
6699
+
6700 // Generate the output file
+
6701 CppCommon::Path output = path / (final_model_name + ".go");
+
6702 WriteBegin();
+
6703
+
6704 // Generate header
+
6705 GenerateHeader(CppCommon::Path(_input).filename().string());
+
6706
+
6707 // Generate package
+
6708 WriteLine();
+
6709 WriteLineIndent("package " + *p->name);
+
6710
+
6711 // Generate imports
+
6712 WriteLine();
+
6713 GenerateImports(p);
+
6714
+
6715 std::string base_type = (s->base && !s->base->empty()) ? ConvertTypeName(*s->base, false) : "";
+
6716 std::string base_final_model = (s->base && !s->base->empty()) ? ConvertModelName(*s->base, "FinalModel") : "";
+
6717 std::string base_final_name = "FinalModel" + ConvertBaseName(base_type);
+
6718
+
6719 // Generate struct final model type
+
6720 WriteLine();
+
6721 WriteLineIndent("// Fast Binary Encoding " + struct_name + " final model");
+
6722 WriteLineIndent("type " + final_model_name + " struct {");
+
6723 Indent(1);
+
6724 WriteLineIndent("buffer *fbe.Buffer // Final model buffer");
+
6725 WriteLineIndent("offset int // Final model buffer offset");
+
6726 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
6727 {
+
6728 WriteLine();
+
6729 if (!base_type.empty())
+
6730 WriteLineIndent("*" + base_final_model);
+
6731 if (s->body)
+
6732 for (const auto& field : s->body->fields)
+
6733 WriteLineIndent(ConvertToUpper(*field->name) + " *" + ConvertTypeFieldDeclaration(*field, true));
+
6734 }
+
6735 Indent(-1);
+
6736 WriteLineIndent("}");
+
6737
+
6738 // Generate struct final model constructor
+
6739 WriteLine();
+
6740 WriteLineIndent("// Create a new " + struct_name + " final model");
+
6741 WriteLineIndent("func New" + final_model_name + "(buffer *fbe.Buffer, offset int) *" + final_model_name + " {");
+
6742 Indent(1);
+
6743 WriteLineIndent("fbeResult := " + final_model_name + "{buffer: buffer, offset: offset}");
+
6744 if (!base_type.empty())
+
6745 WriteLineIndent("fbeResult." + base_final_name + " = " + ConvertModelName(*s->base, "NewFinalModel") + "(buffer, 0)");
+
6746 if (s->body)
+
6747 for (const auto& field : s->body->fields)
+
6748 WriteLineIndent("fbeResult." + ConvertToUpper(*field->name) + " = " + ConvertTypeFieldInitialization(*field, "0", true));
+
6749 WriteLineIndent("return &fbeResult");
+
6750 Indent(-1);
+
6751 WriteLineIndent("}");
+
6752
+
6753 // Generate struct final model FBEAllocationSize() method
+
6754 WriteLine();
+
6755 WriteLineIndent("// Get the allocation size");
+
6756 WriteLineIndent("func (fm *" + final_model_name + ") FBEAllocationSize(fbeValue *" + struct_name + ") int {");
+
6757 Indent(1);
+
6758 WriteLineIndent("fbeResult := 0 +");
+
6759 Indent(1);
+
6760 if (!base_type.empty())
+
6761 WriteLineIndent("fm." + base_final_name + ".FBEAllocationSize(fbeValue." + ConvertBaseName(base_type) + ") + ");
+
6762 if (s->body)
+
6763 {
+
6764 for (const auto& field : s->body->fields)
+
6765 {
+
6766 if (field->array)
+
6767 WriteLineIndent("fm." + ConvertToUpper(*field->name) + ".FBEAllocationSize(fbeValue." + ConvertToUpper(*field->name) + "[:]) +");
+
6768 else if (field->vector || field->list || field->set || field->map || field->hash || field->optional)
+
6769 WriteLineIndent("fm." + ConvertToUpper(*field->name) + ".FBEAllocationSize(fbeValue." + ConvertToUpper(*field->name) + ") +");
+
6770 else if (!IsGoType(*field->type))
+
6771 WriteLineIndent("fm." + ConvertToUpper(*field->name) + ".FBEAllocationSize(&fbeValue." + ConvertToUpper(*field->name) + ") +");
+
6772 else
+
6773 WriteLineIndent("fm." + ConvertToUpper(*field->name) + ".FBEAllocationSize(fbeValue." + ConvertToUpper(*field->name) + ") +");
+
6774 }
+
6775 }
+
6776 WriteLineIndent("0");
+
6777 Indent(-1);
+
6778 WriteLineIndent("return fbeResult");
+
6779 Indent(-1);
+
6780 WriteLineIndent("}");
+
6781
+
6782 // Generate struct final model FBESize() method
+
6783 WriteLine();
+
6784 WriteLineIndent("// Get the final size");
+
6785 WriteLineIndent("func (fm *" + final_model_name + ") FBESize() int { return 0 }");
+
6786
+
6787 // Generate struct final model FBEExtra() method
+
6788 WriteLine();
+
6789 WriteLineIndent("// Get the final extra size");
+
6790 WriteLineIndent("func (fm *" + final_model_name + ") FBEExtra() int { return 0 }");
+
6791
+
6792 // Generate struct final model FBEType() method
+
6793 WriteLine();
+
6794 WriteLineIndent("// Get the final type");
+
6795 if (s->base && !s->base->empty() && (s->type == 0))
+
6796 WriteLineIndent("func (fm *" + final_model_name + ") FBEType() int { return fm." + base_final_name + ".FBEType() }");
+
6797 else
+
6798 WriteLineIndent("func (fm *" + final_model_name + ") FBEType() int { return " + std::to_string(s->type) + " }");
+
6799
+
6800 // Generate struct final model FBEOffset() methods
+
6801 WriteLine();
+
6802 WriteLineIndent("// Get the final offset");
+
6803 WriteLineIndent("func (fm *" + final_model_name + ") FBEOffset() int { return fm.offset }");
+
6804 WriteLineIndent("// Set the final offset");
+
6805 WriteLineIndent("func (fm *" + final_model_name + ") SetFBEOffset(value int) { fm.offset = value }");
+
6806
+
6807 // Generate struct final model FBEShift() methods
+
6808 WriteLine();
+
6809 WriteLineIndent("// Shift the current final offset");
+
6810 WriteLineIndent("func (fm *" + final_model_name + ") FBEShift(size int) { fm.offset += size }");
+
6811 WriteLineIndent("// Unshift the current final offset");
+
6812 WriteLineIndent("func (fm *" + final_model_name + ") FBEUnshift(size int) { fm.offset -= size }");
+
6813
+
6814 // Generate struct final model Verify() methods
+
6815 WriteLine();
+
6816 WriteLineIndent("// Check if the struct value is valid");
+
6817 WriteLineIndent("func (fm *" + final_model_name + ") Verify() int {");
+
6818 Indent(1);
+
6819 WriteLineIndent("fm.buffer.Shift(fm.FBEOffset())");
+
6820 WriteLineIndent("fbeResult := fm.VerifyFields()");
+
6821 WriteLineIndent("fm.buffer.Unshift(fm.FBEOffset())");
+
6822 WriteLineIndent("return fbeResult");
+
6823 Indent(-1);
+
6824 WriteLineIndent("}");
+
6825 WriteLine();
+
6826 WriteLineIndent("// Check if the struct fields are valid");
+
6827 WriteLineIndent("func (fm *" + final_model_name + ") VerifyFields() int {");
+
6828 Indent(1);
+
6829 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
6830 {
+
6831 WriteLineIndent("fbeCurrentOffset := 0");
+
6832 WriteLineIndent("fbeFieldSize := 0");
+
6833 WriteLine();
+
6834 if (!base_type.empty())
+
6835 {
+
6836 WriteLine();
+
6837 WriteLineIndent("fm." + base_final_name + ".SetFBEOffset(fbeCurrentOffset)");
+
6838 WriteLineIndent("if fbeFieldSize = fm." + base_final_name + ".VerifyFields(); fbeFieldSize == fbe.MaxInt {");
+
6839 Indent(1);
+
6840 WriteLineIndent("return fbe.MaxInt");
+
6841 Indent(-1);
+
6842 WriteLineIndent("}");
+
6843 WriteLineIndent("fbeCurrentOffset += fbeFieldSize");
+
6844 }
+
6845 if (s->body)
+
6846 {
+
6847 for (const auto& field : s->body->fields)
+
6848 {
+
6849 WriteLine();
+
6850 WriteLineIndent("fm." + ConvertToUpper(*field->name) + ".SetFBEOffset(fbeCurrentOffset)");
+
6851 WriteLineIndent("if fbeFieldSize = fm." + ConvertToUpper(*field->name) + ".Verify(); fbeFieldSize == fbe.MaxInt {");
+
6852 Indent(1);
+
6853 WriteLineIndent("return fbe.MaxInt");
+
6854 Indent(-1);
+
6855 WriteLineIndent("}");
+
6856 WriteLineIndent("fbeCurrentOffset += fbeFieldSize");
+
6857 }
+
6858 }
+
6859 WriteLine();
+
6860 WriteLineIndent("return fbeCurrentOffset");
+
6861 }
+
6862 else
+
6863 WriteLineIndent("return 0");
+
6864 Indent(-1);
+
6865 WriteLineIndent("}");
+
6866
+
6867 // Generate struct final model Get() methods
+
6868 WriteLine();
+
6869 WriteLineIndent("// Get the struct value");
+
6870 WriteLineIndent("func (fm *" + final_model_name + ") Get() (*" + struct_name + ", int, error) {");
+
6871 Indent(1);
+
6872 WriteLineIndent("fbeResult := New" + struct_name + "()");
+
6873 WriteLineIndent("fbeSize, err := fm.GetValue(fbeResult)");
+
6874 WriteLineIndent("return fbeResult, fbeSize, err");
+
6875 Indent(-1);
+
6876 WriteLineIndent("}");
+
6877 WriteLine();
+
6878 WriteLineIndent("// Get the struct value by the given pointer");
+
6879 WriteLineIndent("func (fm *" + final_model_name + ") GetValue(fbeValue *" + struct_name + ") (int, error) {");
+
6880 Indent(1);
+
6881 WriteLineIndent("fm.buffer.Shift(fm.FBEOffset())");
+
6882 WriteLineIndent("fbeSize, err := fm.GetFields(fbeValue)");
+
6883 WriteLineIndent("fm.buffer.Unshift(fm.FBEOffset())");
+
6884 WriteLineIndent("return fbeSize, err");
+
6885 Indent(-1);
+
6886 WriteLineIndent("}");
+
6887 WriteLine();
+
6888 WriteLineIndent("// Get the struct fields values");
+
6889 WriteLineIndent("func (fm *" + final_model_name + ") GetFields(fbeValue *" + struct_name + ") (int, error) {");
+
6890 Indent(1);
+
6891 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
6892 {
+
6893 WriteLineIndent("var err error = nil");
+
6894 WriteLineIndent("fbeCurrentSize := 0");
+
6895 WriteLineIndent("fbeCurrentOffset := 0");
+
6896 WriteLineIndent("fbeFieldSize := 0");
+
6897 if (!base_type.empty())
+
6898 {
+
6899 WriteLine();
+
6900 WriteLineIndent("fm." + base_final_name + ".SetFBEOffset(fbeCurrentOffset)");
+
6901 WriteLineIndent("if fbeFieldSize, err = fm." + base_final_name + ".GetFields(fbeValue." + ConvertBaseName(base_type) + "); err != nil {");
+
6902 Indent(1);
+
6903 WriteLineIndent("return fbeCurrentSize, err");
+
6904 Indent(-1);
+
6905 WriteLineIndent("}");
+
6906 WriteLineIndent("fbeCurrentOffset += fbeFieldSize");
+
6907 WriteLineIndent("fbeCurrentSize += fbeFieldSize");
+
6908 }
+
6909 if (s->body)
+
6910 {
+
6911 for (const auto& field : s->body->fields)
+
6912 {
+
6913 WriteLine();
+
6914 WriteLineIndent("fm." + ConvertToUpper(*field->name) + ".SetFBEOffset(fbeCurrentOffset)");
+
6915 if (field->array)
+
6916 WriteLineIndent("if slice, size, err := fm." + ConvertToUpper(*field->name) + ".Get(); err != nil {");
+
6917 else if (field->vector || field->list || field->set || field->map || field->hash || field->optional)
+
6918 WriteLineIndent("if fbeValue." + ConvertToUpper(*field->name) + ", fbeFieldSize, err = fm." + ConvertToUpper(*field->name) + ".Get(); err != nil {");
+
6919 else if (!IsGoType(*field->type))
+
6920 WriteLineIndent("if fbeFieldSize, err = fm." + ConvertToUpper(*field->name) + ".GetValue(&fbeValue." + ConvertToUpper(*field->name) + "); err != nil {");
+
6921 else
+
6922 WriteLineIndent("if fbeValue." + ConvertToUpper(*field->name) + ", fbeFieldSize, err = fm." + ConvertToUpper(*field->name) + ".Get(); err != nil {");
+
6923 Indent(1);
+
6924 WriteLineIndent("return fbeCurrentSize, err");
+
6925 Indent(-1);
+
6926 if (field->array)
+
6927 {
+
6928 WriteLineIndent("} else {");
+
6929 Indent(1);
+
6930 WriteLineIndent("copy(fbeValue." + ConvertToUpper(*field->name) + "[:], slice)");
+
6931 WriteLineIndent("fbeFieldSize = size");
+
6932 Indent(-1);
+
6933 }
+
6934 WriteLineIndent("}");
+
6935 WriteLineIndent("fbeCurrentOffset += fbeFieldSize");
+
6936 WriteLineIndent("fbeCurrentSize += fbeFieldSize");
+
6937 }
+
6938 }
+
6939 WriteLine();
+
6940 WriteLineIndent("return fbeCurrentSize, err");
+
6941 }
+
6942 else
+
6943 WriteLineIndent("return 0, nil");
+
6944 Indent(-1);
+
6945 WriteLineIndent("}");
+
6946
+
6947 // Generate struct final model Set() methods
+
6948 WriteLine();
+
6949 WriteLineIndent("// Set the struct value");
+
6950 WriteLineIndent("func (fm *" + final_model_name + ") Set(fbeValue *" + struct_name + ") (int, error) {");
+
6951 Indent(1);
+
6952 WriteLineIndent("fm.buffer.Shift(fm.FBEOffset())");
+
6953 WriteLineIndent("fbeResult, err := fm.SetFields(fbeValue)");
+
6954 WriteLineIndent("fm.buffer.Unshift(fm.FBEOffset())");
+
6955 WriteLineIndent("return fbeResult, err");
+
6956 Indent(-1);
+
6957 WriteLineIndent("}");
+
6958 WriteLine();
+
6959 WriteLineIndent("// Set the struct fields values");
+
6960 WriteLineIndent("func (fm *" + final_model_name + ") SetFields(fbeValue *" + struct_name + ") (int, error) {");
+
6961 Indent(1);
+
6962 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
6963 {
+
6964 WriteLineIndent("var err error = nil");
+
6965 WriteLineIndent("fbeCurrentSize := 0");
+
6966 WriteLineIndent("fbeCurrentOffset := 0");
+
6967 WriteLineIndent("fbeFieldSize := 0");
+
6968 if (!base_type.empty())
+
6969 {
+
6970 WriteLine();
+
6971 WriteLineIndent("fm." + base_final_name + ".SetFBEOffset(fbeCurrentOffset)");
+
6972 WriteLineIndent("if fbeFieldSize, err = fm." + base_final_name + ".SetFields(fbeValue." + ConvertBaseName(base_type) + "); err != nil {");
+
6973 Indent(1);
+
6974 WriteLineIndent("return fbeCurrentSize, err");
+
6975 Indent(-1);
+
6976 WriteLineIndent("}");
+
6977 WriteLineIndent("fbeCurrentOffset += fbeFieldSize");
+
6978 WriteLineIndent("fbeCurrentSize += fbeFieldSize");
+
6979 }
+
6980 if (s->body)
+
6981 {
+
6982 for (const auto& field : s->body->fields)
+
6983 {
+
6984 WriteLine();
+
6985 WriteLineIndent("fm." + ConvertToUpper(*field->name) + ".SetFBEOffset(fbeCurrentOffset)");
+
6986 if (field->array)
+
6987 WriteLineIndent("if fbeFieldSize, err = fm." + ConvertToUpper(*field->name) + ".Set(fbeValue." + ConvertToUpper(*field->name) + "[:]); err != nil {");
+
6988 else
+
6989 WriteLineIndent("if fbeFieldSize, err = fm." + ConvertToUpper(*field->name) + ".Set(" + ((IsGoType(*field->type) || field->vector || field->list || field->set || field->map || field->hash || field->optional) ? "" : "&") + "fbeValue." + ConvertToUpper(*field->name) + "); err != nil {");
+
6990 Indent(1);
+
6991 WriteLineIndent("return fbeCurrentSize, err");
+
6992 Indent(-1);
+
6993 WriteLineIndent("}");
+
6994 WriteLineIndent("fbeCurrentOffset += fbeFieldSize");
+
6995 WriteLineIndent("fbeCurrentSize += fbeFieldSize");
+
6996 }
+
6997 }
+
6998 WriteLine();
+
6999 WriteLineIndent("return fbeCurrentSize, err");
+
7000 }
+
7001 else
+
7002 WriteLineIndent("return 0, nil");
+
7003 Indent(-1);
+
7004 WriteLineIndent("}");
+
7005
+
7006 // Generate footer
+
7007 GenerateFooter();
+
7008
+
7009 // Store the output file
+
7010 WriteEnd();
+
7011 Store(output);
+
7012}
+
7013
+
7014void GeneratorGo::GenerateStructModelFinal(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s, const CppCommon::Path& path)
+
7015{
+
7016 std::string struct_name = ConvertToUpper(*s->name);
+
7017 std::string model_name = struct_name + "FinalModel";
+
7018 std::string final_model_name = "FinalModel" + struct_name;
+
7019
+
7020 // Generate the output file
+
7021 CppCommon::Path output = path / (model_name + ".go");
+
7022 WriteBegin();
+
7023
+
7024 // Generate header
+
7025 GenerateHeader(CppCommon::Path(_input).filename().string());
+
7026
+
7027 // Generate package
+
7028 WriteLine();
+
7029 WriteLineIndent("package " + *p->name);
+
7030
+
7031 // Generate imports
+
7032 WriteLine();
+
7033 GenerateImports(p);
+
7034
+
7035 // Generate struct model final type
+
7036 WriteLine();
+
7037 WriteLineIndent("// Fast Binary Encoding " + struct_name + " final model");
+
7038 WriteLineIndent("type " + model_name + " struct {");
+
7039 Indent(1);
+
7040 WriteLineIndent("// Model buffer");
+
7041 WriteLineIndent("buffer *fbe.Buffer");
+
7042 WriteLine();
+
7043 WriteLineIndent("// Final model");
+
7044 WriteLineIndent("model *" + final_model_name);
+
7045 Indent(-1);
+
7046 WriteLineIndent("}");
+
7047
+
7048 // Generate struct model final constructor
+
7049 WriteLine();
+
7050 WriteLineIndent("// Create a new " + struct_name + " final model");
+
7051 WriteLineIndent("func New" + model_name + "(buffer *fbe.Buffer) *" + model_name + " {");
+
7052 Indent(1);
+
7053 WriteLineIndent("return &" + model_name + "{buffer: buffer, model: New" + final_model_name + "(buffer, 8)}");
+
7054 Indent(-1);
+
7055 WriteLineIndent("}");
+
7056
+
7057 // Generate struct model final Buffer() & Model() methods
+
7058 WriteLine();
+
7059 WriteLineIndent("// Get the final model buffer");
+
7060 WriteLineIndent("func (m *" + model_name + ") Buffer() *fbe.Buffer { return m.buffer }");
+
7061 WriteLineIndent("// Get the final model");
+
7062 WriteLineIndent("func (m *" + model_name + ") Model() *" + final_model_name + " { return m.model }");
+
7063
+
7064 // Generate struct model final FBEType() method
+
7065 WriteLine();
+
7066 WriteLineIndent("// // Get the final model type");
+
7067 WriteLineIndent("func (m *" + model_name + ") FBEType() int { return m.model.FBEType() }");
+
7068
+
7069 // Generate struct model final Verify() method
+
7070 WriteLine();
+
7071 WriteLineIndent("// Check if the struct value is valid");
+
7072 WriteLineIndent("func (m *" + model_name + ") Verify() bool {");
+
7073 Indent(1);
+
7074 WriteLineIndent("if (m.buffer.Offset() + m.model.FBEOffset() - 4) > m.buffer.Size() {");
+
7075 Indent(1);
+
7076 WriteLineIndent("return false");
+
7077 Indent(-1);
+
7078 WriteLineIndent("}");
+
7079 WriteLine();
+
7080 WriteLineIndent("fbeStructSize := int(fbe.ReadUInt32(m.buffer.Data(), m.buffer.Offset() + m.model.FBEOffset() - 8))");
+
7081 WriteLineIndent("fbeStructType := int(fbe.ReadUInt32(m.buffer.Data(), m.buffer.Offset() + m.model.FBEOffset() - 4))");
+
7082 WriteLineIndent("if (fbeStructSize <= 0) || (fbeStructType != m.FBEType()) {");
+
7083 Indent(1);
+
7084 WriteLineIndent("return false");
+
7085 Indent(-1);
+
7086 WriteLineIndent("}");
+
7087 WriteLine();
+
7088 WriteLineIndent("return (8 + m.model.Verify()) == fbeStructSize");
+
7089 Indent(-1);
+
7090 WriteLineIndent("}");
+
7091
+
7092 // Generate struct model final CreateBegin() method
+
7093 WriteLine();
+
7094 WriteLineIndent("// Create a new final model (begin phase)");
+
7095 WriteLineIndent("func (m *" + model_name + ") CreateBegin() int {");
+
7096 Indent(1);
+
7097 WriteLineIndent("fbeBegin := m.buffer.Allocate(4 + m.model.FBESize())");
+
7098 WriteLineIndent("return fbeBegin");
+
7099 Indent(-1);
+
7100 WriteLineIndent("}");
+
7101
+
7102 // Generate struct model final CreateEnd() method
+
7103 WriteLine();
+
7104 WriteLineIndent("// Create a new final model (end phase)");
+
7105 WriteLineIndent("func (m *" + model_name + ") CreateEnd(fbeBegin int) int {");
+
7106 Indent(1);
+
7107 WriteLineIndent("fbeEnd := m.buffer.Size()");
+
7108 WriteLineIndent("fbeFullSize := fbeEnd - fbeBegin");
+
7109 WriteLineIndent("fbe.WriteUInt32(m.buffer.Data(), m.buffer.Offset() + m.model.FBEOffset() - 4, uint32(fbeFullSize))");
+
7110 WriteLineIndent("return fbeFullSize");
+
7111 Indent(-1);
+
7112 WriteLineIndent("}");
+
7113
+
7114 // Generate struct model final Serialize() method
+
7115 WriteLine();
+
7116 WriteLineIndent("// Serialize the struct value");
+
7117 WriteLineIndent("func (m *" + model_name + ") Serialize(value *" + struct_name + ") (int, error) {");
+
7118 Indent(1);
+
7119 WriteLineIndent("fbeInitialSize := m.buffer.Size()");
+
7120 WriteLine();
+
7121 WriteLineIndent("fbeStructType := m.FBEType()");
+
7122 WriteLineIndent("fbeStructSize := 8 + m.model.FBEAllocationSize(value)");
+
7123 WriteLineIndent("fbeStructOffset := m.buffer.Allocate(fbeStructSize) - m.buffer.Offset()");
+
7124 WriteLineIndent("if (m.buffer.Offset() + fbeStructOffset + fbeStructSize) > m.buffer.Size() {");
+
7125 Indent(1);
+
7126 WriteLineIndent("return 0, errors.New(\"model is broken\")");
+
7127 Indent(-1);
+
7128 WriteLineIndent("}");
+
7129 WriteLine();
+
7130 WriteLineIndent("fbeStructSize, err := m.model.Set(value)");
+
7131 WriteLineIndent("fbeStructSize += 8");
+
7132 WriteLineIndent("m.buffer.Resize(fbeInitialSize + fbeStructSize)");
+
7133 WriteLine();
+
7134 WriteLineIndent("fbe.WriteUInt32(m.buffer.Data(), m.buffer.Offset() + m.model.FBEOffset() - 8, uint32(fbeStructSize))");
+
7135 WriteLineIndent("fbe.WriteUInt32(m.buffer.Data(), m.buffer.Offset() + m.model.FBEOffset() - 4, uint32(fbeStructType))");
+
7136 WriteLine();
+
7137 WriteLineIndent("return fbeStructSize, err");
+
7138 Indent(-1);
+
7139 WriteLineIndent("}");
+
7140
+
7141 // Generate struct model final Deserialize() method
+
7142 WriteLine();
+
7143 WriteLineIndent("// Deserialize the struct value");
+
7144 WriteLineIndent("func (m *" + model_name + ") Deserialize() (*" + struct_name + ", int, error) {");
+
7145 Indent(1);
+
7146 WriteLineIndent("value := New" + struct_name + "()");
+
7147 WriteLineIndent("fbeFullSize, err := m.DeserializeValue(value)");
+
7148 WriteLineIndent("return value, fbeFullSize, err");
+
7149 Indent(-1);
+
7150 WriteLineIndent("}");
+
7151
+
7152 // Generate struct model final DeserializeValue() method
+
7153 WriteLine();
+
7154 WriteLineIndent("// Deserialize the struct value by the given pointer");
+
7155 WriteLineIndent("func (m *" + model_name + ") DeserializeValue(value *" + struct_name + ") (int, error) {");
+
7156 Indent(1);
+
7157 WriteLineIndent("if (m.buffer.Offset() + m.model.FBEOffset()) > m.buffer.Size() {");
+
7158 Indent(1);
+
7159 WriteLineIndent("value = New" + struct_name + "()");
+
7160 WriteLineIndent("return 0, errors.New(\"model is broken\")");
+
7161 Indent(-1);
+
7162 WriteLineIndent("}");
+
7163 WriteLine();
+
7164 WriteLineIndent("fbeStructSize := int(fbe.ReadUInt32(m.buffer.Data(), m.buffer.Offset() + m.model.FBEOffset() - 8))");
+
7165 WriteLineIndent("fbeStructType := int(fbe.ReadUInt32(m.buffer.Data(), m.buffer.Offset() + m.model.FBEOffset() - 4))");
+
7166 WriteLineIndent("if (fbeStructSize <= 0) || (fbeStructType != m.FBEType()) {");
+
7167 Indent(1);
+
7168 WriteLineIndent("value = New" + struct_name + "()");
+
7169 WriteLineIndent("return 8, errors.New(\"model is broken\")");
+
7170 Indent(-1);
+
7171 WriteLineIndent("}");
+
7172 WriteLine();
+
7173 WriteLineIndent("fbeStructSize, err := m.model.GetValue(value)");
+
7174 WriteLineIndent("return 8 + fbeStructSize, err");
+
7175 Indent(-1);
+
7176 WriteLineIndent("}");
+
7177
+
7178 // Generate struct model final Next() method
+
7179 WriteLine();
+
7180 WriteLineIndent("// Move to the next struct value");
+
7181 WriteLineIndent("func (m *" + model_name + ") Next(prev int) {");
+
7182 Indent(1);
+
7183 WriteLineIndent("m.model.FBEShift(prev)");
+
7184 Indent(-1);
+
7185 WriteLineIndent("}");
+
7186
+
7187 // Generate footer
+
7188 GenerateFooter();
+
7189
+
7190 // Store the output file
+
7191 WriteEnd();
+
7192 Store(output);
+
7193}
+
7194
+
7195void GeneratorGo::GenerateProtocolVersion(const std::shared_ptr<Package>& p, const CppCommon::Path& path)
+
7196{
+
7197 // Generate the output file
+
7198 CppCommon::Path output = path / "ProtocolVersion.go";
+
7199 WriteBegin();
+
7200
+
7201 // Generate header
+
7202 GenerateHeader(CppCommon::Path(_input).filename().string());
+
7203
+
7204 // Generate package
+
7205 WriteLine();
+
7206 WriteLineIndent("package " + *p->name);
+
7207
+
7208 // Generate protocol version constants
+
7209 WriteLine();
+
7210 WriteLineIndent("// Protocol major version");
+
7211 WriteLineIndent("const ProtocolVersionMajor = " + std::to_string(p->version->major));
+
7212 WriteLineIndent("// Protocol minor version");
+
7213 WriteLineIndent("const ProtocolVersionMinor = " + std::to_string(p->version->minor));
+
7214
+
7215 // Generate footer
+
7216 GenerateFooter();
+
7217
+
7218 // Store the output file
+
7219 WriteEnd();
+
7220 Store(output);
+
7221}
+
7222
+
7223void GeneratorGo::GenerateSender(const std::shared_ptr<Package>& p, const CppCommon::Path& path, bool final)
+
7224{
+
7225 std::string sender_name = std::string(final ? "Final" : "") + "Sender";
+
7226
+
7227 // Generate the output file
+
7228 CppCommon::Path output = path / (sender_name + ".go");
+
7229 WriteBegin();
+
7230
+
7231 // Generate header
+
7232 GenerateHeader(CppCommon::Path(_input).filename().string());
+
7233
+
7234 // Generate package
+
7235 WriteLine();
+
7236 WriteLineIndent("package " + *p->name);
+
7237
+
7238 // Generate imports
+
7239 WriteLine();
+
7240 GenerateImports(p);
+
7241
+
7242 // Generate sender type
+
7243 WriteLine();
+
7244 WriteLineIndent("// Fast Binary Encoding " + *p->name + (final ? " final " : " ") + "sender");
+
7245 WriteLineIndent("type " + sender_name + " struct {");
+
7246 Indent(1);
+
7247 WriteLineIndent("*fbe.Sender");
+
7248 if (p->body)
+
7249 {
+
7250 if (p->import)
+
7251 for (const auto& import : p->import->imports)
+
7252 WriteLineIndent(ConvertToLower(*import) + "Sender *" + *import + (final ? ".Final" : ".") + "Sender");
+
7253 for (const auto& s : p->body->structs)
+
7254 if (s->message)
+
7255 WriteLineIndent(ConvertToLower(*s->name) + "Model *" + ConvertToUpper(*s->name) + (final ? "Final" : "") + "Model");
+
7256 }
+
7257 Indent(-1);
+
7258 WriteLineIndent("}");
+
7259
+
7260 // Generate sender constructor
+
7261 WriteLine();
+
7262 WriteLineIndent("// Create a new " + *p->name + (final ? " final " : " ") + "sender with an empty buffer");
+
7263 WriteLineIndent("func New" + sender_name + "() *" + sender_name + " {");
+
7264 Indent(1);
+
7265 WriteLineIndent("return New" + sender_name + "WithBuffer(fbe.NewEmptyBuffer())");
+
7266 Indent(-1);
+
7267 WriteLineIndent("}");
+
7268 WriteLine();
+
7269 WriteLineIndent("// Create a new " + *p->name + (final ? " final " : " ") + "sender with the given buffer");
+
7270 WriteLineIndent("func New" + sender_name + "WithBuffer(buffer *fbe.Buffer) *" + sender_name + " {");
+
7271 Indent(1);
+
7272 WriteLineIndent("return &" + sender_name + "{");
+
7273 Indent(1);
+
7274 WriteLineIndent("fbe.NewSender(buffer, " + std::string(final ? "true" : "false") + "),");
+
7275 if (p->body)
+
7276 {
+
7277 if (p->import)
+
7278 for (const auto& import : p->import->imports)
+
7279 WriteLineIndent(*import + ".New" + (final ? "Final" : "") + "SenderWithBuffer(buffer),");
+
7280 for (const auto& s : p->body->structs)
+
7281 if (s->message)
+
7282 WriteLineIndent("New" + ConvertToUpper(*s->name) + (final ? "Final" : "") + "Model(buffer),");
+
7283 }
+
7284 Indent(-1);
+
7285 WriteLineIndent("}");
+
7286 Indent(-1);
+
7287 WriteLineIndent("}");
+
7288
+
7289 // Generate sender imported senders
+
7290 if (p->import)
+
7291 {
+
7292 WriteLine();
+
7293 WriteLineIndent("// Imported senders");
+
7294 WriteLine();
+
7295 for (const auto& import : p->import->imports)
+
7296 WriteLineIndent("func (s *" + sender_name + ") " + ConvertToUpper(*import) + "Sender" + "() *" + *import + (final ? ".Final" : ".") + "Sender" + " { return s." + ConvertToLower(*import) + "Sender" + " }");
+
7297 }
+
7298
+
7299 // Generate sender models accessors
+
7300 WriteLine();
+
7301 WriteLineIndent("// Sender models accessors");
+
7302 WriteLine();
+
7303 if (p->body)
+
7304 for (const auto& s : p->body->structs)
+
7305 if (s->message)
+
7306 WriteLineIndent("func (s *" + sender_name + ") " + ConvertToUpper(*s->name) + "Model" + "() *" + ConvertToUpper(*s->name) + (final ? "Final" : "") + "Model" + " { return s." + ConvertToLower(*s->name) + "Model" + " }");
+
7307
+
7308 // Generate sender methods
+
7309 WriteLine();
+
7310 WriteLineIndent("// Send methods");
+
7311 WriteLine();
+
7312 WriteLineIndent("func (s *" + sender_name + ") Send(value interface{}) (int, error) {");
+
7313 Indent(1);
+
7314 if (p->body)
+
7315 {
+
7316 WriteLineIndent("switch value := value.(type) {");
+
7317 for (const auto& s : p->body->structs)
+
7318 {
+
7319 if (s->message)
+
7320 {
+
7321 WriteLineIndent("case *" + ConvertToUpper(*s->name) + ":");
+
7322 Indent(1);
+
7323 WriteLineIndent("if value.FBEType() == s." + ConvertToLower(*s->name) + "Model.FBEType() {");
+
7324 Indent(1);
+
7325 WriteLineIndent("return s.Send" + ConvertToUpper(*s->name) + "(value)");
+
7326 Indent(-1);
+
7327 WriteLineIndent("}");
+
7328 Indent(-1);
+
7329 }
+
7330 }
+
7331 WriteLineIndent("default:");
+
7332 Indent(1);
+
7333 WriteLineIndent("_ = value");
+
7334 WriteLineIndent("break");
+
7335 Indent(-1);
+
7336 WriteLineIndent("}");
+
7337 if (p->import)
+
7338 {
+
7339 for (const auto& import : p->import->imports)
+
7340 {
+
7341 WriteLineIndent("if result, err := s." + ConvertToLower(*import) + "Sender.Send(value); (result > 0) || (err != nil) {");
+
7342 Indent(1);
+
7343 WriteLineIndent("return result, err");
+
7344 Indent(-1);
+
7345 WriteLineIndent("}");
+
7346 }
+
7347 }
+
7348 }
+
7349 WriteLineIndent("return 0, nil");
+
7350 Indent(-1);
+
7351 WriteLineIndent("}");
+
7352 if (p->body)
+
7353 {
+
7354 for (const auto& s : p->body->structs)
+
7355 {
+
7356 if (s->message)
+
7357 {
+
7358 WriteLine();
+
7359 WriteLineIndent("func (s *" + sender_name + ") Send" + ConvertToUpper(*s->name) + "(value *" + ConvertToUpper(*s->name) + ") (int, error) {");
+
7360 Indent(1);
+
7361 WriteLineIndent("// Serialize the value into the FBE stream");
+
7362 WriteLineIndent("serialized, err := s." + ConvertToLower(*s->name) + "Model.Serialize(value)");
+
7363 WriteLineIndent("if serialized <= 0 {");
+
7364 Indent(1);
+
7365 WriteLineIndent("return 0, errors.New(\"" + *p->name + "." + *s->name + " serialization failed\")");
+
7366 Indent(-1);
+
7367 WriteLineIndent("}");
+
7368 WriteLineIndent("if err != nil {");
+
7369 Indent(1);
+
7370 WriteLineIndent("return 0, err");
+
7371 Indent(-1);
+
7372 WriteLineIndent("}");
+
7373 WriteLineIndent("if !s." + ConvertToLower(*s->name) + "Model.Verify() {");
+
7374 Indent(1);
+
7375 WriteLineIndent("return 0, errors.New(\"" + *p->name + "." + *s->name + " validation failed\")");
+
7376 Indent(-1);
+
7377 WriteLineIndent("}");
+
7378 WriteLine();
+
7379 WriteLineIndent("// Log the value");
+
7380 WriteLineIndent("if s.Logging() {");
+
7381 Indent(1);
+
7382 WriteLineIndent("message := value.String()");
+
7383 WriteLineIndent("s.HandlerOnSendLog.OnSendLog(message)");
+
7384 Indent(-1);
+
7385 WriteLineIndent("}");
+
7386 WriteLine();
+
7387 WriteLineIndent("// Send the serialized value");
+
7388 WriteLineIndent("return s.SendSerialized(serialized)");
+
7389 Indent(-1);
+
7390 WriteLineIndent("}");
+
7391 }
+
7392 }
+
7393 }
+
7394
+
7395 // Generate footer
+
7396 GenerateFooter();
+
7397
+
7398 // Store the output file
+
7399 WriteEnd();
+
7400 Store(output);
+
7401}
+
7402
+
7403void GeneratorGo::GenerateReceiver(const std::shared_ptr<Package>& p, const CppCommon::Path& path, bool final)
+
7404{
+
7405 std::string receiver_name = std::string(final ? "Final" : "") + "Receiver";
+
7406
+
7407 // Generate the output file
+
7408 CppCommon::Path output = path / (receiver_name + ".go");
+
7409 WriteBegin();
+
7410
+
7411 // Generate header
+
7412 GenerateHeader(CppCommon::Path(_input).filename().string());
+
7413
+
7414 // Generate package
+
7415 WriteLine();
+
7416 WriteLineIndent("package " + *p->name);
+
7417
+
7418 // Generate imports
+
7419 WriteLine();
+
7420 GenerateImports(p);
+
7421
+
7422 // Generate receiver interfaces
+
7423 if (!final && p->body)
+
7424 {
+
7425 for (const auto& s : p->body->structs)
+
7426 {
+
7427 if (s->message)
+
7428 {
+
7429 std::string struct_name = ConvertToUpper(*s->name);
+
7430 WriteLine();
+
7431 WriteLineIndent("// Receive " + *s->name + " interface");
+
7432 WriteLineIndent("type OnReceive" + struct_name + " interface {");
+
7433 Indent(1);
+
7434 WriteLineIndent("OnReceive" + struct_name + "(value *" + struct_name + ")");
+
7435 Indent(-1);
+
7436 WriteLineIndent("}");
+
7437 WriteLine();
+
7438 WriteLineIndent("// Receive " + *s->name + " function");
+
7439 WriteLineIndent("type OnReceive" + struct_name + "Func func(value *" + struct_name + ")");
+
7440 WriteLineIndent("func (f OnReceive" + struct_name + "Func) OnReceive" + struct_name + "(value *" + struct_name + ") {");
+
7441 Indent(1);
+
7442 WriteLineIndent("f(value)");
+
7443 Indent(-1);
+
7444 WriteLineIndent("}");
+
7445 }
+
7446 }
+
7447 }
+
7448
+
7449 // Generate receiver type
+
7450 WriteLine();
+
7451 WriteLineIndent("// Fast Binary Encoding " + *p->name + (final ? " final " : " ") + "receiver");
+
7452 WriteLineIndent("type " + receiver_name + " struct {");
+
7453 Indent(1);
+
7454 WriteLineIndent("*fbe.Receiver");
+
7455 if (p->import)
+
7456 for (const auto& import : p->import->imports)
+
7457 WriteLineIndent(ConvertToLower(*import) + "Receiver *" + *import + (final ? ".Final" : ".") + "Receiver");
+
7458 if (p->body)
+
7459 {
+
7460 for (const auto& s : p->body->structs)
+
7461 {
+
7462 if (s->message)
+
7463 {
+
7464 WriteLineIndent(ConvertToLower(*s->name) + "Value *" + ConvertToUpper(*s->name));
+
7465 WriteLineIndent(ConvertToLower(*s->name) + "Model *" + ConvertToUpper(*s->name) + (final ? "Final" : "") + "Model");
+
7466 }
+
7467 }
+
7468
+
7469 WriteLine();
+
7470 for (const auto& s : p->body->structs)
+
7471 {
+
7472 if (s->message)
+
7473 {
+
7474 std::string struct_name = ConvertToUpper(*s->name);
+
7475 WriteLineIndent("// Receive " + *s->name + " handler");
+
7476 WriteLineIndent("HandlerOnReceive" + struct_name + " OnReceive" + struct_name);
+
7477 }
+
7478 }
+
7479 }
+
7480 Indent(-1);
+
7481 WriteLineIndent("}");
+
7482
+
7483 // Generate receiver constructor
+
7484 WriteLine();
+
7485 WriteLineIndent("// Create a new " + *p->name + (final ? " final " : " ") + "receiver with an empty buffer");
+
7486 WriteLineIndent("func New" + receiver_name + "() *" + receiver_name + " {");
+
7487 Indent(1);
+
7488 WriteLineIndent("return New" + receiver_name + "WithBuffer(fbe.NewEmptyBuffer())");
+
7489 Indent(-1);
+
7490 WriteLineIndent("}");
+
7491 WriteLine();
+
7492 WriteLineIndent("// Create a new " + *p->name + (final ? " final " : " ") + "receiver with the given buffer");
+
7493 WriteLineIndent("func New" + receiver_name + "WithBuffer(buffer *fbe.Buffer) *" + receiver_name + " {");
+
7494 Indent(1);
+
7495 WriteLineIndent("receiver := &" + receiver_name + "{");
+
7496 Indent(1);
+
7497 WriteLineIndent("fbe.NewReceiver(buffer, " + std::string(final ? "true" : "false") + "),");
+
7498 if (p->import)
+
7499 for (const auto& import : p->import->imports)
+
7500 WriteLineIndent(*import + ".New" + (final ? "Final" : "") + "ReceiverWithBuffer(buffer),");
+
7501 if (p->body)
+
7502 {
+
7503 for (const auto& s : p->body->structs)
+
7504 {
+
7505 if (s->message)
+
7506 {
+
7507 WriteLineIndent("New" + ConvertToUpper(*s->name) + "(),");
+
7508 WriteLineIndent("New" + ConvertToUpper(*s->name) + (final ? "Final" : "") + "Model(buffer),");
+
7509 }
+
7510 }
+
7511 for (size_t i = 0; i < p->body->structs.size(); ++i)
+
7512 if (p->body->structs[i]->message)
+
7513 WriteLineIndent("nil,");
+
7514 }
+
7515 Indent(-1);
+
7516 WriteLineIndent("}");
+
7517 WriteLineIndent("receiver.SetupHandlerOnReceive(receiver)");
+
7518 for (const auto& s : p->body->structs)
+
7519 if (s->message)
+
7520 WriteLineIndent("receiver.SetupHandlerOnReceive" + ConvertToUpper(*s->name) + "Func(func(value *" + ConvertToUpper(*s->name) + ") {})");
+
7521 WriteLineIndent("return receiver");
+
7522 Indent(-1);
+
7523 WriteLineIndent("}");
+
7524
+
7525 if (p->import)
+
7526 {
+
7527 // Generate receiver imports
+
7528 WriteLine();
+
7529 WriteLineIndent("// Imported receivers");
+
7530 WriteLine();
+
7531 for (const auto& import : p->import->imports)
+
7532 {
+
7533 WriteLineIndent("// Get the " + *import + " receiver");
+
7534 WriteLineIndent("func (r *" + receiver_name + ") " + ConvertToUpper(*import) + "Receiver() *" + *import + (final ? ".Final" : ".") + "Receiver { return r." + ConvertToLower(*import) + "Receiver }");
+
7535 WriteLineIndent("// Set the " + *import + " receiver");
+
7536 WriteLineIndent("func (r *" + receiver_name + ") Set" + ConvertToUpper(*import) + "Receiver(receiver *" + *import + (final ? ".Final" : ".") + "Receiver) { r." + ConvertToLower(*import) + "Receiver = receiver }");
+
7537 }
+
7538 }
+
7539
+
7540 // Generate receiver setup handlers
+
7541 WriteLine();
+
7542 WriteLineIndent("// Setup handlers");
+
7543 WriteLineIndent("func (r *" + receiver_name + ") SetupHandlers(handlers interface{}) {");
+
7544 Indent(1);
+
7545 WriteLineIndent("r.Receiver.SetupHandlers(handlers)");
+
7546 if (p->import)
+
7547 for (const auto& import : p->import->imports)
+
7548 WriteLineIndent("r." + ConvertToLower(*import) + "Receiver.SetupHandlers(handlers)");
+
7549 if (p->body)
+
7550 {
+
7551 for (const auto& s : p->body->structs)
+
7552 {
+
7553 if (s->message)
+
7554 {
+
7555 std::string struct_name = ConvertToUpper(*s->name);
+
7556 WriteLineIndent("if handler, ok := handlers.(OnReceive" + struct_name + "); ok {");
+
7557 Indent(1);
+
7558 WriteLineIndent("r.SetupHandlerOnReceive" + struct_name + "(handler)");
+
7559 Indent(-1);
+
7560 WriteLineIndent("}");
+
7561 }
+
7562 }
+
7563 }
+
7564 Indent(-1);
+
7565 WriteLineIndent("}");
+
7566 if (p->body)
+
7567 {
+
7568 WriteLine();
+
7569 for (const auto& s : p->body->structs)
+
7570 {
+
7571 if (s->message)
+
7572 {
+
7573 std::string struct_name = ConvertToUpper(*s->name);
+
7574 WriteLineIndent("// Setup receive " + *s->name + " handler");
+
7575 WriteLineIndent("func (r *" + receiver_name + ") SetupHandlerOnReceive" + struct_name + "(handler OnReceive" + struct_name + ") { r.HandlerOnReceive" + struct_name + " = handler }");
+
7576 WriteLineIndent("// Setup receive " + *s->name + " handler function");
+
7577 WriteLineIndent("func (r *" + receiver_name + ") SetupHandlerOnReceive" + struct_name + "Func(function func(value *" + struct_name + ")) { r.HandlerOnReceive" + struct_name + " = OnReceive" + struct_name + "Func(function) }");
+
7578 }
+
7579 }
+
7580 }
+
7581
+
7582
+
7583 // Generate receiver message handler
+
7584 WriteLine();
+
7585 WriteLineIndent("// Receive message handler");
+
7586 WriteLineIndent("func (r *" + receiver_name + ") OnReceive(fbeType int, buffer []byte) (bool, error) {");
+
7587 Indent(1);
+
7588 if (p->body)
+
7589 {
+
7590 WriteLineIndent("switch fbeType {");
+
7591 for (const auto& s : p->body->structs)
+
7592 {
+
7593 if (s->message)
+
7594 {
+
7595 std::string struct_name = ConvertToUpper(*s->name);
+
7596 std::string struct_model = ConvertToLower(*s->name) + "Model";
+
7597 std::string struct_value = ConvertToLower(*s->name) + "Value";
+
7598 WriteLineIndent("case r." + struct_model + ".FBEType():");
+
7599 Indent(1);
+
7600 WriteLineIndent("// Deserialize the value from the FBE stream");
+
7601 WriteLineIndent("r." + struct_model + ".Buffer().Attach(buffer)");
+
7602 WriteLineIndent("if !r." + struct_model + ".Verify() {");
+
7603 Indent(1);
+
7604 WriteLineIndent("return false, errors.New(\"" + *p->name + "." + *s->name + " validation failed\")");
+
7605 Indent(-1);
+
7606 WriteLineIndent("}");
+
7607 WriteLineIndent("deserialized, err := r." + struct_model + ".DeserializeValue(r." + struct_value + ")");
+
7608 WriteLineIndent("if deserialized <= 0 {");
+
7609 Indent(1);
+
7610 WriteLineIndent("return false, errors.New(\"" + *p->name + "." + *s->name + " deserialization failed\")");
+
7611 Indent(-1);
+
7612 WriteLineIndent("}");
+
7613 WriteLineIndent("if err != nil {");
+
7614 Indent(1);
+
7615 WriteLineIndent("return false, err");
+
7616 Indent(-1);
+
7617 WriteLineIndent("}");
+
7618 WriteLine();
+
7619 WriteLineIndent("// Log the value");
+
7620 WriteLineIndent("if r.Logging() {");
+
7621 Indent(1);
+
7622 WriteLineIndent("message := r." + struct_value + ".String()");
+
7623 WriteLineIndent("r.HandlerOnReceiveLog.OnReceiveLog(message)");
+
7624 Indent(-1);
+
7625 WriteLineIndent("}");
+
7626 WriteLine();
+
7627 WriteLineIndent("// Call receive handler with deserialized value");
+
7628 WriteLineIndent("r.HandlerOnReceive" + struct_name + ".OnReceive" + struct_name + "(r." + struct_value + ")");
+
7629 WriteLineIndent("return true, nil");
+
7630 Indent(-1);
+
7631 }
+
7632 }
+
7633 WriteLineIndent("default:");
+
7634 Indent(1);
+
7635 WriteLineIndent("_ = fbeType");
+
7636 WriteLineIndent("break");
+
7637 Indent(-1);
+
7638 WriteLineIndent("}");
+
7639 }
+
7640 if (p->import)
+
7641 {
+
7642 WriteLine();
+
7643 for (const auto& import : p->import->imports)
+
7644 {
+
7645 WriteLineIndent("if r." + ConvertToLower(*import) + "Receiver != nil {");
+
7646 Indent(1);
+
7647 WriteLineIndent("if ok, err := r." + ConvertToLower(*import) + "Receiver.OnReceive(fbeType, buffer); ok {");
+
7648 Indent(1);
+
7649 WriteLineIndent("return ok, err");
+
7650 Indent(-1);
+
7651 WriteLineIndent("}");
+
7652 Indent(-1);
+
7653 WriteLineIndent("}");
+
7654 }
+
7655 }
+
7656 WriteLine();
+
7657 WriteLineIndent("return false, nil");
+
7658 Indent(-1);
+
7659 WriteLineIndent("}");
+
7660
+
7661 // Generate footer
+
7662 GenerateFooter();
+
7663
+
7664 // Store the output file
+
7665 WriteEnd();
+
7666 Store(output);
+
7667}
+
7668
+
7669void GeneratorGo::GenerateProxy(const std::shared_ptr<Package>& p, const CppCommon::Path& path, bool final)
+
7670{
+
7671 std::string proxy_name = std::string(final ? "Final" : "") + "Proxy";
+
7672
+
7673 // Generate the output file
+
7674 CppCommon::Path output = path / (proxy_name + ".go");
+
7675 WriteBegin();
+
7676
+
7677 // Generate header
+
7678 GenerateHeader(CppCommon::Path(_input).filename().string());
+
7679
+
7680 // Generate package
+
7681 WriteLine();
+
7682 WriteLineIndent("package " + *p->name);
+
7683
+
7684 // Generate imports
+
7685 WriteLine();
+
7686 GenerateImports(p);
+
7687
+
7688 // Generate proxy interfaces
+
7689 if (p->body)
+
7690 {
+
7691 for (const auto& s : p->body->structs)
+
7692 {
+
7693 if (s->message)
+
7694 {
+
7695 std::string struct_name = ConvertToUpper(*s->name);
+
7696 std::string struct_model = ConvertToUpper(*s->name) + (final ? "Final" : "") + "Model";
+
7697 WriteLine();
+
7698 WriteLineIndent("// Proxy " + *s->name + " interface");
+
7699 WriteLineIndent("type OnProxy" + std::string(final ? "Final" : "") + struct_name + " interface {");
+
7700 Indent(1);
+
7701 WriteLineIndent("OnProxy" + struct_name + "(model *" + struct_model + ", fbeType int, buffer []byte)");
+
7702 Indent(-1);
+
7703 WriteLineIndent("}");
+
7704 WriteLine();
+
7705 WriteLineIndent("// Proxy " + *s->name + " function");
+
7706 WriteLineIndent("type OnProxy" + std::string(final ? "Final" : "") + struct_name + "Func func(model *" + struct_model + ", fbeType int, buffer []byte)");
+
7707 WriteLineIndent("func (f OnProxy" + std::string(final ? "Final" : "") + struct_name + "Func) OnProxy" + struct_name + "(model *" + struct_model + ", fbeType int, buffer []byte) {");
+
7708 Indent(1);
+
7709 WriteLineIndent("f(model, fbeType, buffer)");
+
7710 Indent(-1);
+
7711 WriteLineIndent("}");
+
7712 }
+
7713 }
+
7714 }
+
7715
+
7716 // Generate proxy type
+
7717 WriteLine();
+
7718 WriteLineIndent("// Fast Binary Encoding " + *p->name + (final ? " final " : " ") + "proxy");
+
7719 WriteLineIndent("type " + proxy_name + " struct {");
+
7720 Indent(1);
+
7721 WriteLineIndent("*fbe.Receiver");
+
7722 if (p->import)
+
7723 for (const auto& import : p->import->imports)
+
7724 WriteLineIndent(ConvertToLower(*import) + "Proxy *" + *import + (final ? ".Final" : ".") + "Proxy");
+
7725 if (p->body)
+
7726 {
+
7727 for (const auto& s : p->body->structs)
+
7728 if (s->message)
+
7729 WriteLineIndent(ConvertToLower(*s->name) + "Model *" + ConvertToUpper(*s->name) + (final ? "Final" : "") + "Model");
+
7730
+
7731 WriteLine();
+
7732 for (const auto& s : p->body->structs)
+
7733 {
+
7734 if (s->message)
+
7735 {
+
7736 std::string struct_name = ConvertToUpper(*s->name);
+
7737
+
7738 WriteLineIndent("// Proxy " + *s->name + " handler");
+
7739 WriteLineIndent("HandlerOnProxy" + struct_name + " OnProxy" + std::string(final ? "Final" : "") + struct_name);
+
7740 }
+
7741 }
+
7742 }
+
7743 Indent(-1);
+
7744 WriteLineIndent("}");
+
7745
+
7746 // Generate proxy constructor
+
7747 WriteLine();
+
7748 WriteLineIndent("// Create a new " + *p->name + (final ? " final " : " ") + "proxy with an empty buffer");
+
7749 WriteLineIndent("func New" + proxy_name + "() *" + proxy_name + " {");
+
7750 Indent(1);
+
7751 WriteLineIndent("return New" + proxy_name + "WithBuffer(fbe.NewEmptyBuffer())");
+
7752 Indent(-1);
+
7753 WriteLineIndent("}");
+
7754 WriteLine();
+
7755 WriteLineIndent("// Create a new " + *p->name + (final ? " final " : " ") + "proxy with the given buffer");
+
7756 WriteLineIndent("func New" + proxy_name + "WithBuffer(buffer *fbe.Buffer) *" + proxy_name + " {");
+
7757 Indent(1);
+
7758 WriteLineIndent("proxy := &" + proxy_name + "{");
+
7759 Indent(1);
+
7760 WriteLineIndent("fbe.NewReceiver(buffer, " + std::string(final ? "true" : "false") + "),");
+
7761 if (p->import)
+
7762 for (const auto& import : p->import->imports)
+
7763 WriteLineIndent(*import + ".New" + (final ? "Final" : "") + "ProxyWithBuffer(buffer),");
+
7764 if (p->body)
+
7765 {
+
7766 for (const auto& s : p->body->structs)
+
7767 if (s->message)
+
7768 WriteLineIndent("New" + ConvertToUpper(*s->name) + (final ? "Final" : "") + "Model(buffer),");
+
7769 for (size_t i = 0; i < p->body->structs.size(); ++i)
+
7770 if (p->body->structs[i]->message)
+
7771 WriteLineIndent("nil,");
+
7772 }
+
7773 Indent(-1);
+
7774 WriteLineIndent("}");
+
7775 WriteLineIndent("proxy.SetupHandlerOnReceive(proxy)");
+
7776 for (const auto& s : p->body->structs)
+
7777 {
+
7778 if (s->message)
+
7779 {
+
7780 std::string struct_model = ConvertToUpper(*s->name) + (final ? "Final" : "") + "Model";
+
7781 WriteLineIndent("proxy.SetupHandlerOnProxy" + ConvertToUpper(*s->name) + "Func(func(model *" + struct_model + ", fbeType int, buffer []byte) {})");
+
7782 }
+
7783 }
+
7784 WriteLineIndent("return proxy");
+
7785 Indent(-1);
+
7786 WriteLineIndent("}");
+
7787
+
7788 if (p->import)
+
7789 {
+
7790 // Generate proxy imports
+
7791 WriteLine();
+
7792 WriteLineIndent("// Imported proxy");
+
7793 WriteLine();
+
7794 for (const auto& import : p->import->imports)
+
7795 {
+
7796 WriteLineIndent("// Get the " + *import + " proxy");
+
7797 WriteLineIndent("func (p *" + proxy_name + ") " + ConvertToUpper(*import) + "Proxy() *" + *import + (final ? ".Final" : ".") + "Proxy { return p." + ConvertToLower(*import) + "Proxy }");
+
7798 WriteLineIndent("// Set the " + *import + " proxy");
+
7799 WriteLineIndent("func (p *" + proxy_name + ") Set" + ConvertToUpper(*import) + "Proxy(proxy *" + *import + (final ? ".Final" : ".") + "Proxy) { p." + ConvertToLower(*import) + "Proxy = proxy }");
+
7800 }
+
7801 }
+
7802
+
7803 // Generate proxy setup handlers
+
7804 WriteLine();
+
7805 WriteLineIndent("// Setup handlers");
+
7806 WriteLineIndent("func (p *" + proxy_name + ") SetupHandlers(handlers interface{}) {");
+
7807 Indent(1);
+
7808 WriteLineIndent("p.Receiver.SetupHandlers(handlers)");
+
7809 if (p->import)
+
7810 for (const auto& import : p->import->imports)
+
7811 WriteLineIndent("p." + ConvertToLower(*import) + "Proxy.SetupHandlers(handlers)");
+
7812 if (p->body)
+
7813 {
+
7814 for (const auto& s : p->body->structs)
+
7815 {
+
7816 if (s->message)
+
7817 {
+
7818 std::string struct_name = ConvertToUpper(*s->name);
+
7819 WriteLineIndent("if handler, ok := handlers.(OnProxy" + std::string(final ? "Final" : "") + struct_name + "); ok {");
+
7820 Indent(1);
+
7821 WriteLineIndent("p.SetupHandlerOnProxy" + struct_name + "(handler)");
+
7822 Indent(-1);
+
7823 WriteLineIndent("}");
+
7824 }
+
7825 }
+
7826 }
+
7827 Indent(-1);
+
7828 WriteLineIndent("}");
+
7829 if (p->body)
+
7830 {
+
7831 WriteLine();
+
7832 for (const auto& s : p->body->structs)
+
7833 {
+
7834 if (s->message)
+
7835 {
+
7836 std::string struct_name = ConvertToUpper(*s->name);
+
7837 std::string struct_model = ConvertToUpper(*s->name) + (final ? "Final" : "") + "Model";
+
7838 WriteLineIndent("// Setup proxy " + *s->name + " handler");
+
7839 WriteLineIndent("func (p *" + proxy_name + ") SetupHandlerOnProxy" + struct_name + "(handler OnProxy" + std::string(final ? "Final" : "") + struct_name + ") { p.HandlerOnProxy" + struct_name + " = handler }");
+
7840 WriteLineIndent("// Setup proxy " + *s->name + " handler function");
+
7841 WriteLineIndent("func (p *" + proxy_name + ") SetupHandlerOnProxy" + struct_name + "Func(function func(model *" + struct_model + ", fbeType int, buffer []byte)) { p.HandlerOnProxy" + struct_name + " = OnProxy" + std::string(final ? "Final" : "") + struct_name + "Func(function) }");
+
7842 }
+
7843 }
+
7844 }
+
7845
+
7846
+
7847 // Generate proxy message handler
+
7848 WriteLine();
+
7849 WriteLineIndent("// Receive message handler");
+
7850 WriteLineIndent("func (p *" + proxy_name + ") OnReceive(fbeType int, buffer []byte) (bool, error) {");
+
7851 Indent(1);
+
7852 if (p->body)
+
7853 {
+
7854 WriteLineIndent("switch fbeType {");
+
7855 for (const auto& s : p->body->structs)
+
7856 {
+
7857 if (s->message)
+
7858 {
+
7859 std::string struct_name = ConvertToUpper(*s->name);
+
7860 std::string struct_model = ConvertToLower(*s->name) + "Model";
+
7861 WriteLineIndent("case p." + struct_model + ".FBEType():");
+
7862 Indent(1);
+
7863 WriteLineIndent("// Attach the FBE stream to the proxy model");
+
7864 WriteLineIndent("p." + struct_model + ".Buffer().Attach(buffer)");
+
7865 WriteLineIndent("if !p." + struct_model + ".Verify() {");
+
7866 Indent(1);
+
7867 WriteLineIndent("return false, errors.New(\"" + *p->name + "." + *s->name + " validation failed\")");
+
7868 Indent(-1);
+
7869 WriteLineIndent("}");
+
7870 WriteLine();
+
7871 WriteLineIndent("fbeBegin, err := p." + struct_model + ".model.GetBegin()");
+
7872 WriteLineIndent("if fbeBegin == 0 {");
+
7873 Indent(1);
+
7874 WriteLineIndent("return false, err");
+
7875 Indent(-1);
+
7876 WriteLineIndent("}");
+
7877 WriteLineIndent("// Call proxy handler");
+
7878 WriteLineIndent("p.HandlerOnProxy" + struct_name + ".OnProxy" + struct_name + "(p." + struct_model + ", fbeType, buffer)");
+
7879 WriteLineIndent("p." + struct_model + ".model.GetEnd(fbeBegin)");
+
7880 WriteLineIndent("return true, nil");
+
7881 Indent(-1);
+
7882 }
+
7883 }
+
7884 WriteLineIndent("default:");
+
7885 Indent(1);
+
7886 WriteLineIndent("_ = fbeType");
+
7887 WriteLineIndent("break");
+
7888 Indent(-1);
+
7889 WriteLineIndent("}");
+
7890 }
+
7891 if (p->import)
+
7892 {
+
7893 WriteLine();
+
7894 for (const auto& import : p->import->imports)
+
7895 {
+
7896 WriteLineIndent("if p." + ConvertToLower(*import) + "Proxy != nil {");
+
7897 Indent(1);
+
7898 WriteLineIndent("if ok, err := p." + ConvertToLower(*import) + "Proxy.OnReceive(fbeType, buffer); ok {");
+
7899 Indent(1);
+
7900 WriteLineIndent("return ok, err");
+
7901 Indent(-1);
+
7902 WriteLineIndent("}");
+
7903 Indent(-1);
+
7904 WriteLineIndent("}");
+
7905 }
+
7906 }
+
7907 WriteLine();
+
7908 WriteLineIndent("return false, nil");
+
7909 Indent(-1);
+
7910 WriteLineIndent("}");
+
7911
+
7912 // Generate footer
+
7913 GenerateFooter();
+
7914
+
7915 // Store the output file
+
7916 WriteEnd();
+
7917 Store(output);
+
7918}
+
7919
+
7920bool GeneratorGo::IsPrimitiveType(const std::string& type)
+
7921{
+
7922 return ((type == "bool") || (type == "byte") ||
+
7923 (type == "char") || (type == "wchar") ||
+
7924 (type == "int8") || (type == "uint8") ||
+
7925 (type == "int16") || (type == "uint16") ||
+
7926 (type == "int32") || (type == "uint32") ||
+
7927 (type == "int64") || (type == "uint64") ||
+
7928 (type == "float") || (type == "double"));
+
7929}
+
7930
+
7931bool GeneratorGo::IsGoType(const std::string& type)
+
7932{
+
7933 return IsPrimitiveType(type) || (type == "bytes") || (type == "decimal") || (type == "string") || (type == "timestamp") || (type == "uuid");
+
7934}
+
7935
+
7936std::string GeneratorGo::ConvertToLower(const std::string& type)
+
7937{
+
7938 std::string result = CppCommon::StringUtils::ToTrim(type);
+
7939 result[0] = std::tolower(result[0]);
+
7940 return result;
+
7941}
+
7942
+
7943std::string GeneratorGo::ConvertToUpper(const std::string& type)
+
7944{
+
7945 std::string result = CppCommon::StringUtils::ToTrim(type);
+
7946 result[0] = std::toupper(result[0]);
+
7947 return result;
+
7948}
+
7949
+
7950std::string GeneratorGo::ConvertEnumBase(const std::string& type)
+
7951{
+
7952 if (type == "byte")
+
7953 return "Byte";
+
7954 else if (type == "char")
+
7955 return "UInt8";
+
7956 else if (type == "wchar")
+
7957 return "UInt32";
+
7958 else if (type == "int8")
+
7959 return "Int8";
+
7960 else if (type == "uint8")
+
7961 return "UInt8";
+
7962 else if (type == "int16")
+
7963 return "Int16";
+
7964 else if (type == "uint16")
+
7965 return "UInt16";
+
7966 else if (type == "int32")
+
7967 return "Int32";
+
7968 else if (type == "uint32")
+
7969 return "UInt32";
+
7970 else if (type == "int64")
+
7971 return "Int64";
+
7972 else if (type == "uint64")
+
7973 return "UInt64";
+
7974
+
7975 yyerror("Unsupported enum base type - " + type);
+
7976 return "";
+
7977}
+
7978
+
7979std::string GeneratorGo::ConvertEnumSize(const std::string& type)
+
7980{
+
7981 if (type == "byte")
+
7982 return "1";
+
7983 else if (type == "char")
+
7984 return "1";
+
7985 else if (type == "wchar")
+
7986 return "4";
+
7987 else if (type == "int8")
+
7988 return "1";
+
7989 else if (type == "uint8")
+
7990 return "1";
+
7991 else if (type == "int16")
+
7992 return "2";
+
7993 else if (type == "uint16")
+
7994 return "2";
+
7995 else if (type == "int32")
+
7996 return "4";
+
7997 else if (type == "uint32")
+
7998 return "4";
+
7999 else if (type == "int64")
+
8000 return "8";
+
8001 else if (type == "uint64")
+
8002 return "8";
+
8003
+
8004 yyerror("Unsupported enum base type - " + type);
+
8005 return "";
+
8006}
+
8007
+
8008std::string GeneratorGo::ConvertEnumType(const std::string& type)
+
8009{
+
8010 if (type == "byte")
+
8011 return "byte";
+
8012 else if (type == "char")
+
8013 return "uint8";
+
8014 else if (type == "wchar")
+
8015 return "uint32";
+
8016 else if (type == "int8")
+
8017 return "int8";
+
8018 else if (type == "uint8")
+
8019 return "uint8";
+
8020 else if (type == "int16")
+
8021 return "int16";
+
8022 else if (type == "uint16")
+
8023 return "uint16";
+
8024 else if (type == "int32")
+
8025 return "int32";
+
8026 else if (type == "uint32")
+
8027 return "uint32";
+
8028 else if (type == "int64")
+
8029 return "int64";
+
8030 else if (type == "uint64")
+
8031 return "uint64";
+
8032
+
8033 yyerror("Unsupported enum base type - " + type);
+
8034 return "";
+
8035}
+
8036
+
8037std::string GeneratorGo::ConvertEnumConstant(const std::string& value)
+
8038{
+
8039 std::string ns = "";
+
8040 std::string t = "";
+
8041 std::string v = "";
+
8042
+
8043 size_t pos = value.find_last_of('.');
+
8044 if (pos != std::string::npos)
+
8045 {
+
8046 t.assign(value, 0, pos);
+
8047 v.assign(value, pos + 1, value.size() - pos);
+
8048 }
+
8049
+
8050 pos = t.find_last_of('.');
+
8051 if (pos != std::string::npos)
+
8052 {
+
8053 ns.assign(t, 0, pos);
+
8054 t.assign(t, pos + 1, t.size() - pos);
+
8055 }
+
8056
+
8057 return ns + ConvertToUpper(t) + "_" + v;
+
8058}
+
8059
+
8060std::string GeneratorGo::ConvertEnumConstant(const std::string& name, const std::string& type, const std::string& value)
+
8061{
+
8062 if (((type == "char") || (type == "wchar")) && CppCommon::StringUtils::StartsWith(value, "'"))
+
8063 return name + "(" + value + ")";
+
8064
+
8065 std::string result = value;
+
8066
+
8067 if (type.empty())
+
8068 {
+
8069 // Fill flags values
+
8070 std::vector<std::string> flags = CppCommon::StringUtils::Split(value, '|', true);
+
8071
+
8072 // Generate flags combination
+
8073 if (!flags.empty())
+
8074 {
+
8075 result = "";
+
8076 bool first = true;
+
8077 for (const auto& it : flags)
+
8078 {
+
8079 result += (first ? "" : " | ") + name + "_" + CppCommon::StringUtils::ToTrim(it);
+
8080 first = false;
+
8081 }
+
8082 }
+
8083 }
+
8084
+
8085 return result;
+
8086}
+
8087
+
8088std::string GeneratorGo::ConvertBaseName(const std::string& type)
+
8089{
+
8090 if (IsGoType(type))
+
8091 return type;
+
8092
+
8093 std::string ns = "";
+
8094 std::string t = type;
+
8095
+
8096 size_t pos = type.find_last_of('.');
+
8097 if (pos != std::string::npos)
+
8098 {
+
8099 ns.assign(type, 0, pos + 1);
+
8100 t.assign(type, pos + 1, type.size() - pos);
+
8101 }
+
8102
+
8103 return ConvertToUpper(t);
+
8104}
+
8105
+
8106std::string GeneratorGo::ConvertKeyName(const std::string& type)
+
8107{
+
8108 if (IsGoType(type))
+
8109 return type;
+
8110
+
8111 std::string ns = "";
+
8112 std::string t = type;
+
8113
+
8114 size_t pos = type.find_last_of('.');
+
8115 if (pos != std::string::npos)
+
8116 {
+
8117 ns.assign(type, 0, pos + 1);
+
8118 t.assign(type, pos + 1, type.size() - pos);
+
8119 }
+
8120
+
8121 return ns + ConvertToUpper(t) + "Key";
+
8122}
+
8123
+
8124std::string GeneratorGo::ConvertModelName(const std::string& type, const std::string& model)
+
8125{
+
8126 std::string ns = "";
+
8127 std::string t = type;
+
8128
+
8129 size_t pos = type.find_last_of('.');
+
8130 if (pos != std::string::npos)
+
8131 {
+
8132 ns.assign(type, 0, pos + 1);
+
8133 t.assign(type, pos + 1, type.size() - pos);
+
8134 }
+
8135
+
8136 return ns + model + ConvertToUpper(t);
+
8137}
+
8138
+
8139std::string GeneratorGo::ConvertNewName(const std::string& type)
+
8140{
+
8141 std::string ns = "";
+
8142 std::string t = type;
+
8143
+
8144 size_t pos = type.find_last_of('.');
+
8145 if (pos != std::string::npos)
+
8146 {
+
8147 ns.assign(type, 0, pos + 1);
+
8148 t.assign(type, pos + 1, type.size() - pos);
+
8149 }
+
8150
+
8151 return ns + "New" + ConvertToUpper(t);
+
8152}
+
8153
+
8154std::string GeneratorGo::ConvertOptional(const std::string& type)
+
8155{
+
8156 if (type == "bool")
+
8157 return "fbe.OptionalBool(false)";
+
8158 else if (type == "byte")
+
8159 return "fbe.OptionalByte(0)";
+
8160 else if (type == "bytes")
+
8161 return "fbe.OptionalBytes(make([]byte, 0))";
+
8162 else if ((type == "char") || (type == "wchar"))
+
8163 return "fbe.OptionalRune('\\000')";
+
8164 else if (type == "int8")
+
8165 return "fbe.OptionalInt8(0)";
+
8166 else if (type == "uint8")
+
8167 return "fbe.OptionalUInt8(0)";
+
8168 else if (type == "int16")
+
8169 return "fbe.OptionalInt16(0)";
+
8170 else if (type == "uint16")
+
8171 return "fbe.OptionalUInt16(0)";
+
8172 else if (type == "int32")
+
8173 return "fbe.OptionalInt32(0)";
+
8174 else if (type == "uint32")
+
8175 return "fbe.OptionalUInt32(0)";
+
8176 else if (type == "int64")
+
8177 return "fbe.OptionalInt64(0)";
+
8178 else if (type == "uint64")
+
8179 return "fbe.OptionalUInt64(0)";
+
8180 else if (type == "float")
+
8181 return "fbe.OptionalFloat32(0.0)";
+
8182 else if (type == "double")
+
8183 return "fbe.OptionalFloat64(0.0)";
+
8184 else if (type == "decimal")
+
8185 return "fbe.OptionalDecimal(fbe.DecimalZero())";
+
8186 else if (type == "timestamp")
+
8187 return "fbe.OptionalTimestamp(fbe.TimestampEpoch())";
+
8188 else if (type == "string")
+
8189 return "fbe.OptionalString(\"\")";
+
8190 else if (type == "uuid")
+
8191 return "fbe.OptionalUUID(fbe.UUIDNil())";
+
8192
+
8193 return ConvertNewName(type) + "()" + ".Optional()";
+
8194}
+
8195
+
8196std::string GeneratorGo::ConvertOptional(const std::string& type, const std::string& value)
+
8197{
+
8198 if (value == "null")
+
8199 return "nil";
+
8200
+
8201 if (type == "bool")
+
8202 return "fbe.OptionalBool(" + ConvertConstant(type, value, false) + ")";
+
8203 else if (type == "byte")
+
8204 return "fbe.OptionalByte(" + ConvertConstant(type, value, false) + ")";
+
8205 else if (type == "bytes")
+
8206 return "fbe.OptionalBytes(" + ConvertConstant(type, value, false) + ")";
+
8207 else if ((type == "char") || (type == "wchar"))
+
8208 return "fbe.OptionalRune(" + ConvertConstant(type, value, false) + ")";
+
8209 else if (type == "int8")
+
8210 return "fbe.OptionalInt8(" + ConvertConstant(type, value, false) + ")";
+
8211 else if (type == "uint8")
+
8212 return "fbe.OptionalUInt8(" + ConvertConstant(type, value, false) + ")";
+
8213 else if (type == "int16")
+
8214 return "fbe.OptionalInt16(" + ConvertConstant(type, value, false) + ")";
+
8215 else if (type == "uint16")
+
8216 return "fbe.OptionalUInt16(" + ConvertConstant(type, value, false) + ")";
+
8217 else if (type == "int32")
+
8218 return "fbe.OptionalInt32(" + ConvertConstant(type, value, false) + ")";
+
8219 else if (type == "uint32")
+
8220 return "fbe.OptionalUInt32(" + ConvertConstant(type, value, false) + ")";
+
8221 else if (type == "int64")
+
8222 return "fbe.OptionalInt64(" + ConvertConstant(type, value, false) + ")";
+
8223 else if (type == "uint64")
+
8224 return "fbe.OptionalUInt64(" + ConvertConstant(type, value, false) + ")";
+
8225 else if (type == "float")
+
8226 return "fbe.OptionalFloat32(" + ConvertConstant(type, value, false) + ")";
+
8227 else if (type == "double")
+
8228 return "fbe.OptionalFloat64(" + ConvertConstant(type, value, false) + ")";
+
8229 else if (type == "decimal")
+
8230 return "fbe.OptionalDecimal(" + ConvertConstant(type, value, false) + ")";
+
8231 else if (type == "timestamp")
+
8232 return "fbe.OptionalTimestamp(" + ConvertConstant(type, value, false) + ")";
+
8233 else if (type == "string")
+
8234 return "fbe.OptionalString(" + ConvertConstant(type, value, false) + ")";
+
8235 else if (type == "uuid")
+
8236 return "fbe.OptionalUUID(" + ConvertConstant(type, value, false) + ")";
+
8237
+
8238 return ConvertConstant(type, value, false) + ".Optional()";
+
8239}
+
8240
+
8241std::string GeneratorGo::ConvertTypeName(const std::string& type, bool optional)
+
8242{
+
8243 std::string opt = optional ? "*" : "";
+
8244
+
8245 if ((type == "bool") || (type == "byte") || (type == "int8") || (type == "uint8") || (type == "int16") || (type == "uint16") || (type == "int32") || (type == "uint32") || (type == "int64") || (type == "uint64") || (type == "string"))
+
8246 return opt + type;
+
8247 else if ((type == "char") || (type == "wchar"))
+
8248 return opt + "rune";
+
8249 else if (type == "bytes")
+
8250 return opt + "[]byte";
+
8251 else if (type == "float")
+
8252 return opt + "float32";
+
8253 else if (type == "double")
+
8254 return opt + "float64";
+
8255 else if (type == "decimal")
+
8256 return opt + "fbe.Decimal";
+
8257 else if (type == "timestamp")
+
8258 return opt + "fbe.Timestamp";
+
8259 else if (type == "uuid")
+
8260 return opt + "fbe.UUID";
+
8261
+
8262 std::string ns = "";
+
8263 std::string t = type;
+
8264
+
8265 size_t pos = type.find_last_of('.');
+
8266 if (pos != std::string::npos)
+
8267 {
+
8268 ns.assign(type, 0, pos + 1);
+
8269 t.assign(type, pos + 1, type.size() - pos);
+
8270 }
+
8271
+
8272 return opt + ns + ConvertToUpper(t);
+
8273}
+
8274
+
8275std::string GeneratorGo::ConvertTypeName(const StructField& field)
+
8276{
+
8277 if (field.array)
+
8278 return "[" + std::to_string(field.N) + "]" + ConvertTypeName(*field.type, field.optional);
+
8279 else if ((field.vector) || (field.list))
+
8280 return "[]" + ConvertTypeName(*field.type, field.optional);
+
8281 else if (field.set)
+
8282 return "set" + ConvertToUpper(*field.name);
+
8283 else if ((field.set) || (field.map) || (field.hash))
+
8284 {
+
8285 if (IsGoType(*field.key))
+
8286 return "map[" + ConvertKeyName(*field.key) + "]" + ConvertTypeName(*field.type, field.optional);
+
8287 else
+
8288 return "map[" + ConvertKeyName(*field.key) + "]struct{Key " + ConvertTypeName(*field.key, false) + "; Value " + ConvertTypeName(*field.type, field.optional) + "}";
+
8289 }
+
8290
+
8291 return ConvertTypeName(*field.type, field.optional);
+
8292}
+
8293
+
8294std::string GeneratorGo::ConvertTypeFieldName(const std::string& type)
+
8295{
+
8296 if (type == "bool")
+
8297 return "Bool";
+
8298 else if (type == "byte")
+
8299 return "Byte";
+
8300 else if (type == "bytes")
+
8301 return "Bytes";
+
8302 else if (type == "char")
+
8303 return "Char";
+
8304 else if (type == "wchar")
+
8305 return "WChar";
+
8306 else if (type == "int8")
+
8307 return "Int8";
+
8308 else if (type == "uint8")
+
8309 return "UInt8";
+
8310 else if (type == "int16")
+
8311 return "Int16";
+
8312 else if (type == "uint16")
+
8313 return "UInt16";
+
8314 else if (type == "int32")
+
8315 return "Int32";
+
8316 else if (type == "uint32")
+
8317 return "UInt32";
+
8318 else if (type == "int64")
+
8319 return "Int64";
+
8320 else if (type == "uint64")
+
8321 return "UInt64";
+
8322 else if (type == "float")
+
8323 return "Float";
+
8324 else if (type == "double")
+
8325 return "Double";
+
8326 else if (type == "decimal")
+
8327 return "Decimal";
+
8328 else if (type == "timestamp")
+
8329 return "Timestamp";
+
8330 else if (type == "string")
+
8331 return "String";
+
8332 else if (type == "uuid")
+
8333 return "UUID";
+
8334
+
8335 std::string ns = "";
+
8336 std::string t = type;
+
8337
+
8338 size_t pos = type.find_last_of('.');
+
8339 if (pos != std::string::npos)
+
8340 {
+
8341 ns.assign(type, 0, pos + 1);
+
8342 t.assign(type, pos + 1, type.size() - pos);
+
8343 }
+
8344
+
8345 CppCommon::StringUtils::ReplaceAll(ns, ".", "");
+
8346 return ns + ConvertToUpper(t);
+
8347}
+
8348
+
8349std::string GeneratorGo::ConvertTypeFieldType(const std::string& type, bool optional)
+
8350{
+
8351 if (IsGoType(type))
+
8352 return ConvertTypeName(type, optional);
+
8353
+
8354 std::string ns = "";
+
8355 std::string opt = optional ? "*" : "";
+
8356 std::string t = type;
+
8357
+
8358 size_t pos = type.find_last_of('.');
+
8359 if (pos != std::string::npos)
+
8360 {
+
8361 ns.assign(type, 0, pos + 1);
+
8362 t.assign(type, pos + 1, type.size() - pos);
+
8363 }
+
8364
+
8365 return ns + opt + ConvertToUpper(t);
+
8366}
+
8367
+
8368std::string GeneratorGo::ConvertTypeFieldDeclaration(const std::string& type, bool optional, bool final)
+
8369{
+
8370 std::string modelType = final ? "Final" : "Field";
+
8371
+
8372 if (IsGoType(type) && !optional)
+
8373 return "fbe." + modelType + "Model" + ConvertTypeFieldName(type);
+
8374
+
8375 std::string ns = "";
+
8376 std::string opt = optional ? "Optional" : "";
+
8377 std::string t = type;
+
8378
+
8379 size_t pos = type.find_last_of('.');
+
8380 if (pos != std::string::npos)
+
8381 {
+
8382 ns.assign(type, 0, pos + 1);
+
8383 t.assign(type, pos + 1, type.size() - pos);
+
8384 }
+
8385
+
8386 return ns + modelType + "Model" + opt + ConvertTypeFieldName(t);
+
8387}
+
8388
+
8389std::string GeneratorGo::ConvertTypeFieldDeclaration(const StructField& field, bool final)
+
8390{
+
8391 std::string modelType = final ? "Final" : "Field";
+
8392
+
8393 if (field.array)
+
8394 return modelType + "ModelArray" + std::string(field.optional ? "Optional" : "") + ConvertTypeFieldName(*field.type);
+
8395 else if (field.vector || field.list)
+
8396 return modelType + "ModelVector" + std::string(field.optional ? "Optional" : "") + ConvertTypeFieldName(*field.type);
+
8397 else if (field.set)
+
8398 return modelType + "ModelSet" + std::string(field.optional ? "Optional" : "") + ConvertTypeFieldName(*field.type);
+
8399 else if (field.map || field.hash)
+
8400 return modelType + "ModelMap" + ConvertTypeFieldName(*field.key) + std::string(field.optional ? "Optional" : "") + ConvertTypeFieldName(*field.type);
+
8401 else if (field.optional)
+
8402 return modelType + "ModelOptional" + ConvertTypeFieldName(*field.type);
+
8403
+
8404 return ConvertTypeFieldDeclaration(*field.type, field.optional, final);
+
8405}
+
8406
+
8407std::string GeneratorGo::ConvertTypeFieldInitialization(const std::string& type, bool optional, const std::string& offset, bool final)
+
8408{
+
8409 std::string modelType = final ? "Final" : "Field";
+
8410
+
8411 if (IsGoType(type))
+
8412 return "fbe.New" + modelType + "Model" + ConvertTypeFieldName(type) + "(buffer, " + offset + ")";
+
8413
+
8414 std::string ns = "";
+
8415 std::string t = type;
+
8416
+
8417 size_t pos = type.find_last_of('.');
+
8418 if (pos != std::string::npos)
+
8419 {
+
8420 ns.assign(type, 0, pos + 1);
+
8421 t.assign(type, pos + 1, type.size() - pos);
+
8422 }
+
8423
+
8424 return ns + "New" + modelType + "Model" + ConvertTypeFieldName(t) + "(buffer, " + offset + ")";
+
8425}
+
8426
+
8427std::string GeneratorGo::ConvertTypeFieldInitialization(const StructField& field, const std::string& offset, bool final)
+
8428{
+
8429 std::string modelType = final ? "Final" : "Field";
+
8430
+
8431 if (field.array)
+
8432 return "New" + modelType + "ModelArray" + std::string(field.optional ? "Optional" : "") + ConvertTypeFieldName(*field.type) + "(buffer, " + offset + ", " + std::to_string(field.N) + ")";
+
8433 else if (field.vector || field.list)
+
8434 return "New" + modelType + "ModelVector" + std::string(field.optional ? "Optional" : "") + ConvertTypeFieldName(*field.type) + "(buffer, " + offset + ")";
+
8435 else if (field.set)
+
8436 return "New" + modelType + "ModelSet" + std::string(field.optional ? "Optional" : "") + ConvertTypeFieldName(*field.type) + "(buffer, " + offset + ")";
+
8437 else if (field.map || field.hash)
+
8438 return "New" + modelType + "ModelMap" + ConvertTypeFieldName(*field.key) + std::string(field.optional ? "Optional" : "") + ConvertTypeFieldName(*field.type) + "(buffer, " + offset + ")";
+
8439 else if (field.optional)
+
8440 return "New" + modelType + "ModelOptional" + ConvertTypeFieldName(*field.type) + "(buffer, " + offset + ")";
+
8441
+
8442 return ConvertTypeFieldInitialization(*field.type, field.optional, offset, final);
+
8443}
+
8444
+
8445std::string GeneratorGo::ConvertConstant(const std::string& type, const std::string& value, bool optional)
+
8446{
+
8447 if (optional)
+
8448 return ConvertOptional(type, value);
+
8449
+
8450 if (value == "true")
+
8451 return "true";
+
8452 else if (value == "false")
+
8453 return "false";
+
8454 else if (value == "null")
+
8455 return "nil";
+
8456 else if (value == "min")
+
8457 {
+
8458 if ((type == "byte") || (type == "uint8") || (type == "uint16") || (type == "uint32") || (type == "uint64"))
+
8459 return "0";
+
8460 else if (type == "int8")
+
8461 return "-128";
+
8462 else if (type == "int16")
+
8463 return "-32768";
+
8464 else if (type == "int32")
+
8465 return "-2147483648";
+
8466 else if (type == "int64")
+
8467 return "-9223372036854775808";
+
8468
+
8469 yyerror("Unsupported type " + type + " for 'min' constant");
+
8470 return "";
+
8471 }
+
8472 else if (value == "max")
+
8473 {
+
8474 if (type == "byte")
+
8475 return "255";
+
8476 else if (type == "int8")
+
8477 return "127";
+
8478 else if (type == "uint8")
+
8479 return "255";
+
8480 else if (type == "int16")
+
8481 return "32767";
+
8482 else if (type == "uint16")
+
8483 return "65535";
+
8484 else if (type == "int32")
+
8485 return "2147483647";
+
8486 else if (type == "uint32")
+
8487 return "4294967295";
+
8488 else if (type == "int64")
+
8489 return "9223372036854775807";
+
8490 else if (type == "uint64")
+
8491 return "18446744073709551615";
+
8492
+
8493 yyerror("Unsupported type " + type + " for 'max' constant");
+
8494 return "";
+
8495 }
+
8496 else if (value == "epoch")
+
8497 return "fbe.TimestampEpoch()";
+
8498 else if (value == "utc")
+
8499 return "fbe.TimestampUTC()";
+
8500 else if (value == "uuid0")
+
8501 return "fbe.UUIDNil()";
+
8502 else if (value == "uuid1")
+
8503 return "fbe.UUIDSequential()";
+
8504 else if (value == "uuid4")
+
8505 return "fbe.UUIDRandom()";
+
8506
+
8507 if ((type == "bool") || (type == "byte") || (type == "int8") || (type == "uint8") || (type == "int16") || (type == "uint16") || (type == "int32") || (type == "uint32") || (type == "int64") || (type == "uint64"))
+
8508 return type + "(" + value + ")";
+
8509 else if (((type == "char") || (type == "wchar")) && !CppCommon::StringUtils::StartsWith(value, "'"))
+
8510 return "rune(" + value + ")";
+
8511 else if (type == "float")
+
8512 return "float32(" + value + ")";
+
8513 else if (type == "double")
+
8514 return "float64(" + value + ")";
+
8515 else if (type == "decimal")
+
8516 return "fbe.DecimalFromString(\"" + value + "\")";
+
8517 else if (type == "uuid")
+
8518 return "fbe.UUIDFromString(" + value + ")";
+
8519
+
8520 std::string result = value;
+
8521
+
8522 if (!IsGoType(type))
+
8523 {
+
8524 // Fill flags values
+
8525 std::vector<std::string> flags = CppCommon::StringUtils::Split(value, '|', true);
+
8526
+
8527 // Generate flags combination
+
8528 if (flags.size() > 1)
+
8529 {
+
8530 result = "";
+
8531 bool first = true;
+
8532 for (const auto& it : flags)
+
8533 {
+
8534 result += (first ? "" : " | ") + ConvertEnumConstant(CppCommon::StringUtils::ToTrim(it));
+
8535 first = false;
+
8536 }
+
8537 }
+
8538 // Generate single flag
+
8539 else if (flags.size() > 0)
+
8540 result = ConvertEnumConstant(CppCommon::StringUtils::ToTrim(flags.front()));
+
8541 }
+
8542
+
8543 return result;
+
8544}
+
8545
+
8546std::string GeneratorGo::ConvertDefault(const std::string& type, bool optional)
+
8547{
+
8548 if (optional)
+
8549 return "nil";
+
8550
+
8551 if (type == "bool")
+
8552 return "false";
+
8553 else if (type == "byte")
+
8554 return "0";
+
8555 else if (type == "bytes")
+
8556 return "make([]byte, 0)";
+
8557 else if ((type == "char") || (type == "wchar"))
+
8558 return "'\\000'";
+
8559 else if ((type == "int8") || (type == "uint8") || (type == "int16") || (type == "uint16") || (type == "int32") || (type == "uint32") || (type == "int64") || (type == "uint64"))
+
8560 return "0";
+
8561 else if ((type == "float") || (type == "double"))
+
8562 return "0.0";
+
8563 else if (type == "decimal")
+
8564 return "fbe.DecimalZero()";
+
8565 else if (type == "timestamp")
+
8566 return "fbe.TimestampEpoch()";
+
8567 else if (type == "string")
+
8568 return "\"\"";
+
8569 else if (type == "uuid")
+
8570 return "fbe.UUIDNil()";
+
8571
+
8572 return "*" + ConvertNewName(type) + "()";
+
8573}
+
8574
+
8575std::string GeneratorGo::ConvertDefault(const StructField& field)
+
8576{
+
8577 if (field.value)
+
8578 return ConvertConstant(*field.type, *field.value, field.optional);
+
8579
+
8580 if (field.array)
+
8581 return ConvertTypeName(field) + "{}";
+
8582 else if (field.vector || field.list)
+
8583 return "make(" + ConvertTypeName(field) + ", 0)";
+
8584 else if (field.set)
+
8585 return "make(set" + ConvertToUpper(*field.name) + ")";
+
8586 else if (field.map || field.hash)
+
8587 return "make(" + ConvertTypeName(field) + ")";
+
8588
+
8589 return ConvertDefault(*field.type, field.optional);
+
8590}
+
8591
+
8592void GeneratorGo::WriteOutputStreamType(const std::string& type, const std::string& name, bool optional)
+
8593{
+
8594 if (type == "bool")
+
8595 Write("sb.WriteString(strconv.FormatBool(" + std::string(optional ? "*" : "") + name + "))");
+
8596 else if (type == "byte")
+
8597 Write("sb.WriteString(strconv.FormatUint(uint64(" + std::string(optional ? "*" : "") + name + "), 10))");
+
8598 else if ((type == "int8") || (type == "int16") || (type == "int32") || (type == "int64"))
+
8599 Write("sb.WriteString(strconv.FormatInt(int64(" + std::string(optional ? "*" : "") + name + "), 10))");
+
8600 else if ((type == "uint8") || (type == "uint16") || (type == "uint32") || (type == "uint64"))
+
8601 Write("sb.WriteString(strconv.FormatUint(uint64(" + std::string(optional ? "*" : "") + name + "), 10))");
+
8602 else if ((type == "char") || (type == "wchar"))
+
8603 Write("sb.WriteString(\"'\" + string(" + std::string(optional ? "*" : "") + name + ") + \"'\")");
+
8604 else if (type == "float")
+
8605 Write("sb.WriteString(strconv.FormatFloat(float64(" + std::string(optional ? "*" : "") + name + "), 'g', -1, 32))");
+
8606 else if (type == "double")
+
8607 Write("sb.WriteString(strconv.FormatFloat(float64(" + std::string(optional ? "*" : "") + name + "), 'g', -1, 64))");
+
8608 else if (type == "bytes")
+
8609 Write("sb.WriteString(\"bytes[\" + strconv.FormatInt(int64(len(" + std::string(optional ? "*" : "") + name + ")), 10) + \"]\")");
+
8610 else if (type == "string")
+
8611 Write("sb.WriteString(\"\\\"\" + " + std::string(optional ? "*" : "") + name + " + \"\\\"\")");
+
8612 else if (type == "decimal")
+
8613 Write("sb.WriteString(" + std::string(optional ? "(*" : "") + name + std::string(optional ? ")" : "") + ".String())");
+
8614 else if (type == "timestamp")
+
8615 Write("sb.WriteString(strconv.FormatInt(" + std::string(optional ? "(*" : "") + name + std::string(optional ? ")" : "") + + ".UnixNano(), 10))");
+
8616 else if (type == "uuid")
+
8617 Write("sb.WriteString(\"\\\"\" + " + std::string(optional ? "(*" : "") + name + std::string(optional ? ")" : "") + ".String() + \"\\\"\")");
+
8618 else
+
8619 Write("sb.WriteString(" + name + ".String())");
+
8620}
+
8621
+
8622void GeneratorGo::WriteOutputStreamValue(const std::string& type, const std::string& name, bool optional, bool separate)
+
8623{
+
8624 if (optional || (type == "bytes"))
+
8625 {
+
8626 WriteLineIndent("if " + name + " != nil { ");
+
8627 Indent(1);
+
8628 if (separate)
+
8629 WriteLineIndent("if first { sb.WriteString(\"\") } else { sb.WriteString(\",\") }");
+
8630 WriteIndent();
+
8631 WriteOutputStreamType(type, name, optional);
+
8632 WriteLine();
+
8633 Indent(-1);
+
8634 WriteLineIndent("} else {");
+
8635 Indent(1);
+
8636 if (separate)
+
8637 WriteLineIndent("if first { sb.WriteString(\"\") } else { sb.WriteString(\",\") }");
+
8638 WriteLineIndent("sb.WriteString(\"null\")");
+
8639 Indent(-1);
+
8640 WriteLineIndent("}");
+
8641 }
+
8642 else
+
8643 {
+
8644 if (separate)
+
8645 WriteLineIndent("if first { sb.WriteString(\"\") } else { sb.WriteString(\",\") }");
+
8646 WriteIndent();
+
8647 WriteOutputStreamType(type, name, optional);
+
8648 WriteLine();
+
8649 }
+
8650}
+
8651
+
8652} // namespace FBE
+
void Generate(const std::shared_ptr< Package > &package) override
+
bool JSON() const noexcept
+
bool Final() const noexcept
+
bool Proto() const noexcept
+
void WriteBegin()
Definition generator.inl:24
+
void Store(const CppCommon::Path &filename)
Definition generator.cpp:17
+
static std::string EndLine()
Definition generator.inl:68
+
std::string _input
Definition generator.h:25
+ +
std::string _output
Definition generator.h:26
+
void WriteLineIndent(const std::string &str)
Definition generator.inl:58
+
void Write(const std::string &str)
Definition generator.inl:29
+ +
void Indent(int count)
Definition generator.inl:19
+
void WriteIndent()
Definition generator.inl:34
+
int yyerror(const char *msg)
Definition fbe.l:163
+
Fast binary encoding Go generator definition.
+
Definition fbe.h:33
+
const char version[]
Definition version.h:15
+ +
+ + +
+ + diff --git a/documents/html/generator__go_8h.html b/documents/html/generator__go_8h.html new file mode 100644 index 000000000..371798844 --- /dev/null +++ b/documents/html/generator__go_8h.html @@ -0,0 +1,114 @@ + + + + + + + +FastBinaryEncoding: include/generator_go.h File Reference + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+ +
generator_go.h File Reference
+
+
+ +

Fast binary encoding Go generator definition. +More...

+
#include "generator.h"
+
+

Go to the source code of this file.

+ + + +

+Classes

class  FBE::GeneratorGo
+ + +

+Namespaces

namespace  FBE
+

Detailed Description

+

Fast binary encoding Go generator definition.

+
Author
Ivan Shynkarenka
+
Date
20.11.2018
+ + +

Definition in file generator_go.h.

+
+ + +
+ + diff --git a/documents/html/generator__go_8h_source.html b/documents/html/generator__go_8h_source.html new file mode 100644 index 000000000..23a67d8b5 --- /dev/null +++ b/documents/html/generator__go_8h_source.html @@ -0,0 +1,222 @@ + + + + + + + +FastBinaryEncoding: include/generator_go.h Source File + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+
generator_go.h
+
+
+Go to the documentation of this file.
1
+
8
+
9#ifndef GENERATOR_GO_H
+
10#define GENERATOR_GO_H
+
11
+
12#include "generator.h"
+
13
+
14namespace FBE {
+
15
+
+
16class GeneratorGo : public Generator
+
17{
+
18public:
+ +
20
+
21 // Final protocol code generation
+
22 bool Final() const noexcept { return _final; }
+
23 GeneratorGo& Final(bool final) noexcept { _final = final; return *this; }
+
24
+
25 // JSON protocol code generation
+
26 bool JSON() const noexcept { return _json; }
+
27 GeneratorGo& JSON(bool json) noexcept { _json = json; return *this; }
+
28
+
29 // Sender/Receiver protocol code generation
+
30 bool Proto() const noexcept { return _proto; }
+
31 GeneratorGo& Proto(bool proto) noexcept { _proto = proto; return *this; }
+
32
+
33 void Generate(const std::shared_ptr<Package>& package) override;
+
34
+
35private:
+
36 bool _final{false};
+
37 bool _json{false};
+
38 bool _proto{false};
+
39
+
40 void GenerateHeader(const std::string& source);
+
41 void GenerateFooter();
+
42 void GenerateFBEPackage(const std::string& package);
+
43 void GenerateFBEConstants(const std::string& package);
+
44 void GenerateFBEJson(const std::string& package);
+
45 void GenerateFBEOptional(const std::string& package);
+
46 void GenerateFBETypes(const std::string& package);
+
47 void GenerateFBEVersion(const std::string& package, const std::string& source);
+
48 void GenerateFBEBuffer(const std::string& package);
+
49 void GenerateFBEFieldModel(const std::string& package, const std::string& name, const std::string& type, const std::string& size, const std::string& defaults);
+
50 void GenerateFBEFieldModelDecimal(const std::string& package);
+
51 void GenerateFBEFieldModelTimestamp(const std::string& package);
+
52 void GenerateFBEFieldModelUUID(const std::string& package);
+
53 void GenerateFBEFieldModelBytes(const std::string& package);
+
54 void GenerateFBEFieldModelString(const std::string& package);
+
55 void GenerateFBEFieldModelOptional(const std::shared_ptr<Package>& p, const std::string& name, const std::string& model, const StructField& field, const CppCommon::Path& path);
+
56 void GenerateFBEFieldModelArray(const std::shared_ptr<Package>& p, const std::string& name, const std::string& model, const StructField& field, const CppCommon::Path& path);
+
57 void GenerateFBEFieldModelVector(const std::shared_ptr<Package>& p, const std::string& name, const std::string& model, const StructField& field, const CppCommon::Path& path);
+
58 void GenerateFBEFieldModelSet(const std::shared_ptr<Package>& p, const std::string& name, const std::string& model, const StructField& field, const CppCommon::Path& path);
+
59 void GenerateFBEFieldModelMap(const std::shared_ptr<Package>& p, const std::string& key_name, const std::string& key_model, const std::string& value_name, const std::string& value_model, const StructField& field, const CppCommon::Path& path);
+
60 void GenerateFBEFieldModelEnumFlags(const std::string& package, const std::string& name, const std::string& type);
+
61 void GenerateFBEFinalModel(const std::string& package, const std::string& name, const std::string& type, const std::string& size, const std::string& defaults);
+
62 void GenerateFBEFinalModelDecimal(const std::string& package);
+
63 void GenerateFBEFinalModelTimestamp(const std::string& package);
+
64 void GenerateFBEFinalModelUUID(const std::string& package);
+
65 void GenerateFBEFinalModelBytes(const std::string& package);
+
66 void GenerateFBEFinalModelString(const std::string& package);
+
67 void GenerateFBEFinalModelOptional(const std::shared_ptr<Package>& p, const std::string& name, const std::string& model, const StructField& field, const CppCommon::Path& path);
+
68 void GenerateFBEFinalModelArray(const std::shared_ptr<Package>& p, const std::string& name, const std::string& model, const StructField& field, const CppCommon::Path& path);
+
69 void GenerateFBEFinalModelVector(const std::shared_ptr<Package>& p, const std::string& name, const std::string& model, const StructField& field, const CppCommon::Path& path);
+
70 void GenerateFBEFinalModelSet(const std::shared_ptr<Package>& p, const std::string& name, const std::string& model, const StructField& field, const CppCommon::Path& path);
+
71 void GenerateFBEFinalModelMap(const std::shared_ptr<Package>& p, const std::string& key_name, const std::string& key_model, const std::string& value_name, const std::string& value_model, const StructField& field, const CppCommon::Path& path);
+
72 void GenerateFBEFinalModelEnumFlags(const std::string& package, const std::string& name, const std::string& type);
+
73 void GenerateFBESender(const std::string& package);
+
74 void GenerateFBEReceiver(const std::string& package);
+
75 void GenerateImports(const std::shared_ptr<Package>& p);
+
76
+
77 void GenerateContainers(const std::shared_ptr<Package>& p, const CppCommon::Path& path, bool final);
+
78 void GeneratePackage(const std::shared_ptr<Package>& p);
+
79 void GenerateEnum(const std::shared_ptr<Package>& p, const std::shared_ptr<EnumType>& e, const CppCommon::Path& path);
+
80 void GenerateFlags(const std::shared_ptr<Package>& p, const std::shared_ptr<FlagsType>& f, const CppCommon::Path& path);
+
81 void GenerateStruct(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s, const CppCommon::Path& path);
+
82 void GenerateStructFieldModel(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s, const CppCommon::Path& path);
+
83 void GenerateStructModel(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s, const CppCommon::Path& path);
+
84 void GenerateStructFinalModel(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s, const CppCommon::Path& path);
+
85 void GenerateStructModelFinal(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s, const CppCommon::Path& path);
+
86 void GenerateProtocolVersion(const std::shared_ptr<Package>& p, const CppCommon::Path& path);
+
87 void GenerateSender(const std::shared_ptr<Package>& p, const CppCommon::Path& path, bool final);
+
88 void GenerateReceiver(const std::shared_ptr<Package>& p, const CppCommon::Path& path, bool final);
+
89 void GenerateProxy(const std::shared_ptr<Package>& p, const CppCommon::Path& path, bool final);
+
90
+
91 bool IsPrimitiveType(const std::string& type);
+
92 bool IsGoType(const std::string& type);
+
93
+
94 std::string ConvertToLower(const std::string& type);
+
95 std::string ConvertToUpper(const std::string& type);
+
96 std::string ConvertEnumBase(const std::string& type);
+
97 std::string ConvertEnumSize(const std::string& type);
+
98 std::string ConvertEnumType(const std::string& type);
+
99 std::string ConvertEnumConstant(const std::string& value);
+
100 std::string ConvertEnumConstant(const std::string& name, const std::string& type, const std::string& value);
+
101 std::string ConvertBaseName(const std::string& type);
+
102 std::string ConvertKeyName(const std::string& type);
+
103 std::string ConvertModelName(const std::string& type, const std::string& model);
+
104 std::string ConvertNewName(const std::string& type);
+
105 std::string ConvertOptional(const std::string& type);
+
106 std::string ConvertOptional(const std::string& type, const std::string& value);
+
107 std::string ConvertTypeName(const std::string& type, bool optional);
+
108 std::string ConvertTypeName(const StructField& field);
+
109 std::string ConvertTypeFieldName(const std::string& type);
+
110 std::string ConvertTypeFieldType(const std::string& type, bool optional);
+
111 std::string ConvertTypeFieldDeclaration(const std::string& type, bool optional, bool final);
+
112 std::string ConvertTypeFieldDeclaration(const StructField& field, bool final);
+
113 std::string ConvertTypeFieldInitialization(const std::string& type, bool optional, const std::string& offset, bool final);
+
114 std::string ConvertTypeFieldInitialization(const StructField& field, const std::string& offset, bool final);
+
115 std::string ConvertConstant(const std::string& type, const std::string& value, bool optional);
+
116 std::string ConvertDefault(const std::string& type, bool optional);
+
117 std::string ConvertDefault(const StructField& field);
+
118
+
119 void WriteOutputStreamType(const std::string& type, const std::string& name, bool optional);
+
120 void WriteOutputStreamValue(const std::string& type, const std::string& name, bool optional, bool separate);
+
121};
+
+
122
+
123} // namespace FBE
+
124
+
125#endif // GENERATOR_GO_H
+ +
GeneratorGo & Proto(bool proto) noexcept
+
GeneratorGo & JSON(bool json) noexcept
+
void Generate(const std::shared_ptr< Package > &package) override
+
bool JSON() const noexcept
+
GeneratorGo & Final(bool final) noexcept
+
bool Final() const noexcept
+
bool Proto() const noexcept
+
Generator(const std::string &input, const std::string &output, int indent, char space)
Definition generator.inl:11
+
Generator(const std::string &input, const std::string &output, int indent, char space)
Definition generator.inl:11
+
Fast binary encoding generator definition.
+
Definition fbe.h:33
+
+ + +
+ + diff --git a/documents/html/generator__java_8cpp.html b/documents/html/generator__java_8cpp.html new file mode 100644 index 000000000..5672c48ec --- /dev/null +++ b/documents/html/generator__java_8cpp.html @@ -0,0 +1,109 @@ + + + + + + + +FastBinaryEncoding: source/generator_java.cpp File Reference + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+ +
generator_java.cpp File Reference
+
+
+ +

Fast binary encoding Java generator implementation. +More...

+
#include "generator_java.h"
+
+

Go to the source code of this file.

+ + + +

+Namespaces

namespace  FBE
+

Detailed Description

+

Fast binary encoding Java generator implementation.

+
Author
Ivan Shynkarenka
+
Date
20.04.2018
+ + +

Definition in file generator_java.cpp.

+
+ + +
+ + diff --git a/documents/html/generator__java_8cpp_source.html b/documents/html/generator__java_8cpp_source.html new file mode 100644 index 000000000..e2b2177c2 --- /dev/null +++ b/documents/html/generator__java_8cpp_source.html @@ -0,0 +1,8107 @@ + + + + + + + +FastBinaryEncoding: source/generator_java.cpp Source File + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+
generator_java.cpp
+
+
+Go to the documentation of this file.
1
+
8
+
9#include "generator_java.h"
+
10
+
11namespace FBE {
+
12
+
+
13void GeneratorJava::Generate(const std::shared_ptr<Package>& package)
+
14{
+
15 std::string domain = (package->domain && !package->domain->empty()) ? (*package->domain + ".") : "";
+
16
+
17 GenerateFBEPackage(domain, "fbe");
+
18 GenerateFBEPair(domain, "fbe");
+
19 GenerateFBEUUIDGenerator(domain, "fbe");
+
20 GenerateFBEBuffer(domain, "fbe");
+
21 GenerateFBEModel(domain, "fbe");
+
22 GenerateFBEFieldModel(domain, "fbe");
+
23 GenerateFBEFieldModel(domain, "fbe", "Boolean", "boolean", "", "1", "false");
+
24 GenerateFBEFieldModel(domain, "fbe", "Byte", "byte", "", "1", "(byte)0");
+
25 GenerateFBEFieldModel(domain, "fbe", "Char", "char", "(byte)", "1", "'\\u0000'");
+
26 GenerateFBEFieldModel(domain, "fbe", "WChar", "char", "(int)", "4", "'\\u0000'");
+
27 GenerateFBEFieldModel(domain, "fbe", "Int8", "byte", "", "1", "(byte)0");
+
28 GenerateFBEFieldModel(domain, "fbe", "Int16", "short", "", "2", "(short)0");
+
29 GenerateFBEFieldModel(domain, "fbe", "Int32", "int", "", "4", "0");
+
30 GenerateFBEFieldModel(domain, "fbe", "Int64", "long", "", "8", "0l");
+
31 GenerateFBEFieldModel(domain, "fbe", "Float", "float", "", "4", "0.0f");
+
32 GenerateFBEFieldModel(domain, "fbe", "Double", "double", "", "8", "0.0d");
+
33 GenerateFBEFieldModel(domain, "fbe", "UUID", "java.util.UUID", "", "16", "UUIDGenerator.nil()");
+
34 GenerateFBEFieldModelDecimal(domain, "fbe");
+
35 GenerateFBEFieldModelDate(domain, "fbe");
+
36 GenerateFBEFieldModelTimestamp(domain, "fbe");
+
37 GenerateFBEFieldModelBytes(domain, "fbe");
+
38 GenerateFBEFieldModelString(domain, "fbe");
+
39 if (Final())
+
40 {
+
41 GenerateFBESize(domain, "fbe");
+
42 GenerateFBEFinalModel(domain, "fbe");
+
43 GenerateFBEFinalModel(domain, "fbe", "Boolean", "boolean", "", "1", "false");
+
44 GenerateFBEFinalModel(domain, "fbe", "Byte", "byte", "", "1", "(byte)0");
+
45 GenerateFBEFinalModel(domain, "fbe", "Char", "char", "(byte)", "1", "'\\u0000'");
+
46 GenerateFBEFinalModel(domain, "fbe", "WChar", "char", "(int)", "4", "'\\u0000'");
+
47 GenerateFBEFinalModel(domain, "fbe", "Int8", "byte", "", "1", "(byte)0");
+
48 GenerateFBEFinalModel(domain, "fbe", "Int16", "short", "", "2", "(short)0");
+
49 GenerateFBEFinalModel(domain, "fbe", "Int32", "int", "", "4", "0");
+
50 GenerateFBEFinalModel(domain, "fbe", "Int64", "long", "", "8", "0l");
+
51 GenerateFBEFinalModel(domain, "fbe", "Float", "float", "", "4", "0.0f");
+
52 GenerateFBEFinalModel(domain, "fbe", "Double", "double", "", "8", "0.0d");
+
53 GenerateFBEFinalModel(domain, "fbe", "UUID", "java.util.UUID", "", "16", "UUIDGenerator.nil()");
+
54 GenerateFBEFinalModelDecimal(domain, "fbe");
+
55 GenerateFBEFinalModelDate(domain, "fbe");
+
56 GenerateFBEFinalModelTimestamp(domain, "fbe");
+
57 GenerateFBEFinalModelBytes(domain, "fbe");
+
58 GenerateFBEFinalModelString(domain, "fbe");
+
59 }
+
60 if (Proto())
+
61 {
+
62 GenerateFBESender(domain, "fbe");
+
63 GenerateFBEReceiver(domain, "fbe");
+
64 }
+
65 if (JSON())
+
66 GenerateFBEJson(domain, "fbe");
+
67
+
68 GeneratePackage(package);
+
69}
+
+
70
+
71void GeneratorJava::GenerateHeader(const std::string& source)
+
72{
+
73 std::string code = R"CODE(//------------------------------------------------------------------------------
+
74// Automatically generated by the Fast Binary Encoding compiler, do not modify!
+
75// https://github.com/chronoxor/FastBinaryEncoding
+
76// Source: _INPUT_
+
77// FBE version: _VERSION_
+
78//------------------------------------------------------------------------------
+
79)CODE";
+
80
+
81 // Prepare code template
+
82 code = std::regex_replace(code, std::regex("_INPUT_"), source);
+
83 code = std::regex_replace(code, std::regex("_VERSION_"), version);
+
84 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
85
+
86 Write(code);
+
87}
+
88
+
89void GeneratorJava::GenerateFooter()
+
90{
+
91}
+
92
+
93void GeneratorJava::GenerateImports(const std::string& domain, const std::string& package)
+
94{
+
95 // Generate package name
+
96 WriteLine();
+
97 WriteLineIndent("package " + domain + package + ";");
+
98}
+
99
+
100void GeneratorJava::GenerateImports(const std::shared_ptr<Package>& p)
+
101{
+
102 std::string domain = (p->domain && !p->domain->empty()) ? (*p->domain + ".") : "";
+
103
+
104 // Generate common import
+
105 GenerateImports(domain, *p->name);
+
106}
+
107
+
108void GeneratorJava::GenerateFBEPackage(const std::string& domain, const std::string& package)
+
109{
+
110 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
111
+
112 // Create FBE package path
+
113 CppCommon::Directory::CreateTree(path);
+
114}
+
115
+
116void GeneratorJava::GenerateFBEPair(const std::string& domain, const std::string& package)
+
117{
+
118 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
119
+
120 // Generate the file
+
121 CppCommon::Path file = path / "Pair.java";
+
122 WriteBegin();
+
123
+
124 // Generate headers
+
125 GenerateHeader("FBE");
+
126 GenerateImports(domain, package);
+
127
+
128 std::string code = R"CODE(
+
129// Fast Binary Encoding pair wrapper
+
130public final class Pair<K, V>
+
131{
+
132 private final K key;
+
133 private final V value;
+
134
+
135 // Initialize the pair with given key and value
+
136 public Pair(K key, V value)
+
137 {
+
138 this.key = key;
+
139 this.value = value;
+
140 }
+
141
+
142 // Get the pair key
+
143 public K getKey() { return key; }
+
144 // Get the pair value
+
145 public V getValue() { return value; }
+
146
+
147 // Create a new pair
+
148 public static <K, V> Pair<K, V> create(K key, V value) { return new Pair<K, V>(key, value); }
+
149}
+
150)CODE";
+
151
+
152 // Prepare code template
+
153 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
154
+
155 Write(code);
+
156
+
157 // Generate footer
+
158 GenerateFooter();
+
159
+
160 // Store the file
+
161 WriteEnd();
+
162 Store(file);
+
163}
+
164
+
165void GeneratorJava::GenerateFBEUUIDGenerator(const std::string& domain, const std::string& package)
+
166{
+
167 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
168
+
169 // Generate the file
+
170 CppCommon::Path file = path / "UUIDGenerator.java";
+
171 WriteBegin();
+
172
+
173 // Generate headers
+
174 GenerateHeader("FBE");
+
175 GenerateImports(domain, package);
+
176
+
177 std::string code = R"CODE(
+
178// Fast Binary Encoding UUID generator
+
179public final class UUIDGenerator
+
180{
+
181 // Gregorian epoch
+
182 private static final long GregorianEpoch = -12219292800000L;
+
183
+
184 // Lock and random generator
+
185 private static final Object _lock = new Object();
+
186 private static final java.util.Random _generator = new java.util.Random();
+
187
+
188 // Node & clock sequence bytes
+
189 private static long _node = makeNode();
+
190 private static long _nodeAndClockSequence = makeNodeAndClockSequence();
+
191
+
192 // Last UUID generated timestamp
+
193 private static long _last = GregorianEpoch;
+
194
+
195 private static long makeNode()
+
196 {
+
197 return _generator.nextLong() | 0x0000010000000000L;
+
198 }
+
199
+
200 private static long makeNodeAndClockSequence()
+
201 {
+
202 long clock = _generator.nextLong();
+
203
+
204 long lsb = 0;
+
205 // Variant (2 bits)
+
206 lsb |= 0x8000000000000000L;
+
207 // Clock sequence (14 bits)
+
208 lsb |= (clock & 0x0000000000003FFFL) << 48;
+
209 // 6 bytes
+
210 lsb |= _node;
+
211 return lsb;
+
212 }
+
213
+
214 // Generate nil UUID0 (all bits set to zero)
+
215 public static java.util.UUID nil() { return new java.util.UUID(0, 0); }
+
216
+
217 // Generate sequential UUID1 (time based version)
+
218 public static java.util.UUID sequential()
+
219 {
+
220 long now = System.currentTimeMillis();
+
221
+
222 // Generate new clock sequence bytes to get rid of UUID duplicates
+
223 synchronized(_lock)
+
224 {
+
225 if (now <= _last)
+
226 _nodeAndClockSequence = makeNodeAndClockSequence();
+
227 _last = now;
+
228 }
+
229
+
230 long nanosSince = (now - GregorianEpoch) * 10000;
+
231
+
232 long msb = 0L;
+
233 msb |= (0x00000000FFFFFFFFL & nanosSince) << 32;
+
234 msb |= (0x0000FFFF00000000L & nanosSince) >>> 16;
+
235 msb |= (0xFFFF000000000000L & nanosSince) >>> 48;
+
236 // Sets the version to 1
+
237 msb |= 0x0000000000001000L;
+
238
+
239 return new java.util.UUID(msb, _nodeAndClockSequence);
+
240 }
+
241
+
242 // Generate random UUID4 (randomly or pseudo-randomly generated version)
+
243 public static java.util.UUID random() { return java.util.UUID.randomUUID(); }
+
244}
+
245)CODE";
+
246
+
247 // Prepare code template
+
248 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
249
+
250 Write(code);
+
251
+
252 // Generate footer
+
253 GenerateFooter();
+
254
+
255 // Store the file
+
256 WriteEnd();
+
257 Store(file);
+
258}
+
259
+
260void GeneratorJava::GenerateFBEBuffer(const std::string& domain, const std::string& package)
+
261{
+
262 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
263
+
264 // Generate the file
+
265 CppCommon::Path file = path / "Buffer.java";
+
266 WriteBegin();
+
267
+
268 // Generate headers
+
269 GenerateHeader("FBE");
+
270 GenerateImports(domain, package);
+
271
+
272 std::string code = R"CODE(
+
273// Fast Binary Encoding buffer based on dynamic byte array
+
274public class Buffer
+
275{
+
276 private byte[] _data;
+
277 private long _size;
+
278 private long _offset;
+
279
+
280 // Is the buffer empty?
+
281 public boolean isEmpty() { return (_data == null) || (_size == 0); }
+
282 // Get bytes memory buffer
+
283 public byte[] getData() { return _data; }
+
284 // Get bytes memory buffer capacity
+
285 public long getCapacity() { return _data.length; }
+
286 // Get bytes memory buffer size
+
287 public long getSize() { return _size; }
+
288 // Get bytes memory buffer offset
+
289 public long getOffset() { return _offset; }
+
290
+
291 // Initialize a new expandable buffer with zero capacity
+
292 public Buffer() { attach(); }
+
293 // Initialize a new expandable buffer with the given capacity
+
294 public Buffer(long capacity) { attach(capacity); }
+
295 // Initialize a new buffer based on the specified byte array
+
296 public Buffer(byte[] buffer) { attach(buffer); }
+
297 // Initialize a new buffer based on the specified region (offset) of a byte array
+
298 public Buffer(byte[] buffer, long offset) { attach(buffer, offset); }
+
299 // Initialize a new buffer based on the specified region (size and offset) of a byte array
+
300 public Buffer(byte[] buffer, long size, long offset) { attach(buffer, size, offset); }
+
301
+
302 // Attach memory buffer methods
+
303 public void attach() { _data = new byte[0]; _size = 0; _offset = 0; }
+
304 public void attach(long capacity) { _data = new byte[(int)capacity]; _size = 0; _offset = 0; }
+
305 public void attach(byte[] buffer) { _data = buffer; _size = buffer.length; _offset = 0; }
+
306 public void attach(byte[] buffer, long offset) { _data = buffer; _size = buffer.length; _offset = offset; }
+
307 public void attach(byte[] buffer, long size, long offset) { _data = buffer; _size = size; _offset = offset; }
+
308
+
309 // Allocate memory in the current buffer and return offset to the allocated memory block
+
310 public long allocate(long size)
+
311 {
+
312 assert (size >= 0) : "Invalid allocation size!";
+
313 if (size < 0)
+
314 throw new IllegalArgumentException("Invalid allocation size!");
+
315
+
316 long offset = _size;
+
317
+
318 // Calculate a new buffer size
+
319 long total = _size + size;
+
320
+
321 if (total <= _data.length)
+
322 {
+
323 _size = total;
+
324 return offset;
+
325 }
+
326
+
327 byte[] data = new byte[(int)Math.max(total, 2 * _data.length)];
+
328 System.arraycopy(_data, 0, data, 0, (int)_size);
+
329 _data = data;
+
330 _size = total;
+
331 return offset;
+
332 }
+
333
+
334 // Remove some memory of the given size from the current buffer
+
335 public void remove(long offset, long size)
+
336 {
+
337 assert ((offset + size) <= _size) : "Invalid offset & size!";
+
338 if ((offset + size) > _size)
+
339 throw new IllegalArgumentException("Invalid offset & size!");
+
340
+
341 System.arraycopy(_data, (int)(offset + size), _data, (int)offset, (int)(_size - size - offset));
+
342 _size -= size;
+
343 if (_offset >= (offset + size))
+
344 _offset -= size;
+
345 else if (_offset >= offset)
+
346 {
+
347 _offset -= _offset - offset;
+
348 if (_offset > _size)
+
349 _offset = _size;
+
350 }
+
351 }
+
352
+
353 // Reserve memory of the given capacity in the current buffer
+
354 public void reserve(long capacity)
+
355 {
+
356 assert (capacity >= 0) : "Invalid reserve capacity!";
+
357 if (capacity < 0)
+
358 throw new IllegalArgumentException("Invalid reserve capacity!");
+
359
+
360 if (capacity > _data.length)
+
361 {
+
362 byte[] data = new byte[(int)Math.max(capacity, 2 * _data.length)];
+
363 System.arraycopy(_data, 0, data, 0, (int)_size);
+
364 _data = data;
+
365 }
+
366 }
+
367
+
368 // Resize the current buffer
+
369 public void resize(long size)
+
370 {
+
371 reserve(size);
+
372 _size = size;
+
373 if (_offset > _size)
+
374 _offset = _size;
+
375 }
+
376
+
377 // Reset the current buffer and its offset
+
378 public void reset()
+
379 {
+
380 _size = 0;
+
381 _offset = 0;
+
382 }
+
383
+
384 // Shift the current buffer offset
+
385 public void shift(long offset) { _offset += offset; }
+
386 // Unshift the current buffer offset
+
387 public void unshift(long offset) { _offset -= offset; }
+
388
+
389 // Buffer I/O methods
+
390
+
391 public static boolean readBoolean(byte[] buffer, long offset)
+
392 {
+
393 return buffer[(int)offset] != 0;
+
394 }
+
395
+
396 public static byte readByte(byte[] buffer, long offset)
+
397 {
+
398 return buffer[(int)offset];
+
399 }
+
400
+
401 public static char readChar(byte[] buffer, long offset)
+
402 {
+
403 return (char)readInt8(buffer, offset);
+
404 }
+
405
+
406 public static char readWChar(byte[] buffer, long offset)
+
407 {
+
408 return (char)readInt32(buffer, offset);
+
409 }
+
410
+
411 public static byte readInt8(byte[] buffer, long offset)
+
412 {
+
413 return buffer[(int)offset];
+
414 }
+
415
+
416 public static short readInt16(byte[] buffer, long offset)
+
417 {
+
418 return (short)(((buffer[(int)offset + 0] & 0xFF) << 0) | ((buffer[(int)offset + 1] & 0xFF) << 8));
+
419 }
+
420
+
421 public static int readInt32(byte[] buffer, long offset)
+
422 {
+
423 return ((buffer[(int)offset + 0] & 0xFF) << 0)|
+
424 ((buffer[(int)offset + 1] & 0xFF) << 8)|
+
425 ((buffer[(int)offset + 2] & 0xFF) << 16)|
+
426 ((buffer[(int)offset + 3] & 0xFF) << 24);
+
427 }
+
428
+
429 public static long readInt64(byte[] buffer, long offset)
+
430 {
+
431 return (((long)buffer[(int)offset + 0] & 0xFF) << 0)|
+
432 (((long)buffer[(int)offset + 1] & 0xFF) << 8)|
+
433 (((long)buffer[(int)offset + 2] & 0xFF) << 16)|
+
434 (((long)buffer[(int)offset + 3] & 0xFF) << 24)|
+
435 (((long)buffer[(int)offset + 4] & 0xFF) << 32)|
+
436 (((long)buffer[(int)offset + 5] & 0xFF) << 40)|
+
437 (((long)buffer[(int)offset + 6] & 0xFF) << 48)|
+
438 (((long)buffer[(int)offset + 7] & 0xFF) << 56);
+
439 }
+
440
+
441 private static long readInt64BE(byte[] buffer, long offset)
+
442 {
+
443 return (((long)buffer[(int)offset + 0] & 0xFF) << 56)|
+
444 (((long)buffer[(int)offset + 1] & 0xFF) << 48)|
+
445 (((long)buffer[(int)offset + 2] & 0xFF) << 40)|
+
446 (((long)buffer[(int)offset + 3] & 0xFF) << 32)|
+
447 (((long)buffer[(int)offset + 4] & 0xFF) << 24)|
+
448 (((long)buffer[(int)offset + 5] & 0xFF) << 16)|
+
449 (((long)buffer[(int)offset + 6] & 0xFF) << 8)|
+
450 (((long)buffer[(int)offset + 7] & 0xFF) << 0);
+
451 }
+
452
+
453 public static float readFloat(byte[] buffer, long offset)
+
454 {
+
455 int bits = readInt32(buffer, offset);
+
456 return Float.intBitsToFloat(bits);
+
457 }
+
458
+
459 public static double readDouble(byte[] buffer, long offset)
+
460 {
+
461 long bits = readInt64(buffer, offset);
+
462 return Double.longBitsToDouble(bits);
+
463 }
+
464
+
465 public static byte[] readBytes(byte[] buffer, long offset, long size)
+
466 {
+
467 byte[] result = new byte[(int)size];
+
468 System.arraycopy(buffer, (int)offset, result, 0, (int)size);
+
469 return result;
+
470 }
+
471
+
472 public static String readString(byte[] buffer, long offset, long size)
+
473 {
+
474 return new String(buffer, (int)offset, (int)size, java.nio.charset.StandardCharsets.UTF_8);
+
475 }
+
476
+
477 public static java.util.UUID readUUID(byte[] buffer, long offset)
+
478 {
+
479 return new java.util.UUID(readInt64BE(buffer, offset), readInt64BE(buffer, offset + 8));
+
480 }
+
481
+
482 public static void write(byte[] buffer, long offset, boolean value)
+
483 {
+
484 buffer[(int)offset] = (byte)(value ? 1 : 0);
+
485 }
+
486
+
487 public static void write(byte[] buffer, long offset, byte value)
+
488 {
+
489 buffer[(int)offset] = value;
+
490 }
+
491
+
492 public static void write(byte[] buffer, long offset, short value)
+
493 {
+
494 buffer[(int)offset + 0] = (byte)(value >> 0);
+
495 buffer[(int)offset + 1] = (byte)(value >> 8);
+
496 }
+
497
+
498 public static void write(byte[] buffer, long offset, int value)
+
499 {
+
500 buffer[(int)offset + 0] = (byte)(value >> 0);
+
501 buffer[(int)offset + 1] = (byte)(value >> 8);
+
502 buffer[(int)offset + 2] = (byte)(value >> 16);
+
503 buffer[(int)offset + 3] = (byte)(value >> 24);
+
504 }
+
505
+
506 public static void write(byte[] buffer, long offset, long value)
+
507 {
+
508 buffer[(int)offset + 0] = (byte)(value >> 0);
+
509 buffer[(int)offset + 1] = (byte)(value >> 8);
+
510 buffer[(int)offset + 2] = (byte)(value >> 16);
+
511 buffer[(int)offset + 3] = (byte)(value >> 24);
+
512 buffer[(int)offset + 4] = (byte)(value >> 32);
+
513 buffer[(int)offset + 5] = (byte)(value >> 40);
+
514 buffer[(int)offset + 6] = (byte)(value >> 48);
+
515 buffer[(int)offset + 7] = (byte)(value >> 56);
+
516 }
+
517
+
518 private static void writeBE(byte[] buffer, long offset, long value)
+
519 {
+
520 buffer[(int)offset + 0] = (byte)(value >> 56);
+
521 buffer[(int)offset + 1] = (byte)(value >> 48);
+
522 buffer[(int)offset + 2] = (byte)(value >> 40);
+
523 buffer[(int)offset + 3] = (byte)(value >> 32);
+
524 buffer[(int)offset + 4] = (byte)(value >> 24);
+
525 buffer[(int)offset + 5] = (byte)(value >> 16);
+
526 buffer[(int)offset + 6] = (byte)(value >> 8);
+
527 buffer[(int)offset + 7] = (byte)(value >> 0);
+
528 }
+
529
+
530 public static void write(byte[] buffer, long offset, float value)
+
531 {
+
532 int bits = Float.floatToIntBits(value);
+
533 write(buffer, offset, bits);
+
534 }
+
535
+
536 public static void write(byte[] buffer, long offset, double value)
+
537 {
+
538 long bits = Double.doubleToLongBits(value);
+
539 write(buffer, offset, bits);
+
540 }
+
541
+
542 public static void write(byte[] buffer, long offset, byte[] value)
+
543 {
+
544 System.arraycopy(value, 0, buffer, (int)offset, value.length);
+
545 }
+
546
+
547 public static void write(byte[] buffer, long offset, byte[] value, long valueOffset, long valueSize)
+
548 {
+
549 System.arraycopy(value, (int)valueOffset, buffer, (int)offset, (int)valueSize);
+
550 }
+
551
+
552 public static void write(byte[] buffer, long offset, byte value, long valueCount)
+
553 {
+
554 for (long i = 0; i < valueCount; i++)
+
555 buffer[(int)(offset + i)] = value;
+
556 }
+
557
+
558 public static void write(byte[] buffer, long offset, java.util.UUID value)
+
559 {
+
560 writeBE(buffer, offset, value.getMostSignificantBits());
+
561 writeBE(buffer, offset + 8, value.getLeastSignificantBits());
+
562 }
+
563}
+
564)CODE";
+
565
+
566 // Prepare code template
+
567 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
568
+
569 Write(code);
+
570
+
571 // Generate footer
+
572 GenerateFooter();
+
573
+
574 // Store the file
+
575 WriteEnd();
+
576 Store(file);
+
577}
+
578
+
579void GeneratorJava::GenerateFBEModel(const std::string& domain, const std::string& package)
+
580{
+
581 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
582
+
583 // Generate the file
+
584 CppCommon::Path file = path / "Model.java";
+
585 WriteBegin();
+
586
+
587 // Generate headers
+
588 GenerateHeader("FBE");
+
589 GenerateImports(domain, package);
+
590
+
591 std::string code = R"CODE(
+
592// Fast Binary Encoding base model
+
593public class Model
+
594{
+
595 private Buffer _buffer;
+
596
+
597 // Get bytes buffer
+
598 public Buffer getBuffer() { return _buffer; }
+
599
+
600 // Initialize a new model
+
601 protected Model() { _buffer = new Buffer(); }
+
602 protected Model(Buffer buffer) { _buffer = buffer; }
+
603
+
604 // Attach memory buffer methods
+
605 public void attach() { _buffer.attach(); }
+
606 public void attach(long capacity) { _buffer.attach(capacity); }
+
607 public void attach(byte[] buffer) { _buffer.attach(buffer); }
+
608 public void attach(byte[] buffer, long offset) { _buffer.attach(buffer, offset); }
+
609 public void attach(byte[] buffer, long size, long offset) { _buffer.attach(buffer, size, offset); }
+
610 public void attach(Buffer buffer) { _buffer.attach(buffer.getData(), buffer.getSize(), buffer.getOffset()); }
+
611 public void attach(Buffer buffer, long offset) { _buffer.attach(buffer.getData(), buffer.getSize(), offset); }
+
612
+
613 // Model buffer operations
+
614 public long allocate(long size) { return _buffer.allocate(size); }
+
615 public void remove(long offset, long size) { _buffer.remove(offset, size); }
+
616 public void reserve(long capacity) { _buffer.reserve(capacity); }
+
617 public void resize(long size) { _buffer.resize(size); }
+
618 public void reset() { _buffer.reset(); }
+
619 public void shift(long offset) { _buffer.shift(offset); }
+
620 public void unshift(long offset) { _buffer.unshift(offset); }
+
621
+
622 // Buffer I/O methods
+
623 protected int readInt32(long offset) { return Buffer.readInt32(_buffer.getData(), _buffer.getOffset() + offset); }
+
624 protected void write(long offset, int value) { Buffer.write(_buffer.getData(), _buffer.getOffset() + offset, value); }
+
625}
+
626)CODE";
+
627
+
628 // Prepare code template
+
629 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
630
+
631 Write(code);
+
632
+
633 // Generate footer
+
634 GenerateFooter();
+
635
+
636 // Store the file
+
637 WriteEnd();
+
638 Store(file);
+
639}
+
640
+
641void GeneratorJava::GenerateFBEFieldModel(const std::string& domain, const std::string& package)
+
642{
+
643 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
644
+
645 // Generate the file
+
646 CppCommon::Path file = path / "FieldModel.java";
+
647 WriteBegin();
+
648
+
649 // Generate headers
+
650 GenerateHeader("FBE");
+
651 GenerateImports(domain, package);
+
652
+
653 std::string code = R"CODE(
+
654// Fast Binary Encoding base field model
+
655public abstract class FieldModel
+
656{
+
657 protected Buffer _buffer;
+
658 protected long _offset;
+
659
+
660 // Get the field offset
+
661 public long fbeOffset() { return _offset; }
+
662 // Set the field offset
+
663 public void fbeOffset(long value) { _offset = value; }
+
664
+
665 // Get the field size
+
666 public long fbeSize() { return 0; }
+
667 // Get the field extra size
+
668 public long fbeExtra() { return 0; }
+
669
+
670 // Shift the current field offset
+
671 public void fbeShift(long size) { _offset += size; }
+
672 // Unshift the current field offset
+
673 public void fbeUnshift(long size) { _offset -= size; }
+
674
+
675 // Initialize a new field model
+
676 protected FieldModel(Buffer buffer, long offset)
+
677 {
+
678 _buffer = buffer;
+
679 _offset = offset;
+
680 }
+
681
+
682 // Check if the value is valid
+
683 public boolean verify() { return true; }
+
684
+
685 // Buffer I/O methods
+
686 protected boolean readBoolean(long offset) { return Buffer.readBoolean(_buffer.getData(), _buffer.getOffset() + offset); }
+
687 protected byte readByte(long offset) { return Buffer.readByte(_buffer.getData(), _buffer.getOffset() + offset); }
+
688 protected char readChar(long offset) { return Buffer.readChar(_buffer.getData(), _buffer.getOffset() + offset); }
+
689 protected char readWChar(long offset) { return Buffer.readWChar(_buffer.getData(), _buffer.getOffset() + offset); }
+
690 protected byte readInt8(long offset) { return Buffer.readInt8(_buffer.getData(), _buffer.getOffset() + offset); }
+
691 protected short readInt16(long offset) { return Buffer.readInt16(_buffer.getData(), _buffer.getOffset() + offset); }
+
692 protected int readInt32(long offset) { return Buffer.readInt32(_buffer.getData(), _buffer.getOffset() + offset); }
+
693 protected long readInt64(long offset) { return Buffer.readInt64(_buffer.getData(), _buffer.getOffset() + offset); }
+
694 protected float readFloat(long offset) { return Buffer.readFloat(_buffer.getData(), _buffer.getOffset() + offset); }
+
695 protected double readDouble(long offset) { return Buffer.readDouble(_buffer.getData(), _buffer.getOffset() + offset); }
+
696 protected byte[] readBytes(long offset, long size) { return Buffer.readBytes(_buffer.getData(), _buffer.getOffset() + offset, size); }
+
697 protected String readString(long offset, long size) { return Buffer.readString(_buffer.getData(), _buffer.getOffset() + offset, size); }
+
698 protected java.util.UUID readUUID(long offset) { return Buffer.readUUID(_buffer.getData(), _buffer.getOffset() + offset); }
+
699 protected void write(long offset, boolean value) { Buffer.write(_buffer.getData(), _buffer.getOffset() + offset, value); }
+
700 protected void write(long offset, byte value) { Buffer.write(_buffer.getData(), _buffer.getOffset() + offset, value); }
+
701 protected void write(long offset, short value) { Buffer.write(_buffer.getData(), _buffer.getOffset() + offset, value); }
+
702 protected void write(long offset, int value) { Buffer.write(_buffer.getData(), _buffer.getOffset() + offset, value); }
+
703 protected void write(long offset, long value) { Buffer.write(_buffer.getData(), _buffer.getOffset() + offset, value); }
+
704 protected void write(long offset, float value) { Buffer.write(_buffer.getData(), _buffer.getOffset() + offset, value); }
+
705 protected void write(long offset, double value) { Buffer.write(_buffer.getData(), _buffer.getOffset() + offset, value); }
+
706 protected void write(long offset, byte[] value) { Buffer.write(_buffer.getData(), _buffer.getOffset() + offset, value); }
+
707 protected void write(long offset, byte[] value, long valueOffset, long valueSize) { Buffer.write(_buffer.getData(), _buffer.getOffset() + offset, value, valueOffset, valueSize); }
+
708 protected void write(long offset, byte value, long valueCount) { Buffer.write(_buffer.getData(), _buffer.getOffset() + offset, value, valueCount); }
+
709 protected void write(long offset, java.util.UUID value) { Buffer.write(_buffer.getData(), _buffer.getOffset() + offset, value); }
+
710}
+
711)CODE";
+
712
+
713 // Prepare code template
+
714 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
715
+
716 Write(code);
+
717
+
718 // Generate footer
+
719 GenerateFooter();
+
720
+
721 // Store the file
+
722 WriteEnd();
+
723 Store(file);
+
724}
+
725
+
726void GeneratorJava::GenerateFBEFieldModel(const std::string& domain, const std::string& package, const std::string& name, const std::string& type, const std::string& base, const std::string& size, const std::string& defaults)
+
727{
+
728 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
729
+
730 // Generate the file
+
731 CppCommon::Path file = path / ("FieldModel" + name + ".java");
+
732 WriteBegin();
+
733
+
734 // Generate headers
+
735 GenerateHeader("FBE");
+
736 GenerateImports(domain, package);
+
737
+
738 std::string code = R"CODE(
+
739// Fast Binary Encoding _TYPE_ field model
+
740public final class FieldModel_NAME_ extends FieldModel
+
741{
+
742 public FieldModel_NAME_(Buffer buffer, long offset) { super(buffer, offset); }
+
743
+
744 // Get the field size
+
745 @Override
+
746 public long fbeSize() { return _SIZE_; }
+
747
+
748 // Get the value
+
749 public _TYPE_ get() { return get(_DEFAULTS_); }
+
750 public _TYPE_ get(_TYPE_ defaults)
+
751 {
+
752 if ((_buffer.getOffset() + fbeOffset() + fbeSize()) > _buffer.getSize())
+
753 return defaults;
+
754
+
755 return read_NAME_(fbeOffset());
+
756 }
+
757
+
758 // Set the value
+
759 public void set(_TYPE_ value)
+
760 {
+
761 assert ((_buffer.getOffset() + fbeOffset() + fbeSize()) <= _buffer.getSize()) : "Model is broken!";
+
762 if ((_buffer.getOffset() + fbeOffset() + fbeSize()) > _buffer.getSize())
+
763 return;
+
764
+
765 write(fbeOffset(), _BASE_value);
+
766 }
+
767}
+
768)CODE";
+
769
+
770 // Prepare code template
+
771 code = std::regex_replace(code, std::regex("_NAME_"), name);
+
772 code = std::regex_replace(code, std::regex("_TYPE_"), type);
+
773 code = std::regex_replace(code, std::regex("_BASE_"), base);
+
774 code = std::regex_replace(code, std::regex("_SIZE_"), size);
+
775 code = std::regex_replace(code, std::regex("_DEFAULTS_"), defaults);
+
776 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
777
+
778 Write(code);
+
779
+
780 // Generate footer
+
781 GenerateFooter();
+
782
+
783 // Store the file
+
784 WriteEnd();
+
785 Store(file);
+
786}
+
787
+
788void GeneratorJava::GenerateFBEFieldModelDecimal(const std::string& domain, const std::string& package)
+
789{
+
790 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
791
+
792 // Generate the file
+
793 CppCommon::Path file = path / "FieldModelDecimal.java";
+
794 WriteBegin();
+
795
+
796 // Generate headers
+
797 GenerateHeader("FBE");
+
798 GenerateImports(domain, package);
+
799
+
800 std::string code = R"CODE(
+
801// Fast Binary Encoding decimal field model
+
802public final class FieldModelDecimal extends FieldModel
+
803{
+
804 public FieldModelDecimal(Buffer buffer, long offset) { super(buffer, offset); }
+
805
+
806 // Get the field size
+
807 @Override
+
808 public long fbeSize() { return 16; }
+
809
+
810 // Get the decimal value
+
811 public java.math.BigDecimal get() { return get(java.math.BigDecimal.valueOf(0L)); }
+
812 public java.math.BigDecimal get(java.math.BigDecimal defaults)
+
813 {
+
814 assert (defaults != null) : "Invalid default decimal value!";
+
815 if (defaults == null)
+
816 throw new IllegalArgumentException("Invalid default decimal value!");
+
817
+
818 if ((_buffer.getOffset() + fbeOffset() + fbeSize()) > _buffer.getSize())
+
819 return defaults;
+
820
+
821 byte[] magnitude = readBytes(fbeOffset(), 12);
+
822 int scale = readByte(fbeOffset() + 14);
+
823 int signum = (readByte(fbeOffset() + 15) < 0) ? -1 : 1;
+
824
+
825 // Reverse magnitude
+
826 for(int i = 0; i < magnitude.length / 2; i++)
+
827 {
+
828 byte temp = magnitude[i];
+
829 magnitude[i] = magnitude[magnitude.length - i - 1];
+
830 magnitude[magnitude.length - i - 1] = temp;
+
831 }
+
832
+
833 var unscaled = new java.math.BigInteger(signum, magnitude);
+
834
+
835 return new java.math.BigDecimal(unscaled, scale);
+
836 }
+
837
+
838 // Set the decimal value
+
839 public void set(java.math.BigDecimal value)
+
840 {
+
841 assert (value != null) : "Invalid decimal value!";
+
842 if (value == null)
+
843 throw new IllegalArgumentException("Invalid decimal value!");
+
844
+
845 assert ((_buffer.getOffset() + fbeOffset() + fbeSize()) <= _buffer.getSize()) : "Model is broken!";
+
846 if ((_buffer.getOffset() + fbeOffset() + fbeSize()) > _buffer.getSize())
+
847 return;
+
848
+
849 // Get unscaled absolute value
+
850 java.math.BigInteger unscaled = value.abs().unscaledValue();
+
851 int bitLength = unscaled.bitLength();
+
852 if ((bitLength < 0) || (bitLength > 96))
+
853 {
+
854 // Value too big for .NET Decimal (bit length is limited to [0, 96])
+
855 write(fbeOffset(), (byte)0, fbeSize());
+
856 return;
+
857 }
+
858
+
859 // Get byte array
+
860 byte[] unscaledBytes = unscaled.toByteArray();
+
861
+
862 // Get scale
+
863 int scale = value.scale();
+
864 if ((scale < 0) || (scale > 28))
+
865 {
+
866 // Value scale exceeds .NET Decimal limit of [0, 28]
+
867 write(fbeOffset(), (byte)0, fbeSize());
+
868 return;
+
869 }
+
870
+
871 // Write unscaled value to bytes 0-11
+
872 int index = 0;
+
873 for (int i = unscaledBytes.length - 1; (i >= 0) && (index < 12); i--, index++)
+
874 write(fbeOffset() + index, unscaledBytes[i]);
+
875
+
876 // Fill remaining bytes with zeros
+
877 for (; index < 14; index++)
+
878 write(fbeOffset() + index, (byte)0);
+
879
+
880 // Write scale at byte 14
+
881 write(fbeOffset() + 14, (byte)scale);
+
882
+
883 // Write signum at byte 15
+
884 write(fbeOffset() + 15, (byte)((value.signum() < 0) ? -128 : 0));
+
885 }
+
886}
+
887)CODE";
+
888
+
889 // Prepare code template
+
890 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
891
+
892 Write(code);
+
893
+
894 // Generate footer
+
895 GenerateFooter();
+
896
+
897 // Store the file
+
898 WriteEnd();
+
899 Store(file);
+
900}
+
901
+
902void GeneratorJava::GenerateFBEFieldModelDate(const std::string& domain, const std::string& package)
+
903{
+
904 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
905
+
906 // Generate the file
+
907 CppCommon::Path file = path / "FieldModelDate.java";
+
908 WriteBegin();
+
909
+
910 // Generate headers
+
911 GenerateHeader("FBE");
+
912 GenerateImports(domain, package);
+
913
+
914 std::string code = R"CODE(
+
915// Fast Binary Encoding date field model
+
916public final class FieldModelDate extends FieldModel
+
917{
+
918 public FieldModelDate(Buffer buffer, long offset) { super(buffer, offset); }
+
919
+
920 // Get the field size
+
921 @Override
+
922 public long fbeSize() { return 8; }
+
923
+
924 // Get the date value
+
925 public java.util.Date get() { return get(new java.util.Date(0)); }
+
926 public java.util.Date get(java.util.Date defaults)
+
927 {
+
928 assert (defaults != null) : "Invalid default date value!";
+
929 if (defaults == null)
+
930 throw new IllegalArgumentException("Invalid default date value!");
+
931
+
932 if ((_buffer.getOffset() + fbeOffset() + fbeSize()) > _buffer.getSize())
+
933 return defaults;
+
934
+
935 long nanoseconds = readInt64(fbeOffset());
+
936 return new java.util.Date(nanoseconds / 1000000);
+
937 }
+
938
+
939 // Set the date value
+
940 public void set(java.util.Date value)
+
941 {
+
942 assert (value != null) : "Invalid date value!";
+
943 if (value == null)
+
944 throw new IllegalArgumentException("Invalid date value!");
+
945
+
946 assert ((_buffer.getOffset() + fbeOffset() + fbeSize()) <= _buffer.getSize()) : "Model is broken!";
+
947 if ((_buffer.getOffset() + fbeOffset() + fbeSize()) > _buffer.getSize())
+
948 return;
+
949
+
950 long nanoseconds = value.getTime() * 1000;
+
951 write(fbeOffset(), nanoseconds);
+
952 }
+
953}
+
954)CODE";
+
955
+
956 // Prepare code template
+
957 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
958
+
959 Write(code);
+
960
+
961 // Generate footer
+
962 GenerateFooter();
+
963
+
964 // Store the file
+
965 WriteEnd();
+
966 Store(file);
+
967}
+
968
+
969void GeneratorJava::GenerateFBEFieldModelTimestamp(const std::string& domain, const std::string& package)
+
970{
+
971 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
972
+
973 // Generate the file
+
974 CppCommon::Path file = path / "FieldModelTimestamp.java";
+
975 WriteBegin();
+
976
+
977 // Generate headers
+
978 GenerateHeader("FBE");
+
979 GenerateImports(domain, package);
+
980
+
981 std::string code = R"CODE(
+
982// Fast Binary Encoding timestamp field model
+
983public final class FieldModelTimestamp extends FieldModel
+
984{
+
985 public FieldModelTimestamp(Buffer buffer, long offset) { super(buffer, offset); }
+
986
+
987 // Get the field size
+
988 @Override
+
989 public long fbeSize() { return 8; }
+
990
+
991 // Get the timestamp value
+
992 public java.time.Instant get() { return get(java.time.Instant.EPOCH); }
+
993 public java.time.Instant get(java.time.Instant defaults)
+
994 {
+
995 assert (defaults != null) : "Invalid default timestamp value!";
+
996 if (defaults == null)
+
997 throw new IllegalArgumentException("Invalid default timestamp value!");
+
998
+
999 if ((_buffer.getOffset() + fbeOffset() + fbeSize()) > _buffer.getSize())
+
1000 return defaults;
+
1001
+
1002 long nanoseconds = readInt64(fbeOffset());
+
1003 return java.time.Instant.ofEpochSecond(nanoseconds / 1000000000, nanoseconds % 1000000000);
+
1004 }
+
1005
+
1006 // Set the timestamp value
+
1007 public void set(java.time.Instant value)
+
1008 {
+
1009 assert (value != null) : "Invalid timestamp value!";
+
1010 if (value == null)
+
1011 throw new IllegalArgumentException("Invalid timestamp value!");
+
1012
+
1013 assert ((_buffer.getOffset() + fbeOffset() + fbeSize()) <= _buffer.getSize()) : "Model is broken!";
+
1014 if ((_buffer.getOffset() + fbeOffset() + fbeSize()) > _buffer.getSize())
+
1015 return;
+
1016
+
1017 long nanoseconds = value.getEpochSecond() * 1000000000 + value.getNano();
+
1018 write(fbeOffset(), nanoseconds);
+
1019 }
+
1020}
+
1021)CODE";
+
1022
+
1023 // Prepare code template
+
1024 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
1025
+
1026 Write(code);
+
1027
+
1028 // Generate footer
+
1029 GenerateFooter();
+
1030
+
1031 // Store the file
+
1032 WriteEnd();
+
1033 Store(file);
+
1034}
+
1035
+
1036void GeneratorJava::GenerateFBEFieldModelBytes(const std::string& domain, const std::string& package)
+
1037{
+
1038 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
1039
+
1040 // Generate the file
+
1041 CppCommon::Path file = path / "FieldModelBytes.java";
+
1042 WriteBegin();
+
1043
+
1044 // Generate headers
+
1045 GenerateHeader("FBE");
+
1046 GenerateImports(domain, package);
+
1047
+
1048 std::string code = R"CODE(
+
1049// Fast Binary Encoding bytes field model
+
1050public final class FieldModelBytes extends FieldModel
+
1051{
+
1052 public FieldModelBytes(Buffer buffer, long offset) { super(buffer, offset); }
+
1053
+
1054 // Get the field size
+
1055 @Override
+
1056 public long fbeSize() { return 4; }
+
1057 // Get the field extra size
+
1058 @Override
+
1059 public long fbeExtra()
+
1060 {
+
1061 if ((_buffer.getOffset() + fbeOffset() + fbeSize()) > _buffer.getSize())
+
1062 return 0;
+
1063
+
1064 int fbeBytesOffset = readInt32(fbeOffset());
+
1065 if ((fbeBytesOffset == 0) || ((_buffer.getOffset() + fbeBytesOffset + 4) > _buffer.getSize()))
+
1066 return 0;
+
1067
+
1068 int fbeBytesSize = readInt32(fbeBytesOffset);
+
1069 return 4 + fbeBytesSize;
+
1070 }
+
1071
+
1072 // Check if the bytes value is valid
+
1073 @Override
+
1074 public boolean verify()
+
1075 {
+
1076 if ((_buffer.getOffset() + fbeOffset() + fbeSize()) > _buffer.getSize())
+
1077 return true;
+
1078
+
1079 int fbeBytesOffset = readInt32(fbeOffset());
+
1080 if (fbeBytesOffset == 0)
+
1081 return true;
+
1082
+
1083 if ((_buffer.getOffset() + fbeBytesOffset + 4) > _buffer.getSize())
+
1084 return false;
+
1085
+
1086 int fbeBytesSize = readInt32(fbeBytesOffset);
+
1087 if ((_buffer.getOffset() + fbeBytesOffset + 4 + fbeBytesSize) > _buffer.getSize())
+
1088 return false;
+
1089
+
1090 return true;
+
1091 }
+
1092
+
1093 // Get the bytes value
+
1094 public java.nio.ByteBuffer get() { return get(java.nio.ByteBuffer.allocate(0)); }
+
1095 public java.nio.ByteBuffer get(java.nio.ByteBuffer defaults)
+
1096 {
+
1097 assert (defaults != null) : "Invalid default bytes value!";
+
1098 if (defaults == null)
+
1099 throw new IllegalArgumentException("Invalid default bytes value!");
+
1100
+
1101 if ((_buffer.getOffset() + fbeOffset() + fbeSize()) > _buffer.getSize())
+
1102 return defaults;
+
1103
+
1104 int fbeBytesOffset = readInt32(fbeOffset());
+
1105 if (fbeBytesOffset == 0)
+
1106 return defaults;
+
1107
+
1108 assert ((_buffer.getOffset() + fbeBytesOffset + 4) <= _buffer.getSize()) : "Model is broken!";
+
1109 if ((_buffer.getOffset() + fbeBytesOffset + 4) > _buffer.getSize())
+
1110 return defaults;
+
1111
+
1112 int fbeBytesSize = readInt32(fbeBytesOffset);
+
1113 assert ((_buffer.getOffset() + fbeBytesOffset + 4 + fbeBytesSize) <= _buffer.getSize()) : "Model is broken!";
+
1114 if ((_buffer.getOffset() + fbeBytesOffset + 4 + fbeBytesSize) > _buffer.getSize())
+
1115 return defaults;
+
1116
+
1117 return java.nio.ByteBuffer.wrap(readBytes(fbeBytesOffset + 4, fbeBytesSize));
+
1118 }
+
1119
+
1120 // Set the bytes value
+
1121 public void set(java.nio.ByteBuffer value)
+
1122 {
+
1123 assert (value != null) : "Invalid bytes value!";
+
1124 if (value == null)
+
1125 throw new IllegalArgumentException("Invalid bytes value!");
+
1126
+
1127 assert ((_buffer.getOffset() + fbeOffset() + fbeSize()) <= _buffer.getSize()) : "Model is broken!";
+
1128 if ((_buffer.getOffset() + fbeOffset() + fbeSize()) > _buffer.getSize())
+
1129 return;
+
1130
+
1131 int fbeBytesSize = value.array().length;
+
1132 int fbeBytesOffset = (int)(_buffer.allocate(4 + fbeBytesSize) - _buffer.getOffset());
+
1133 assert ((fbeBytesOffset > 0) && ((_buffer.getOffset() + fbeBytesOffset + 4 + fbeBytesSize) <= _buffer.getSize())) : "Model is broken!";
+
1134 if ((fbeBytesOffset <= 0) || ((_buffer.getOffset() + fbeBytesOffset + 4 + fbeBytesSize) > _buffer.getSize()))
+
1135 return;
+
1136
+
1137 write(fbeOffset(), fbeBytesOffset);
+
1138 write(fbeBytesOffset, fbeBytesSize);
+
1139 write(fbeBytesOffset + 4, value.array());
+
1140 }
+
1141}
+
1142)CODE";
+
1143
+
1144 // Prepare code template
+
1145 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
1146
+
1147 Write(code);
+
1148
+
1149 // Generate footer
+
1150 GenerateFooter();
+
1151
+
1152 // Store the file
+
1153 WriteEnd();
+
1154 Store(file);
+
1155}
+
1156
+
1157void GeneratorJava::GenerateFBEFieldModelString(const std::string& domain, const std::string& package)
+
1158{
+
1159 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
1160
+
1161 // Generate the file
+
1162 CppCommon::Path file = path / "FieldModelString.java";
+
1163 WriteBegin();
+
1164
+
1165 // Generate headers
+
1166 GenerateHeader("FBE");
+
1167 GenerateImports(domain, package);
+
1168
+
1169 std::string code = R"CODE(
+
1170// Fast Binary Encoding string field model
+
1171public final class FieldModelString extends FieldModel
+
1172{
+
1173 public FieldModelString(Buffer buffer, long offset) { super(buffer, offset); }
+
1174
+
1175 // Get the field size
+
1176 @Override
+
1177 public long fbeSize() { return 4; }
+
1178 // Get the field extra size
+
1179 @Override
+
1180 public long fbeExtra()
+
1181 {
+
1182 if ((_buffer.getOffset() + fbeOffset() + fbeSize()) > _buffer.getSize())
+
1183 return 0;
+
1184
+
1185 int fbeStringOffset = readInt32(fbeOffset());
+
1186 if ((fbeStringOffset == 0) || ((_buffer.getOffset() + fbeStringOffset + 4) > _buffer.getSize()))
+
1187 return 0;
+
1188
+
1189 int fbeStringSize = readInt32(fbeStringOffset);
+
1190 return 4 + fbeStringSize;
+
1191 }
+
1192
+
1193 // Check if the string value is valid
+
1194 @Override
+
1195 public boolean verify()
+
1196 {
+
1197 if ((_buffer.getOffset() + fbeOffset() + fbeSize()) > _buffer.getSize())
+
1198 return true;
+
1199
+
1200 int fbeStringOffset = readInt32(fbeOffset());
+
1201 if (fbeStringOffset == 0)
+
1202 return true;
+
1203
+
1204 if ((_buffer.getOffset() + fbeStringOffset + 4) > _buffer.getSize())
+
1205 return false;
+
1206
+
1207 int fbeStringSize = readInt32(fbeStringOffset);
+
1208 if ((_buffer.getOffset() + fbeStringOffset + 4 + fbeStringSize) > _buffer.getSize())
+
1209 return false;
+
1210
+
1211 return true;
+
1212 }
+
1213
+
1214 // Get the string value
+
1215 public String get() { return get(""); }
+
1216 public String get(String defaults)
+
1217 {
+
1218 assert (defaults != null) : "Invalid default string value!";
+
1219 if (defaults == null)
+
1220 throw new IllegalArgumentException("Invalid default string value!");
+
1221
+
1222 if ((_buffer.getOffset() + fbeOffset() + fbeSize()) > _buffer.getSize())
+
1223 return defaults;
+
1224
+
1225 int fbeStringOffset = readInt32(fbeOffset());
+
1226 if (fbeStringOffset == 0)
+
1227 return defaults;
+
1228
+
1229 assert ((_buffer.getOffset() + fbeStringOffset + 4) <= _buffer.getSize()) : "Model is broken!";
+
1230 if ((_buffer.getOffset() + fbeStringOffset + 4) > _buffer.getSize())
+
1231 return defaults;
+
1232
+
1233 int fbeStringSize = readInt32(fbeStringOffset);
+
1234 assert ((_buffer.getOffset() + fbeStringOffset + 4 + fbeStringSize) <= _buffer.getSize()) : "Model is broken!";
+
1235 if ((_buffer.getOffset() + fbeStringOffset + 4 + fbeStringSize) > _buffer.getSize())
+
1236 return defaults;
+
1237
+
1238 return readString(fbeStringOffset + 4, fbeStringSize);
+
1239 }
+
1240
+
1241 // Set the string value
+
1242 public void set(String value)
+
1243 {
+
1244 assert (value != null) : "Invalid string value!";
+
1245 if (value == null)
+
1246 throw new IllegalArgumentException("Invalid string value!");
+
1247
+
1248 assert ((_buffer.getOffset() + fbeOffset() + fbeSize()) <= _buffer.getSize()) : "Model is broken!";
+
1249 if ((_buffer.getOffset() + fbeOffset() + fbeSize()) > _buffer.getSize())
+
1250 return;
+
1251
+
1252 byte[] bytes = value.getBytes(java.nio.charset.StandardCharsets.UTF_8);
+
1253
+
1254 int fbeStringSize = bytes.length;
+
1255 int fbeStringOffset = (int)(_buffer.allocate(4 + fbeStringSize) - _buffer.getOffset());
+
1256 assert ((fbeStringOffset > 0) && ((_buffer.getOffset() + fbeStringOffset + 4 + fbeStringSize) <= _buffer.getSize())) : "Model is broken!";
+
1257 if ((fbeStringOffset <= 0) || ((_buffer.getOffset() + fbeStringOffset + 4 + fbeStringSize) > _buffer.getSize()))
+
1258 return;
+
1259
+
1260 write(fbeOffset(), fbeStringOffset);
+
1261 write(fbeStringOffset, fbeStringSize);
+
1262 write(fbeStringOffset + 4, bytes);
+
1263 }
+
1264}
+
1265)CODE";
+
1266
+
1267 // Prepare code template
+
1268 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
1269
+
1270 Write(code);
+
1271
+
1272 // Generate footer
+
1273 GenerateFooter();
+
1274
+
1275 // Store the file
+
1276 WriteEnd();
+
1277 Store(file);
+
1278}
+
1279
+
1280void GeneratorJava::GenerateFBEFieldModelOptional(const std::string& domain, const std::string& package, const std::string& name, const std::string& type, const std::string& model)
+
1281{
+
1282 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "fbe";
+
1283
+
1284 // Create package path
+
1285 CppCommon::Directory::CreateTree(path);
+
1286
+
1287 // Generate the file
+
1288 CppCommon::Path file = path / ("FieldModelOptional" + name + ".java");
+
1289 WriteBegin();
+
1290
+
1291 // Generate headers
+
1292 GenerateHeader(CppCommon::Path(_input).filename().string());
+
1293 GenerateImports(domain, package + ".fbe");
+
1294
+
1295 std::string code = R"CODE(
+
1296// Fast Binary Encoding optional _NAME_ field model
+
1297public final class FieldModelOptional_NAME_ extends _DOMAIN_fbe.FieldModel
+
1298{
+
1299 public FieldModelOptional_NAME_(_DOMAIN_fbe.Buffer buffer, long offset)
+
1300 {
+
1301 super(buffer, offset);
+
1302 value = new _MODEL_(buffer, 0);
+
1303 }
+
1304
+
1305 // Get the field size
+
1306 @Override
+
1307 public long fbeSize() { return 1 + 4; }
+
1308 // Get the field extra size
+
1309 @Override
+
1310 public long fbeExtra()
+
1311 {
+
1312 if (!hasValue())
+
1313 return 0;
+
1314
+
1315 int fbeOptionalOffset = readInt32(fbeOffset() + 1);
+
1316 if ((fbeOptionalOffset == 0) || ((_buffer.getOffset() + fbeOptionalOffset + 4) > _buffer.getSize()))
+
1317 return 0;
+
1318
+
1319 _buffer.shift(fbeOptionalOffset);
+
1320 long fbeResult = value.fbeSize() + value.fbeExtra();
+
1321 _buffer.unshift(fbeOptionalOffset);
+
1322 return fbeResult;
+
1323 }
+
1324
+
1325 // Checks if the object contains a value
+
1326 public boolean hasValue()
+
1327 {
+
1328 if ((_buffer.getOffset() + fbeOffset() + fbeSize()) > _buffer.getSize())
+
1329 return false;
+
1330
+
1331 byte fbeHasValue = readInt8(fbeOffset());
+
1332 return (fbeHasValue != 0);
+
1333 }
+
1334
+
1335 // Base field model value
+
1336 public final _MODEL_ value;
+
1337
+
1338 // Check if the optional value is valid
+
1339 @Override
+
1340 public boolean verify()
+
1341 {
+
1342 if ((_buffer.getOffset() + fbeOffset() + fbeSize()) > _buffer.getSize())
+
1343 return true;
+
1344
+
1345 byte fbeHasValue = readInt8(fbeOffset());
+
1346 if (fbeHasValue == 0)
+
1347 return true;
+
1348
+
1349 int fbeOptionalOffset = readInt32(fbeOffset() + 1);
+
1350 if (fbeOptionalOffset == 0)
+
1351 return false;
+
1352
+
1353 _buffer.shift(fbeOptionalOffset);
+
1354 boolean fbeResult = value.verify();
+
1355 _buffer.unshift(fbeOptionalOffset);
+
1356 return fbeResult;
+
1357 }
+
1358
+
1359 // Get the optional value (being phase)
+
1360 public long getBegin()
+
1361 {
+
1362 if (!hasValue())
+
1363 return 0;
+
1364
+
1365 int fbeOptionalOffset = readInt32(fbeOffset() + 1);
+
1366 assert (fbeOptionalOffset > 0) : "Model is broken!";
+
1367 if (fbeOptionalOffset <= 0)
+
1368 return 0;
+
1369
+
1370 _buffer.shift(fbeOptionalOffset);
+
1371 return fbeOptionalOffset;
+
1372 }
+
1373
+
1374 // Get the optional value (end phase)
+
1375 public void getEnd(long fbeBegin)
+
1376 {
+
1377 _buffer.unshift(fbeBegin);
+
1378 }
+
1379
+
1380 // Get the optional value
+
1381 public _TYPE_ get() { return get(null); }
+
1382 public _TYPE_ get(_TYPE_ defaults)
+
1383 {
+
1384 long fbeBegin = getBegin();
+
1385 if (fbeBegin == 0)
+
1386 return defaults;
+
1387
+
1388 _TYPE_ optional = value.get();
+
1389 getEnd(fbeBegin);
+
1390 return optional;
+
1391 }
+
1392
+
1393 // Set the optional value (begin phase)
+
1394 public long setBegin(boolean hasValue)
+
1395 {
+
1396 assert ((_buffer.getOffset() + fbeOffset() + fbeSize()) <= _buffer.getSize()) : "Model is broken!";
+
1397 if ((_buffer.getOffset() + fbeOffset() + fbeSize()) > _buffer.getSize())
+
1398 return 0;
+
1399
+
1400 byte fbeHasValue = (byte)(hasValue ? 1 : 0);
+
1401 write(fbeOffset(), fbeHasValue);
+
1402 if (fbeHasValue == 0)
+
1403 return 0;
+
1404
+
1405 int fbeOptionalSize = (int)value.fbeSize();
+
1406 int fbeOptionalOffset = (int)(_buffer.allocate(fbeOptionalSize) - _buffer.getOffset());
+
1407 assert ((fbeOptionalOffset > 0) && ((_buffer.getOffset() + fbeOptionalOffset + fbeOptionalSize) <= _buffer.getSize())) : "Model is broken!";
+
1408 if ((fbeOptionalOffset <= 0) || ((_buffer.getOffset() + fbeOptionalOffset + fbeOptionalSize) > _buffer.getSize()))
+
1409 return 0;
+
1410
+
1411 write(fbeOffset() + 1, fbeOptionalOffset);
+
1412
+
1413 _buffer.shift(fbeOptionalOffset);
+
1414 return fbeOptionalOffset;
+
1415 }
+
1416
+
1417 // Set the optional value (end phase)
+
1418 public void setEnd(long fbeBegin)
+
1419 {
+
1420 _buffer.unshift(fbeBegin);
+
1421 }
+
1422
+
1423 // Set the optional value
+
1424 public void set(_TYPE_ optional)
+
1425 {
+
1426 long fbeBegin = setBegin(optional != null);
+
1427 if (fbeBegin == 0)
+
1428 return;
+
1429
+
1430 value.set(optional);
+
1431 setEnd(fbeBegin);
+
1432 }
+
1433}
+
1434)CODE";
+
1435
+
1436 std::string type_name = IsPackageType(type) ? type : (domain + package + "." + type);
+
1437
+
1438 // Prepare code template
+
1439 code = std::regex_replace(code, std::regex("_DOMAIN_"), domain);
+
1440 code = std::regex_replace(code, std::regex("_NAME_"), name);
+
1441 code = std::regex_replace(code, std::regex("_TYPE_"), type_name);
+
1442 code = std::regex_replace(code, std::regex("_MODEL_"), model);
+
1443 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
1444
+
1445 Write(code);
+
1446
+
1447 // Generate footer
+
1448 GenerateFooter();
+
1449
+
1450 // Store the file
+
1451 WriteEnd();
+
1452 Store(file);
+
1453}
+
1454
+
1455void GeneratorJava::GenerateFBEFieldModelArray(const std::string& domain, const std::string& package, const std::string& name, const std::string& type, const std::string& model, bool bytes)
+
1456{
+
1457 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "fbe";
+
1458
+
1459 // Create package path
+
1460 CppCommon::Directory::CreateTree(path);
+
1461
+
1462 // Generate the file
+
1463 CppCommon::Path file = path / ("FieldModelArray" + name + ".java");
+
1464 WriteBegin();
+
1465
+
1466 // Generate headers
+
1467 GenerateHeader(CppCommon::Path(_input).filename().string());
+
1468 GenerateImports(domain, package + ".fbe");
+
1469
+
1470 std::string code = R"CODE(
+
1471// Fast Binary Encoding _NAME_ array field model
+
1472public final class FieldModelArray_NAME_ extends _DOMAIN_fbe.FieldModel
+
1473{
+
1474 private final _MODEL_ _model;
+
1475 private final long _size;
+
1476
+
1477 public FieldModelArray_NAME_(_DOMAIN_fbe.Buffer buffer, long offset, long size)
+
1478 {
+
1479 super(buffer, offset);
+
1480 _model = new _MODEL_(buffer, offset);
+
1481 _size = size;
+
1482 }
+
1483
+
1484 // Get the field size
+
1485 @Override
+
1486 public long fbeSize() { return _size * _model.fbeSize(); }
+
1487 // Get the field extra size
+
1488 @Override
+
1489 public long fbeExtra() { return 0; }
+
1490
+
1491 // Get the array offset
+
1492 public long getOffset() { return 0; }
+
1493 // Get the array size
+
1494 public long getSize() { return _size; }
+
1495
+
1496 // Array index operator
+
1497 public _MODEL_ getItem(long index)
+
1498 {
+
1499 assert ((_buffer.getOffset() + fbeOffset() + fbeSize()) <= _buffer.getSize()) : "Model is broken!";
+
1500 assert (index < _size) : "Index is out of bounds!";
+
1501
+
1502 _model.fbeOffset(fbeOffset());
+
1503 _model.fbeShift(index * _model.fbeSize());
+
1504 return _model;
+
1505 }
+
1506
+
1507 // Check if the array is valid
+
1508 @Override
+
1509 public boolean verify()
+
1510 {
+
1511 if ((_buffer.getOffset() + fbeOffset() + fbeSize()) > _buffer.getSize())
+
1512 return false;
+
1513
+
1514 _model.fbeOffset(fbeOffset());
+
1515 for (long i = _size; i-- > 0;)
+
1516 {
+
1517 if (!_model.verify())
+
1518 return false;
+
1519 _model.fbeShift(_model.fbeSize());
+
1520 }
+
1521
+
1522 return true;
+
1523 }
+
1524
+
1525 // Get the array
+
1526 public _ARRAY_ get()
+
1527 {
+
1528 var values = _INIT_;
+
1529
+
1530 var fbeModel = getItem(0);
+
1531 for (long i = 0; i < _size; i++)
+
1532 {
+
1533 values[(int)i] = fbeModel.get();
+
1534 fbeModel.fbeShift(fbeModel.fbeSize());
+
1535 }
+
1536 return values;
+
1537 }
+
1538
+
1539 // Get the array
+
1540 public void get(_ARRAY_ values)
+
1541 {
+
1542 assert (values != null) : "Invalid values parameter!";
+
1543 if (values == null)
+
1544 throw new IllegalArgumentException("Invalid values parameter!");
+
1545
+
1546 var fbeModel = getItem(0);
+
1547 for (long i = 0; (i < values.length) && (i < _size); i++)
+
1548 {
+
1549 values[(int)i] = fbeModel.get();
+
1550 fbeModel.fbeShift(fbeModel.fbeSize());
+
1551 }
+
1552 }
+
1553
+
1554 // Get the array as java.util.ArrayList
+
1555 public void get(java.util.ArrayList<_TYPE_> values)
+
1556 {
+
1557 assert (values != null) : "Invalid values parameter!";
+
1558 if (values == null)
+
1559 throw new IllegalArgumentException("Invalid values parameter!");
+
1560
+
1561 values.clear();
+
1562 values.ensureCapacity((int)_size);
+
1563
+
1564 var fbeModel = getItem(0);
+
1565 for (long i = _size; i-- > 0;)
+
1566 {
+
1567 _TYPE_ value = fbeModel.get();
+
1568 values.add(value);
+
1569 fbeModel.fbeShift(fbeModel.fbeSize());
+
1570 }
+
1571 }
+
1572
+
1573 // Set the array
+
1574 public void set(_ARRAY_ values)
+
1575 {
+
1576 assert (values != null) : "Invalid values parameter!";
+
1577 if (values == null)
+
1578 throw new IllegalArgumentException("Invalid values parameter!");
+
1579
+
1580 assert ((_buffer.getOffset() + fbeOffset() + fbeSize()) <= _buffer.getSize()) : "Model is broken!";
+
1581 if ((_buffer.getOffset() + fbeOffset() + fbeSize()) > _buffer.getSize())
+
1582 return;
+
1583
+
1584 var fbeModel = getItem(0);
+
1585 for (long i = 0; (i < values.length) && (i < _size); i++)
+
1586 {
+
1587 fbeModel.set(values[(int)i]);
+
1588 fbeModel.fbeShift(fbeModel.fbeSize());
+
1589 }
+
1590 }
+
1591
+
1592 // Set the array as java.util.ArrayList
+
1593 public void set(java.util.ArrayList<_TYPE_> values)
+
1594 {
+
1595 assert (values != null) : "Invalid values parameter!";
+
1596 if (values == null)
+
1597 throw new IllegalArgumentException("Invalid values parameter!");
+
1598
+
1599 assert ((_buffer.getOffset() + fbeOffset() + fbeSize()) <= _buffer.getSize()) : "Model is broken!";
+
1600 if ((_buffer.getOffset() + fbeOffset() + fbeSize()) > _buffer.getSize())
+
1601 return;
+
1602
+
1603 var fbeModel = getItem(0);
+
1604 for (long i = 0; (i < values.size()) && (i < _size); i++)
+
1605 {
+
1606 fbeModel.set(values.get((int)i));
+
1607 fbeModel.fbeShift(fbeModel.fbeSize());
+
1608 }
+
1609 }
+
1610}
+
1611)CODE";
+
1612
+
1613 std::string type_name = IsPackageType(type) ? type : (domain + package + "." + type);
+
1614
+
1615 // Prepare code template
+
1616 code = std::regex_replace(code, std::regex("_DOMAIN_"), domain);
+
1617 code = std::regex_replace(code, std::regex("_NAME_"), name);
+
1618 code = std::regex_replace(code, std::regex("_TYPE_"), type_name);
+
1619 code = std::regex_replace(code, std::regex("_MODEL_"), model);
+
1620 code = std::regex_replace(code, std::regex("_ARRAY_"), (bytes ? "byte" : type_name) + "[]");
+
1621 code = std::regex_replace(code, std::regex("_INIT_"), ((type != "byte[]") ? ("new " + (bytes ? "byte" : type_name) + "[(int)_size]") : "new byte[(int)_size][]"));
+
1622 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
1623
+
1624 Write(code);
+
1625
+
1626 // Generate footer
+
1627 GenerateFooter();
+
1628
+
1629 // Store the file
+
1630 WriteEnd();
+
1631 Store(file);
+
1632}
+
1633
+
1634void GeneratorJava::GenerateFBEFieldModelVector(const std::string& domain, const std::string& package, const std::string& name, const std::string& type, const std::string& model)
+
1635{
+
1636 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "fbe";
+
1637
+
1638 // Create package path
+
1639 CppCommon::Directory::CreateTree(path);
+
1640
+
1641 // Generate the file
+
1642 CppCommon::Path file = path / ("FieldModelVector" + name + ".java");
+
1643 WriteBegin();
+
1644
+
1645 // Generate headers
+
1646 GenerateHeader(CppCommon::Path(_input).filename().string());
+
1647 GenerateImports(domain, package + ".fbe");
+
1648
+
1649 std::string code = R"CODE(
+
1650// Fast Binary Encoding _NAME_ vector field model
+
1651public final class FieldModelVector_NAME_ extends _DOMAIN_fbe.FieldModel
+
1652{
+
1653 private final _MODEL_ _model;
+
1654
+
1655 public FieldModelVector_NAME_(_DOMAIN_fbe.Buffer buffer, long offset)
+
1656 {
+
1657 super(buffer, offset);
+
1658 _model = new _MODEL_(buffer, offset);
+
1659 }
+
1660
+
1661 // Get the field size
+
1662 @Override
+
1663 public long fbeSize() { return 4; }
+
1664 // Get the field extra size
+
1665 @Override
+
1666 public long fbeExtra()
+
1667 {
+
1668 if ((_buffer.getOffset() + fbeOffset() + fbeSize()) > _buffer.getSize())
+
1669 return 0;
+
1670
+
1671 int fbeVectorOffset = readInt32(fbeOffset());
+
1672 if ((fbeVectorOffset == 0) || ((_buffer.getOffset() + fbeVectorOffset + 4) > _buffer.getSize()))
+
1673 return 0;
+
1674
+
1675 int fbeVectorSize = readInt32(fbeVectorOffset);
+
1676
+
1677 long fbeResult = 4;
+
1678 _model.fbeOffset(fbeVectorOffset + 4);
+
1679 for (int i = fbeVectorSize; i-- > 0;)
+
1680 {
+
1681 fbeResult += _model.fbeSize() + _model.fbeExtra();
+
1682 _model.fbeShift(_model.fbeSize());
+
1683 }
+
1684 return fbeResult;
+
1685 }
+
1686
+
1687 // Get the vector offset
+
1688 public long getOffset()
+
1689 {
+
1690 if ((_buffer.getOffset() + fbeOffset() + fbeSize()) > _buffer.getSize())
+
1691 return 0;
+
1692
+
1693 int fbeVectorOffset = readInt32(fbeOffset());
+
1694 return fbeVectorOffset;
+
1695 }
+
1696
+
1697 // Get the vector size
+
1698 public long getSize()
+
1699 {
+
1700 if ((_buffer.getOffset() + fbeOffset() + fbeSize()) > _buffer.getSize())
+
1701 return 0;
+
1702
+
1703 int fbeVectorOffset = readInt32(fbeOffset());
+
1704 if ((fbeVectorOffset == 0) || ((_buffer.getOffset() + fbeVectorOffset + 4) > _buffer.getSize()))
+
1705 return 0;
+
1706
+
1707 int fbeVectorSize = readInt32(fbeVectorOffset);
+
1708 return fbeVectorSize;
+
1709 }
+
1710
+
1711 // Vector index operator
+
1712 public _MODEL_ getItem(long index)
+
1713 {
+
1714 assert ((_buffer.getOffset() + fbeOffset() + fbeSize()) <= _buffer.getSize()) : "Model is broken!";
+
1715
+
1716 int fbeVectorOffset = readInt32(fbeOffset());
+
1717 assert ((fbeVectorOffset > 0) && ((_buffer.getOffset() + fbeVectorOffset + 4) <= _buffer.getSize())) : "Model is broken!";
+
1718
+
1719 int fbeVectorSize = readInt32(fbeVectorOffset);
+
1720 assert (index < fbeVectorSize) : "Index is out of bounds!";
+
1721
+
1722 _model.fbeOffset(fbeVectorOffset + 4);
+
1723 _model.fbeShift(index * _model.fbeSize());
+
1724 return _model;
+
1725 }
+
1726
+
1727 // Resize the vector and get its first model
+
1728 public _MODEL_ resize(long size)
+
1729 {
+
1730 int fbeVectorSize = (int)(size * _model.fbeSize());
+
1731 int fbeVectorOffset = (int)(_buffer.allocate(4 + fbeVectorSize) - _buffer.getOffset());
+
1732 assert ((fbeVectorOffset > 0) && ((_buffer.getOffset() + fbeVectorOffset + 4) <= _buffer.getSize())) : "Model is broken!";
+
1733
+
1734 write(fbeOffset(), fbeVectorOffset);
+
1735 write(fbeVectorOffset, (int)size);
+
1736 write(fbeVectorOffset + 4, (byte)0, fbeVectorSize);
+
1737
+
1738 _model.fbeOffset(fbeVectorOffset + 4);
+
1739 return _model;
+
1740 }
+
1741
+
1742 // Check if the vector is valid
+
1743 @Override
+
1744 public boolean verify()
+
1745 {
+
1746 if ((_buffer.getOffset() + fbeOffset() + fbeSize()) > _buffer.getSize())
+
1747 return true;
+
1748
+
1749 int fbeVectorOffset = readInt32(fbeOffset());
+
1750 if (fbeVectorOffset == 0)
+
1751 return true;
+
1752
+
1753 if ((_buffer.getOffset() + fbeVectorOffset + 4) > _buffer.getSize())
+
1754 return false;
+
1755
+
1756 int fbeVectorSize = readInt32(fbeVectorOffset);
+
1757
+
1758 _model.fbeOffset(fbeVectorOffset + 4);
+
1759 for (int i = fbeVectorSize; i-- > 0;)
+
1760 {
+
1761 if (!_model.verify())
+
1762 return false;
+
1763 _model.fbeShift(_model.fbeSize());
+
1764 }
+
1765
+
1766 return true;
+
1767 }
+
1768
+
1769 // Get the vector as java.util.ArrayList
+
1770 public void get(java.util.ArrayList<_TYPE_> values)
+
1771 {
+
1772 assert (values != null) : "Invalid values parameter!";
+
1773 if (values == null)
+
1774 throw new IllegalArgumentException("Invalid values parameter!");
+
1775
+
1776 values.clear();
+
1777
+
1778 long fbeVectorSize = getSize();
+
1779 if (fbeVectorSize == 0)
+
1780 return;
+
1781
+
1782 values.ensureCapacity((int)fbeVectorSize);
+
1783
+
1784 var fbeModel = getItem(0);
+
1785 for (long i = fbeVectorSize; i-- > 0;)
+
1786 {
+
1787 _TYPE_ value = fbeModel.get();
+
1788 values.add(value);
+
1789 fbeModel.fbeShift(fbeModel.fbeSize());
+
1790 }
+
1791 }
+
1792
+
1793 // Get the vector as java.util.LinkedList
+
1794 public void get(java.util.LinkedList<_TYPE_> values)
+
1795 {
+
1796 assert (values != null) : "Invalid values parameter!";
+
1797 if (values == null)
+
1798 throw new IllegalArgumentException("Invalid values parameter!");
+
1799
+
1800 values.clear();
+
1801
+
1802 long fbeVectorSize = getSize();
+
1803 if (fbeVectorSize == 0)
+
1804 return;
+
1805
+
1806 var fbeModel = getItem(0);
+
1807 for (long i = fbeVectorSize; i-- > 0;)
+
1808 {
+
1809 _TYPE_ value = fbeModel.get();
+
1810 values.add(value);
+
1811 fbeModel.fbeShift(fbeModel.fbeSize());
+
1812 }
+
1813 }
+
1814
+
1815 // Get the vector as java.util.HashSet
+
1816 public void get(java.util.HashSet<_TYPE_> values)
+
1817 {
+
1818 assert (values != null) : "Invalid values parameter!";
+
1819 if (values == null)
+
1820 throw new IllegalArgumentException("Invalid values parameter!");
+
1821
+
1822 values.clear();
+
1823
+
1824 long fbeVectorSize = getSize();
+
1825 if (fbeVectorSize == 0)
+
1826 return;
+
1827
+
1828 var fbeModel = getItem(0);
+
1829 for (long i = fbeVectorSize; i-- > 0;)
+
1830 {
+
1831 _TYPE_ value = fbeModel.get();
+
1832 values.add(value);
+
1833 fbeModel.fbeShift(fbeModel.fbeSize());
+
1834 }
+
1835 }
+
1836
+
1837 // Set the vector as java.util.ArrayList
+
1838 public void set(java.util.ArrayList<_TYPE_> values)
+
1839 {
+
1840 assert (values != null) : "Invalid values parameter!";
+
1841 if (values == null)
+
1842 throw new IllegalArgumentException("Invalid values parameter!");
+
1843
+
1844 assert ((_buffer.getOffset() + fbeOffset() + fbeSize()) <= _buffer.getSize()) : "Model is broken!";
+
1845 if ((_buffer.getOffset() + fbeOffset() + fbeSize()) > _buffer.getSize())
+
1846 return;
+
1847
+
1848 var fbeModel = resize(values.size());
+
1849 for (var value : values)
+
1850 {
+
1851 fbeModel.set(value);
+
1852 fbeModel.fbeShift(fbeModel.fbeSize());
+
1853 }
+
1854 }
+
1855
+
1856 // Set the vector as java.util.LinkedList
+
1857 public void set(java.util.LinkedList<_TYPE_> values)
+
1858 {
+
1859 assert (values != null) : "Invalid values parameter!";
+
1860 if (values == null)
+
1861 throw new IllegalArgumentException("Invalid values parameter!");
+
1862
+
1863 assert ((_buffer.getOffset() + fbeOffset() + fbeSize()) <= _buffer.getSize()) : "Model is broken!";
+
1864 if ((_buffer.getOffset() + fbeOffset() + fbeSize()) > _buffer.getSize())
+
1865 return;
+
1866
+
1867 var fbeModel = resize(values.size());
+
1868 for (var value : values)
+
1869 {
+
1870 fbeModel.set(value);
+
1871 fbeModel.fbeShift(fbeModel.fbeSize());
+
1872 }
+
1873 }
+
1874
+
1875 // Set the vector as java.util.HashSet
+
1876 public void set(java.util.HashSet<_TYPE_> values)
+
1877 {
+
1878 assert (values != null) : "Invalid values parameter!";
+
1879 if (values == null)
+
1880 throw new IllegalArgumentException("Invalid values parameter!");
+
1881
+
1882 assert ((_buffer.getOffset() + fbeOffset() + fbeSize()) <= _buffer.getSize()) : "Model is broken!";
+
1883 if ((_buffer.getOffset() + fbeOffset() + fbeSize()) > _buffer.getSize())
+
1884 return;
+
1885
+
1886 var fbeModel = resize(values.size());
+
1887 for (var value : values)
+
1888 {
+
1889 fbeModel.set(value);
+
1890 fbeModel.fbeShift(fbeModel.fbeSize());
+
1891 }
+
1892 }
+
1893}
+
1894)CODE";
+
1895
+
1896 std::string type_name = IsPackageType(type) ? type : (domain + package + "." + type);
+
1897
+
1898 // Prepare code template
+
1899 code = std::regex_replace(code, std::regex("_DOMAIN_"), domain);
+
1900 code = std::regex_replace(code, std::regex("_NAME_"), name);
+
1901 code = std::regex_replace(code, std::regex("_TYPE_"), type_name);
+
1902 code = std::regex_replace(code, std::regex("_MODEL_"), model);
+
1903 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
1904
+
1905 Write(code);
+
1906
+
1907 // Generate footer
+
1908 GenerateFooter();
+
1909
+
1910 // Store the file
+
1911 WriteEnd();
+
1912 Store(file);
+
1913}
+
1914
+
1915void GeneratorJava::GenerateFBEFieldModelMap(const std::string& domain, const std::string& package, const std::string& key_name, const std::string& key_type, const std::string& key_model, const std::string& value_name, const std::string& value_type, const std::string& value_model)
+
1916{
+
1917 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "fbe";
+
1918
+
1919 // Create package path
+
1920 CppCommon::Directory::CreateTree(path);
+
1921
+
1922 // Generate the file
+
1923 CppCommon::Path file = path / ("FieldModelMap" + key_name + value_name + ".java");
+
1924 WriteBegin();
+
1925
+
1926 // Generate headers
+
1927 GenerateHeader(CppCommon::Path(_input).filename().string());
+
1928 GenerateImports(domain, package + ".fbe");
+
1929
+
1930 std::string code = R"CODE(
+
1931// Fast Binary Encoding _KEY_NAME_->_VALUE_NAME_ map field model
+
1932public final class FieldModelMap_KEY_NAME__VALUE_NAME_ extends _DOMAIN_fbe.FieldModel
+
1933{
+
1934 private final _KEY_MODEL_ _modelKey;
+
1935 private final _VALUE_MODEL_ _modelValue;
+
1936
+
1937 public FieldModelMap_KEY_NAME__VALUE_NAME_(_DOMAIN_fbe.Buffer buffer, long offset)
+
1938 {
+
1939 super(buffer, offset);
+
1940 _modelKey = new _KEY_MODEL_(buffer, offset);
+
1941 _modelValue = new _VALUE_MODEL_(buffer, offset);
+
1942 }
+
1943
+
1944 // Get the field size
+
1945 @Override
+
1946 public long fbeSize() { return 4; }
+
1947 // Get the field extra size
+
1948 @Override
+
1949 public long fbeExtra()
+
1950 {
+
1951 if ((_buffer.getOffset() + fbeOffset() + fbeSize()) > _buffer.getSize())
+
1952 return 0;
+
1953
+
1954 int fbeMapOffset = readInt32(fbeOffset());
+
1955 if ((fbeMapOffset == 0) || ((_buffer.getOffset() + fbeMapOffset + 4) > _buffer.getSize()))
+
1956 return 0;
+
1957
+
1958 int fbeMapSize = readInt32(fbeMapOffset);
+
1959
+
1960 long fbeResult = 4;
+
1961 _modelKey.fbeOffset(fbeMapOffset + 4);
+
1962 _modelValue.fbeOffset(fbeMapOffset + 4 + _modelKey.fbeSize());
+
1963 for (int i = fbeMapSize; i-- > 0;)
+
1964 {
+
1965 fbeResult += _modelKey.fbeSize() + _modelKey.fbeExtra();
+
1966 _modelKey.fbeShift(_modelKey.fbeSize() + _modelValue.fbeSize());
+
1967
+
1968 fbeResult += _modelValue.fbeSize() + _modelValue.fbeExtra();
+
1969 _modelValue.fbeShift(_modelKey.fbeSize() + _modelValue.fbeSize());
+
1970 }
+
1971 return fbeResult;
+
1972 }
+
1973
+
1974 // Get the map offset
+
1975 public long getOffset()
+
1976 {
+
1977 if ((_buffer.getOffset() + fbeOffset() + fbeSize()) > _buffer.getSize())
+
1978 return 0;
+
1979
+
1980 int fbeMapOffset = readInt32(fbeOffset());
+
1981 return fbeMapOffset;
+
1982 }
+
1983
+
1984 // Get the map size
+
1985 public long getSize()
+
1986 {
+
1987 if ((_buffer.getOffset() + fbeOffset() + fbeSize()) > _buffer.getSize())
+
1988 return 0;
+
1989
+
1990 int fbeMapOffset = readInt32(fbeOffset());
+
1991 if ((fbeMapOffset == 0) || ((_buffer.getOffset() + fbeMapOffset + 4) > _buffer.getSize()))
+
1992 return 0;
+
1993
+
1994 int fbeMapSize = readInt32(fbeMapOffset);
+
1995 return fbeMapSize;
+
1996 }
+
1997
+
1998 // Map index operator
+
1999 public _DOMAIN_fbe.Pair<_KEY_MODEL_, _VALUE_MODEL_> getItem(long index)
+
2000 {
+
2001 assert ((_buffer.getOffset() + fbeOffset() + fbeSize()) <= _buffer.getSize()) : "Model is broken!";
+
2002
+
2003 int fbeMapOffset = readInt32(fbeOffset());
+
2004 assert ((fbeMapOffset > 0) && ((_buffer.getOffset() + fbeMapOffset + 4) <= _buffer.getSize())) : "Model is broken!";
+
2005
+
2006 int fbeMapSize = readInt32(fbeMapOffset);
+
2007 assert (index < fbeMapSize) : "Index is out of bounds!";
+
2008
+
2009 _modelKey.fbeOffset(fbeMapOffset + 4);
+
2010 _modelValue.fbeOffset(fbeMapOffset + 4 + _modelKey.fbeSize());
+
2011 _modelKey.fbeShift(index * (_modelKey.fbeSize() + _modelValue.fbeSize()));
+
2012 _modelValue.fbeShift(index * (_modelKey.fbeSize() + _modelValue.fbeSize()));
+
2013 return _DOMAIN_fbe.Pair.create(_modelKey, _modelValue);
+
2014 }
+
2015
+
2016 // Resize the map and get its first model
+
2017 public _DOMAIN_fbe.Pair<_KEY_MODEL_, _VALUE_MODEL_> resize(long size)
+
2018 {
+
2019 int fbeMapSize = (int)(size * (_modelKey.fbeSize() + _modelValue.fbeSize()));
+
2020 int fbeMapOffset = (int)(_buffer.allocate(4 + fbeMapSize) - _buffer.getOffset());
+
2021 assert ((fbeMapOffset > 0) && ((_buffer.getOffset() + fbeMapOffset + 4) <= _buffer.getSize())) : "Model is broken!";
+
2022
+
2023 write(fbeOffset(), fbeMapOffset);
+
2024 write(fbeMapOffset, (int)size);
+
2025 write(fbeMapOffset + 4, (byte)0, fbeMapSize);
+
2026
+
2027 _modelKey.fbeOffset(fbeMapOffset + 4);
+
2028 _modelValue.fbeOffset(fbeMapOffset + 4 + _modelKey.fbeSize());
+
2029 return _DOMAIN_fbe.Pair.create(_modelKey, _modelValue);
+
2030 }
+
2031
+
2032 // Check if the map is valid
+
2033 @Override
+
2034 public boolean verify()
+
2035 {
+
2036 if ((_buffer.getOffset() + fbeOffset() + fbeSize()) > _buffer.getSize())
+
2037 return true;
+
2038
+
2039 int fbeMapOffset = readInt32(fbeOffset());
+
2040 if (fbeMapOffset == 0)
+
2041 return true;
+
2042
+
2043 if ((_buffer.getOffset() + fbeMapOffset + 4) > _buffer.getSize())
+
2044 return false;
+
2045
+
2046 int fbeMapSize = readInt32(fbeMapOffset);
+
2047
+
2048 _modelKey.fbeOffset(fbeMapOffset + 4);
+
2049 _modelValue.fbeOffset(fbeMapOffset + 4 + _modelKey.fbeSize());
+
2050 for (int i = fbeMapSize; i-- > 0;)
+
2051 {
+
2052 if (!_modelKey.verify())
+
2053 return false;
+
2054 _modelKey.fbeShift(_modelKey.fbeSize() + _modelValue.fbeSize());
+
2055 if (!_modelValue.verify())
+
2056 return false;
+
2057 _modelValue.fbeShift(_modelKey.fbeSize() + _modelValue.fbeSize());
+
2058 }
+
2059
+
2060 return true;
+
2061 }
+
2062
+
2063 // Get the map as java.util.TreeMap
+
2064 public void get(java.util.TreeMap<_KEY_TYPE_, _VALUE_TYPE_> values)
+
2065 {
+
2066 assert (values != null) : "Invalid values parameter!";
+
2067 if (values == null)
+
2068 throw new IllegalArgumentException("Invalid values parameter!");
+
2069
+
2070 values.clear();
+
2071
+
2072 long fbeMapSize = getSize();
+
2073 if (fbeMapSize == 0)
+
2074 return;
+
2075
+
2076 var fbeModel = getItem(0);
+
2077 for (long i = fbeMapSize; i-- > 0;)
+
2078 {
+
2079 _KEY_TYPE_ key = fbeModel.getKey().get();
+
2080 _VALUE_TYPE_ value = fbeModel.getValue().get();
+
2081 values.put(key, value);
+
2082 fbeModel.getKey().fbeShift(fbeModel.getKey().fbeSize() + fbeModel.getValue().fbeSize());
+
2083 fbeModel.getValue().fbeShift(fbeModel.getKey().fbeSize() + fbeModel.getValue().fbeSize());
+
2084 }
+
2085 }
+
2086
+
2087 // Get the map as java.util.HashMap
+
2088 public void get(java.util.HashMap<_KEY_TYPE_, _VALUE_TYPE_> values)
+
2089 {
+
2090 assert (values != null) : "Invalid values parameter!";
+
2091 if (values == null)
+
2092 throw new IllegalArgumentException("Invalid values parameter!");
+
2093
+
2094 values.clear();
+
2095
+
2096 long fbeMapSize = getSize();
+
2097 if (fbeMapSize == 0)
+
2098 return;
+
2099
+
2100 var fbeModel = getItem(0);
+
2101 for (long i = fbeMapSize; i-- > 0;)
+
2102 {
+
2103 _KEY_TYPE_ key = fbeModel.getKey().get();
+
2104 _VALUE_TYPE_ value = fbeModel.getValue().get();
+
2105 values.put(key, value);
+
2106 fbeModel.getKey().fbeShift(fbeModel.getKey().fbeSize() + fbeModel.getValue().fbeSize());
+
2107 fbeModel.getValue().fbeShift(fbeModel.getKey().fbeSize() + fbeModel.getValue().fbeSize());
+
2108 }
+
2109 }
+
2110
+
2111 // Set the map as java.util.TreeMap
+
2112 public void set(java.util.TreeMap<_KEY_TYPE_, _VALUE_TYPE_> values)
+
2113 {
+
2114 assert (values != null) : "Invalid values parameter!";
+
2115 if (values == null)
+
2116 throw new IllegalArgumentException("Invalid values parameter!");
+
2117
+
2118 assert ((_buffer.getOffset() + fbeOffset() + fbeSize()) <= _buffer.getSize()) : "Model is broken!";
+
2119 if ((_buffer.getOffset() + fbeOffset() + fbeSize()) > _buffer.getSize())
+
2120 return;
+
2121
+
2122 var fbeModel = resize(values.size());
+
2123 for (var value : values.entrySet())
+
2124 {
+
2125 fbeModel.getKey().set(value.getKey());
+
2126 fbeModel.getKey().fbeShift(fbeModel.getKey().fbeSize() + fbeModel.getValue().fbeSize());
+
2127 fbeModel.getValue().set(value.getValue());
+
2128 fbeModel.getValue().fbeShift(fbeModel.getKey().fbeSize() + fbeModel.getValue().fbeSize());
+
2129 }
+
2130 }
+
2131
+
2132 // Set the map as java.util.HashMap
+
2133 public void set(java.util.HashMap<_KEY_TYPE_, _VALUE_TYPE_> values)
+
2134 {
+
2135 assert (values != null) : "Invalid values parameter!";
+
2136 if (values == null)
+
2137 throw new IllegalArgumentException("Invalid values parameter!");
+
2138
+
2139 assert ((_buffer.getOffset() + fbeOffset() + fbeSize()) <= _buffer.getSize()) : "Model is broken!";
+
2140 if ((_buffer.getOffset() + fbeOffset() + fbeSize()) > _buffer.getSize())
+
2141 return;
+
2142
+
2143 var fbeModel = resize(values.size());
+
2144 for (var value : values.entrySet())
+
2145 {
+
2146 fbeModel.getKey().set(value.getKey());
+
2147 fbeModel.getKey().fbeShift(fbeModel.getKey().fbeSize() + fbeModel.getValue().fbeSize());
+
2148 fbeModel.getValue().set(value.getValue());
+
2149 fbeModel.getValue().fbeShift(fbeModel.getKey().fbeSize() + fbeModel.getValue().fbeSize());
+
2150 }
+
2151 }
+
2152}
+
2153)CODE";
+
2154
+
2155 std::string key_type_name = IsPackageType(key_type) ? key_type : (domain + package + "." + key_type);
+
2156 std::string value_type_name = IsPackageType(value_type) ? value_type : (domain + package + "." + value_type);
+
2157
+
2158 // Prepare code template
+
2159 code = std::regex_replace(code, std::regex("_DOMAIN_"), domain);
+
2160 code = std::regex_replace(code, std::regex("_KEY_NAME_"), key_name);
+
2161 code = std::regex_replace(code, std::regex("_KEY_TYPE_"), key_type_name);
+
2162 code = std::regex_replace(code, std::regex("_KEY_MODEL_"), key_model);
+
2163 code = std::regex_replace(code, std::regex("_VALUE_NAME_"), value_name);
+
2164 code = std::regex_replace(code, std::regex("_VALUE_TYPE_"), value_type_name);
+
2165 code = std::regex_replace(code, std::regex("_VALUE_MODEL_"), value_model);
+
2166 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2167
+
2168 Write(code);
+
2169
+
2170 // Generate footer
+
2171 GenerateFooter();
+
2172
+
2173 // Store the file
+
2174 WriteEnd();
+
2175 Store(file);
+
2176}
+
2177
+
2178void GeneratorJava::GenerateFBEFieldModelEnumFlags(const std::string& domain, const std::string& package, const std::string& name, const std::string& type)
+
2179{
+
2180 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "fbe";
+
2181
+
2182 // Create package path
+
2183 CppCommon::Directory::CreateTree(path);
+
2184
+
2185 // Generate the file
+
2186 CppCommon::Path file = path / ("FieldModel" + name + ".java");
+
2187 WriteBegin();
+
2188
+
2189 // Generate headers
+
2190 GenerateHeader(CppCommon::Path(_input).filename().string());
+
2191 GenerateImports(domain, package + ".fbe");
+
2192
+
2193 std::string code = R"CODE(
+
2194// Fast Binary Encoding _NAME_ field model
+
2195public final class FieldModel_NAME_ extends _DOMAIN_fbe.FieldModel
+
2196{
+
2197 public FieldModel_NAME_(_DOMAIN_fbe.Buffer buffer, long offset) { super(buffer, offset); }
+
2198
+
2199 // Get the field size
+
2200 @Override
+
2201 public long fbeSize() { return _SIZE_; }
+
2202
+
2203 // Get the value
+
2204 public _DOMAIN__PACKAGE_._NAME_ get() { return get(new _DOMAIN__PACKAGE_._NAME_()); }
+
2205 public _DOMAIN__PACKAGE_._NAME_ get(_DOMAIN__PACKAGE_._NAME_ defaults)
+
2206 {
+
2207 if ((_buffer.getOffset() + fbeOffset() + fbeSize()) > _buffer.getSize())
+
2208 return defaults;
+
2209
+
2210 return new _DOMAIN__PACKAGE_._NAME_(_READ_(fbeOffset()));
+
2211 }
+
2212
+
2213 // Set the value
+
2214 public void set(_DOMAIN__PACKAGE_._NAME_ value)
+
2215 {
+
2216 assert ((_buffer.getOffset() + fbeOffset() + fbeSize()) <= _buffer.getSize()) : "Model is broken!";
+
2217 if ((_buffer.getOffset() + fbeOffset() + fbeSize()) > _buffer.getSize())
+
2218 return;
+
2219
+
2220 write(fbeOffset(), value.getRaw());
+
2221 }
+
2222}
+
2223)CODE";
+
2224
+
2225 // Prepare code template
+
2226 code = std::regex_replace(code, std::regex("_DOMAIN_"), domain);
+
2227 code = std::regex_replace(code, std::regex("_PACKAGE_"), package);
+
2228 code = std::regex_replace(code, std::regex("_NAME_"), name);
+
2229 code = std::regex_replace(code, std::regex("_SIZE_"), ConvertEnumSize(type));
+
2230 code = std::regex_replace(code, std::regex("_READ_"), ConvertEnumRead(type));
+
2231 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2232
+
2233 Write(code);
+
2234
+
2235 // Generate footer
+
2236 GenerateFooter();
+
2237
+
2238 // Store the file
+
2239 WriteEnd();
+
2240 Store(file);
+
2241}
+
2242
+
2243void GeneratorJava::GenerateFBESize(const std::string& domain, const std::string& package)
+
2244{
+
2245 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
2246
+
2247 // Generate the file
+
2248 CppCommon::Path file = path / "Size.java";
+
2249 WriteBegin();
+
2250
+
2251 // Generate headers
+
2252 GenerateHeader("FBE");
+
2253 GenerateImports(domain, package);
+
2254
+
2255 std::string code = R"CODE(
+
2256// Fast Binary Encoding size
+
2257public class Size
+
2258{
+
2259 public long value;
+
2260
+
2261 // Initialize a new size
+
2262 public Size() { value = 0; }
+
2263 public Size(long size) { value = size; }
+
2264}
+
2265)CODE";
+
2266
+
2267 // Prepare code template
+
2268 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2269
+
2270 Write(code);
+
2271
+
2272 // Generate footer
+
2273 GenerateFooter();
+
2274
+
2275 // Store the file
+
2276 WriteEnd();
+
2277 Store(file);
+
2278}
+
2279
+
2280void GeneratorJava::GenerateFBEFinalModel(const std::string& domain, const std::string& package)
+
2281{
+
2282 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
2283
+
2284 // Generate the file
+
2285 CppCommon::Path file = path / "FinalModel.java";
+
2286 WriteBegin();
+
2287
+
2288 // Generate headers
+
2289 GenerateHeader("FBE");
+
2290 GenerateImports(domain, package);
+
2291
+
2292 std::string code = R"CODE(
+
2293// Fast Binary Encoding base final model
+
2294public abstract class FinalModel
+
2295{
+
2296 protected Buffer _buffer;
+
2297 protected long _offset;
+
2298
+
2299 // Get the final offset
+
2300 public long fbeOffset() { return _offset; }
+
2301 // Set the final offset
+
2302 public void fbeOffset(long value) { _offset = value; }
+
2303
+
2304 // Get the final size
+
2305 public long fbeSize() { return 0; }
+
2306 // Get the final extra size
+
2307 public long fbeExtra() { return 0; }
+
2308
+
2309 // Shift the current final offset
+
2310 public void fbeShift(long size) { _offset += size; }
+
2311 // Unshift the current final offset
+
2312 public void fbeUnshift(long size) { _offset -= size; }
+
2313
+
2314 // Initialize a new final model
+
2315 protected FinalModel(Buffer buffer, long offset)
+
2316 {
+
2317 _buffer = buffer;
+
2318 _offset = offset;
+
2319 }
+
2320
+
2321 // Check if the value is valid
+
2322 public abstract long verify();
+
2323
+
2324 // Buffer I/O methods
+
2325 protected boolean readBoolean(long offset) { return Buffer.readBoolean(_buffer.getData(), _buffer.getOffset() + offset); }
+
2326 protected byte readByte(long offset) { return Buffer.readByte(_buffer.getData(), _buffer.getOffset() + offset); }
+
2327 protected char readChar(long offset) { return Buffer.readChar(_buffer.getData(), _buffer.getOffset() + offset); }
+
2328 protected char readWChar(long offset) { return Buffer.readWChar(_buffer.getData(), _buffer.getOffset() + offset); }
+
2329 protected byte readInt8(long offset) { return Buffer.readInt8(_buffer.getData(), _buffer.getOffset() + offset); }
+
2330 protected short readInt16(long offset) { return Buffer.readInt16(_buffer.getData(), _buffer.getOffset() + offset); }
+
2331 protected int readInt32(long offset) { return Buffer.readInt32(_buffer.getData(), _buffer.getOffset() + offset); }
+
2332 protected long readInt64(long offset) { return Buffer.readInt64(_buffer.getData(), _buffer.getOffset() + offset); }
+
2333 protected float readFloat(long offset) { return Buffer.readFloat(_buffer.getData(), _buffer.getOffset() + offset); }
+
2334 protected double readDouble(long offset) { return Buffer.readDouble(_buffer.getData(), _buffer.getOffset() + offset); }
+
2335 protected byte[] readBytes(long offset, long size) { return Buffer.readBytes(_buffer.getData(), _buffer.getOffset() + offset, size); }
+
2336 protected String readString(long offset, long size) { return Buffer.readString(_buffer.getData(), _buffer.getOffset() + offset, size); }
+
2337 protected java.util.UUID readUUID(long offset) { return Buffer.readUUID(_buffer.getData(), _buffer.getOffset() + offset); }
+
2338 protected void write(long offset, boolean value) { Buffer.write(_buffer.getData(), _buffer.getOffset() + offset, value); }
+
2339 protected void write(long offset, byte value) { Buffer.write(_buffer.getData(), _buffer.getOffset() + offset, value); }
+
2340 protected void write(long offset, short value) { Buffer.write(_buffer.getData(), _buffer.getOffset() + offset, value); }
+
2341 protected void write(long offset, int value) { Buffer.write(_buffer.getData(), _buffer.getOffset() + offset, value); }
+
2342 protected void write(long offset, long value) { Buffer.write(_buffer.getData(), _buffer.getOffset() + offset, value); }
+
2343 protected void write(long offset, float value) { Buffer.write(_buffer.getData(), _buffer.getOffset() + offset, value); }
+
2344 protected void write(long offset, double value) { Buffer.write(_buffer.getData(), _buffer.getOffset() + offset, value); }
+
2345 protected void write(long offset, byte[] value) { Buffer.write(_buffer.getData(), _buffer.getOffset() + offset, value); }
+
2346 protected void write(long offset, byte[] value, long valueOffset, long valueSize) { Buffer.write(_buffer.getData(), _buffer.getOffset() + offset, value, valueOffset, valueSize); }
+
2347 protected void write(long offset, byte value, long valueCount) { Buffer.write(_buffer.getData(), _buffer.getOffset() + offset, value, valueCount); }
+
2348 protected void write(long offset, java.util.UUID value) { Buffer.write(_buffer.getData(), _buffer.getOffset() + offset, value); }
+
2349}
+
2350)CODE";
+
2351
+
2352 // Prepare code template
+
2353 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2354
+
2355 Write(code);
+
2356
+
2357 // Generate footer
+
2358 GenerateFooter();
+
2359
+
2360 // Store the file
+
2361 WriteEnd();
+
2362 Store(file);
+
2363}
+
2364
+
2365void GeneratorJava::GenerateFBEFinalModel(const std::string& domain, const std::string& package, const std::string& name, const std::string& type, const std::string& base, const std::string& size, const std::string& defaults)
+
2366{
+
2367 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
2368
+
2369 // Generate the file
+
2370 CppCommon::Path file = path / ("FinalModel" + name + ".java");
+
2371 WriteBegin();
+
2372
+
2373 // Generate headers
+
2374 GenerateHeader("FBE");
+
2375 GenerateImports(domain, package);
+
2376
+
2377 std::string code = R"CODE(
+
2378// Fast Binary Encoding _TYPE_ final model
+
2379public final class FinalModel_NAME_ extends FinalModel
+
2380{
+
2381 public FinalModel_NAME_(Buffer buffer, long offset) { super(buffer, offset); }
+
2382
+
2383 // Get the allocation size
+
2384 public long fbeAllocationSize(_TYPE_ value) { return fbeSize(); }
+
2385
+
2386 // Get the final size
+
2387 @Override
+
2388 public long fbeSize() { return _SIZE_; }
+
2389
+
2390 // Check if the value is valid
+
2391 @Override
+
2392 public long verify()
+
2393 {
+
2394 if ((_buffer.getOffset() + fbeOffset() + fbeSize()) > _buffer.getSize())
+
2395 return Long.MAX_VALUE;
+
2396
+
2397 return fbeSize();
+
2398 }
+
2399
+
2400 // Get the value
+
2401 public _TYPE_ get(Size size)
+
2402 {
+
2403 if ((_buffer.getOffset() + fbeOffset() + fbeSize()) > _buffer.getSize())
+
2404 return _DEFAULTS_;
+
2405
+
2406 size.value = fbeSize();
+
2407 return read_NAME_(fbeOffset());
+
2408 }
+
2409
+
2410 // Set the value
+
2411 public long set(_TYPE_ value)
+
2412 {
+
2413 assert ((_buffer.getOffset() + fbeOffset() + fbeSize()) <= _buffer.getSize()) : "Model is broken!";
+
2414 if ((_buffer.getOffset() + fbeOffset() + fbeSize()) > _buffer.getSize())
+
2415 return 0;
+
2416
+
2417 write(fbeOffset(), _BASE_value);
+
2418 return fbeSize();
+
2419 }
+
2420}
+
2421)CODE";
+
2422
+
2423 // Prepare code template
+
2424 code = std::regex_replace(code, std::regex("_NAME_"), name);
+
2425 code = std::regex_replace(code, std::regex("_TYPE_"), type);
+
2426 code = std::regex_replace(code, std::regex("_BASE_"), base);
+
2427 code = std::regex_replace(code, std::regex("_SIZE_"), size);
+
2428 code = std::regex_replace(code, std::regex("_DEFAULTS_"), defaults);
+
2429 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2430
+
2431 Write(code);
+
2432
+
2433 // Generate footer
+
2434 GenerateFooter();
+
2435
+
2436 // Store the file
+
2437 WriteEnd();
+
2438 Store(file);
+
2439}
+
2440
+
2441void GeneratorJava::GenerateFBEFinalModelDecimal(const std::string& domain, const std::string& package)
+
2442{
+
2443 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
2444
+
2445 // Generate the file
+
2446 CppCommon::Path file = path / "FinalModelDecimal.java";
+
2447 WriteBegin();
+
2448
+
2449 // Generate headers
+
2450 GenerateHeader("FBE");
+
2451 GenerateImports(domain, package);
+
2452
+
2453 std::string code = R"CODE(
+
2454// Fast Binary Encoding decimal final model
+
2455public final class FinalModelDecimal extends FinalModel
+
2456{
+
2457 public FinalModelDecimal(Buffer buffer, long offset) { super(buffer, offset); }
+
2458
+
2459 // Get the allocation size
+
2460 public long fbeAllocationSize(java.math.BigDecimal value) { return fbeSize(); }
+
2461
+
2462 // Get the final size
+
2463 @Override
+
2464 public long fbeSize() { return 16; }
+
2465
+
2466 // Check if the decimal value is valid
+
2467 @Override
+
2468 public long verify()
+
2469 {
+
2470 if ((_buffer.getOffset() + fbeOffset() + fbeSize()) > _buffer.getSize())
+
2471 return Long.MAX_VALUE;
+
2472
+
2473 return fbeSize();
+
2474 }
+
2475
+
2476 // Get the decimal value
+
2477 public java.math.BigDecimal get(Size size)
+
2478 {
+
2479 if ((_buffer.getOffset() + fbeOffset() + fbeSize()) > _buffer.getSize())
+
2480 return java.math.BigDecimal.valueOf(0L);
+
2481
+
2482 byte[] magnitude = readBytes(fbeOffset(), 12);
+
2483 int scale = readByte(fbeOffset() + 14);
+
2484 int signum = (readByte(fbeOffset() + 15) < 0) ? -1 : 1;
+
2485
+
2486 // Reverse magnitude
+
2487 for(int i = 0; i < magnitude.length / 2; i++)
+
2488 {
+
2489 byte temp = magnitude[i];
+
2490 magnitude[i] = magnitude[magnitude.length - i - 1];
+
2491 magnitude[magnitude.length - i - 1] = temp;
+
2492 }
+
2493
+
2494 var unscaled = new java.math.BigInteger(signum, magnitude);
+
2495
+
2496 size.value = fbeSize();
+
2497 return new java.math.BigDecimal(unscaled, scale);
+
2498 }
+
2499
+
2500 // Set the decimal value
+
2501 public long set(java.math.BigDecimal value)
+
2502 {
+
2503 assert ((_buffer.getOffset() + fbeOffset() + fbeSize()) <= _buffer.getSize()) : "Model is broken!";
+
2504 if ((_buffer.getOffset() + fbeOffset() + fbeSize()) > _buffer.getSize())
+
2505 return 0;
+
2506
+
2507 // Get unscaled absolute value
+
2508 java.math.BigInteger unscaled = value.abs().unscaledValue();
+
2509 int bitLength = unscaled.bitLength();
+
2510 if ((bitLength < 0) || (bitLength > 96))
+
2511 {
+
2512 // Value too big for .NET Decimal (bit length is limited to [0, 96])
+
2513 write(fbeOffset(), (byte)0, fbeSize());
+
2514 return fbeSize();
+
2515 }
+
2516
+
2517 // Get byte array
+
2518 byte[] unscaledBytes = unscaled.toByteArray();
+
2519
+
2520 // Get scale
+
2521 int scale = value.scale();
+
2522 if ((scale < 0) || (scale > 28))
+
2523 {
+
2524 // Value scale exceeds .NET Decimal limit of [0, 28]
+
2525 write(fbeOffset(), (byte)0, fbeSize());
+
2526 return fbeSize();
+
2527 }
+
2528
+
2529 // Write unscaled value to bytes 0-11
+
2530 int index = 0;
+
2531 for (int i = unscaledBytes.length - 1; (i >= 0) && (index < 12); i--, index++)
+
2532 write(fbeOffset() + index, unscaledBytes[i]);
+
2533
+
2534 // Fill remaining bytes with zeros
+
2535 for (; index < 14; index++)
+
2536 write(fbeOffset() + index, (byte)0);
+
2537
+
2538 // Write scale at byte 14
+
2539 write(fbeOffset() + 14, (byte)scale);
+
2540
+
2541 // Write signum at byte 15
+
2542 write(fbeOffset() + 15, (byte)((value.signum() < 0) ? -128 : 0));
+
2543 return fbeSize();
+
2544 }
+
2545}
+
2546)CODE";
+
2547
+
2548 // Prepare code template
+
2549 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2550
+
2551 Write(code);
+
2552
+
2553 // Generate footer
+
2554 GenerateFooter();
+
2555
+
2556 // Store the file
+
2557 WriteEnd();
+
2558 Store(file);
+
2559}
+
2560
+
2561void GeneratorJava::GenerateFBEFinalModelDate(const std::string& domain, const std::string& package)
+
2562{
+
2563 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
2564
+
2565 // Generate the file
+
2566 CppCommon::Path file = path / "FinalModelDate.java";
+
2567 WriteBegin();
+
2568
+
2569 // Generate headers
+
2570 GenerateHeader("FBE");
+
2571 GenerateImports(domain, package);
+
2572
+
2573 std::string code = R"CODE(
+
2574// Fast Binary Encoding date final model
+
2575public final class FinalModelDate extends FinalModel
+
2576{
+
2577 public FinalModelDate(Buffer buffer, long offset) { super(buffer, offset); }
+
2578
+
2579 // Get the allocation size
+
2580 public long fbeAllocationSize(java.util.Date value) { return fbeSize(); }
+
2581
+
2582 // Get the final size
+
2583 @Override
+
2584 public long fbeSize() { return 8; }
+
2585
+
2586 // Check if the date value is valid
+
2587 @Override
+
2588 public long verify()
+
2589 {
+
2590 if ((_buffer.getOffset() + fbeOffset() + fbeSize()) > _buffer.getSize())
+
2591 return Long.MAX_VALUE;
+
2592
+
2593 return fbeSize();
+
2594 }
+
2595
+
2596 // Get the date value
+
2597 public java.util.Date get(Size size)
+
2598 {
+
2599 if ((_buffer.getOffset() + fbeOffset() + fbeSize()) > _buffer.getSize())
+
2600 return new java.util.Date(0);
+
2601
+
2602 size.value = fbeSize();
+
2603 long nanoseconds = readInt64(fbeOffset());
+
2604 return new java.util.Date(nanoseconds / 1000000);
+
2605 }
+
2606
+
2607 // Set the date value
+
2608 public long set(java.util.Date value)
+
2609 {
+
2610 assert ((_buffer.getOffset() + fbeOffset() + fbeSize()) <= _buffer.getSize()) : "Model is broken!";
+
2611 if ((_buffer.getOffset() + fbeOffset() + fbeSize()) > _buffer.getSize())
+
2612 return 0;
+
2613
+
2614 long nanoseconds = value.getTime() * 1000;
+
2615 write(fbeOffset(), nanoseconds);
+
2616 return fbeSize();
+
2617 }
+
2618}
+
2619)CODE";
+
2620
+
2621 // Prepare code template
+
2622 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2623
+
2624 Write(code);
+
2625
+
2626 // Generate footer
+
2627 GenerateFooter();
+
2628
+
2629 // Store the file
+
2630 WriteEnd();
+
2631 Store(file);
+
2632}
+
2633
+
2634void GeneratorJava::GenerateFBEFinalModelTimestamp(const std::string& domain, const std::string& package)
+
2635{
+
2636 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
2637
+
2638 // Generate the file
+
2639 CppCommon::Path file = path / "FinalModelTimestamp.java";
+
2640 WriteBegin();
+
2641
+
2642 // Generate headers
+
2643 GenerateHeader("FBE");
+
2644 GenerateImports(domain, package);
+
2645
+
2646 std::string code = R"CODE(
+
2647// Fast Binary Encoding timestamp final model
+
2648public final class FinalModelTimestamp extends FinalModel
+
2649{
+
2650 public FinalModelTimestamp(Buffer buffer, long offset) { super(buffer, offset); }
+
2651
+
2652 // Get the allocation size
+
2653 public long fbeAllocationSize(java.time.Instant value) { return fbeSize(); }
+
2654
+
2655 // Get the final size
+
2656 @Override
+
2657 public long fbeSize() { return 8; }
+
2658
+
2659 // Check if the timestamp value is valid
+
2660 @Override
+
2661 public long verify()
+
2662 {
+
2663 if ((_buffer.getOffset() + fbeOffset() + fbeSize()) > _buffer.getSize())
+
2664 return Long.MAX_VALUE;
+
2665
+
2666 return fbeSize();
+
2667 }
+
2668
+
2669 // Get the timestamp value
+
2670 public java.time.Instant get(Size size)
+
2671 {
+
2672 if ((_buffer.getOffset() + fbeOffset() + fbeSize()) > _buffer.getSize())
+
2673 return java.time.Instant.EPOCH;
+
2674
+
2675 size.value = fbeSize();
+
2676 long nanoseconds = readInt64(fbeOffset());
+
2677 return java.time.Instant.ofEpochSecond(nanoseconds / 1000000000, nanoseconds % 1000000000);
+
2678 }
+
2679
+
2680 // Set the timestamp value
+
2681 public long set(java.time.Instant value)
+
2682 {
+
2683 assert ((_buffer.getOffset() + fbeOffset() + fbeSize()) <= _buffer.getSize()) : "Model is broken!";
+
2684 if ((_buffer.getOffset() + fbeOffset() + fbeSize()) > _buffer.getSize())
+
2685 return 0;
+
2686
+
2687 long nanoseconds = value.getEpochSecond() * 1000000000 + value.getNano();
+
2688 write(fbeOffset(), nanoseconds);
+
2689 return fbeSize();
+
2690 }
+
2691}
+
2692)CODE";
+
2693
+
2694 // Prepare code template
+
2695 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2696
+
2697 Write(code);
+
2698
+
2699 // Generate footer
+
2700 GenerateFooter();
+
2701
+
2702 // Store the file
+
2703 WriteEnd();
+
2704 Store(file);
+
2705}
+
2706
+
2707void GeneratorJava::GenerateFBEFinalModelBytes(const std::string& domain, const std::string& package)
+
2708{
+
2709 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
2710
+
2711 // Generate the file
+
2712 CppCommon::Path file = path / "FinalModelBytes.java";
+
2713 WriteBegin();
+
2714
+
2715 // Generate headers
+
2716 GenerateHeader("FBE");
+
2717 GenerateImports(domain, package);
+
2718
+
2719 std::string code = R"CODE(
+
2720// Fast Binary Encoding bytes final model
+
2721public final class FinalModelBytes extends FinalModel
+
2722{
+
2723 public FinalModelBytes(Buffer buffer, long offset) { super(buffer, offset); }
+
2724
+
2725 // Get the allocation size
+
2726 public long fbeAllocationSize(java.nio.ByteBuffer value) { return 4 + value.array().length; }
+
2727
+
2728 // Check if the bytes value is valid
+
2729 @Override
+
2730 public long verify()
+
2731 {
+
2732 if ((_buffer.getOffset() + fbeOffset() + 4) > _buffer.getSize())
+
2733 return Long.MAX_VALUE;
+
2734
+
2735 int fbeBytesSize = readInt32(fbeOffset());
+
2736 if ((_buffer.getOffset() + fbeOffset() + 4 + fbeBytesSize) > _buffer.getSize())
+
2737 return Long.MAX_VALUE;
+
2738
+
2739 return 4 + fbeBytesSize;
+
2740 }
+
2741
+
2742 // Get the bytes value
+
2743 public java.nio.ByteBuffer get(Size size)
+
2744 {
+
2745 if ((_buffer.getOffset() + fbeOffset() + 4) > _buffer.getSize())
+
2746 {
+
2747 size.value = 0;
+
2748 return java.nio.ByteBuffer.allocate(0);
+
2749 }
+
2750
+
2751 int fbeBytesSize = readInt32(fbeOffset());
+
2752 assert ((_buffer.getOffset() + fbeOffset() + 4 + fbeBytesSize) <= _buffer.getSize()) : "Model is broken!";
+
2753 if ((_buffer.getOffset() + fbeOffset() + 4 + fbeBytesSize) > _buffer.getSize())
+
2754 {
+
2755 size.value = 4;
+
2756 return java.nio.ByteBuffer.allocate(0);
+
2757 }
+
2758
+
2759 size.value = 4 + fbeBytesSize;
+
2760 return java.nio.ByteBuffer.wrap(readBytes(fbeOffset() + 4, fbeBytesSize));
+
2761 }
+
2762
+
2763 // Set the bytes value
+
2764 public long set(java.nio.ByteBuffer value)
+
2765 {
+
2766 assert (value != null) : "Invalid bytes value!";
+
2767 if (value == null)
+
2768 throw new IllegalArgumentException("Invalid bytes value!");
+
2769
+
2770 assert ((_buffer.getOffset() + fbeOffset() + 4) <= _buffer.getSize()) : "Model is broken!";
+
2771 if ((_buffer.getOffset() + fbeOffset() + 4) > _buffer.getSize())
+
2772 return 0;
+
2773
+
2774 int fbeBytesSize = value.array().length;
+
2775 assert ((_buffer.getOffset() + fbeOffset() + 4 + fbeBytesSize) <= _buffer.getSize()) : "Model is broken!";
+
2776 if ((_buffer.getOffset() + fbeOffset() + 4 + fbeBytesSize) > _buffer.getSize())
+
2777 return 4;
+
2778
+
2779 write(fbeOffset(), fbeBytesSize);
+
2780 write(fbeOffset() + 4, value.array());
+
2781 return 4 + fbeBytesSize;
+
2782 }
+
2783}
+
2784)CODE";
+
2785
+
2786 // Prepare code template
+
2787 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2788
+
2789 Write(code);
+
2790
+
2791 // Generate footer
+
2792 GenerateFooter();
+
2793
+
2794 // Store the file
+
2795 WriteEnd();
+
2796 Store(file);
+
2797}
+
2798
+
2799void GeneratorJava::GenerateFBEFinalModelString(const std::string& domain, const std::string& package)
+
2800{
+
2801 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
2802
+
2803 // Generate the file
+
2804 CppCommon::Path file = path / "FinalModelString.java";
+
2805 WriteBegin();
+
2806
+
2807 // Generate headers
+
2808 GenerateHeader("FBE");
+
2809 GenerateImports(domain, package);
+
2810
+
2811 std::string code = R"CODE(
+
2812// Fast Binary Encoding string final model
+
2813public final class FinalModelString extends FinalModel
+
2814{
+
2815 public FinalModelString(Buffer buffer, long offset) { super(buffer, offset); }
+
2816
+
2817 // Get the allocation size
+
2818 public long fbeAllocationSize(String value) { return 4 + 3 * (value.length() + 1); }
+
2819
+
2820 // Check if the string value is valid
+
2821 @Override
+
2822 public long verify()
+
2823 {
+
2824 if ((_buffer.getOffset() + fbeOffset() + 4) > _buffer.getSize())
+
2825 return Long.MAX_VALUE;
+
2826
+
2827 int fbeStringSize = readInt32(fbeOffset());
+
2828 if ((_buffer.getOffset() + fbeOffset() + 4 + fbeStringSize) > _buffer.getSize())
+
2829 return Long.MAX_VALUE;
+
2830
+
2831 return 4 + fbeStringSize;
+
2832 }
+
2833
+
2834 // Get the string value
+
2835 public String get(Size size)
+
2836 {
+
2837 if ((_buffer.getOffset() + fbeOffset() + 4) > _buffer.getSize())
+
2838 {
+
2839 size.value = 0;
+
2840 return "";
+
2841 }
+
2842
+
2843 int fbeStringSize = readInt32(fbeOffset());
+
2844 assert ((_buffer.getOffset() + fbeOffset() + 4 + fbeStringSize) <= _buffer.getSize()) : "Model is broken!";
+
2845 if ((_buffer.getOffset() + fbeOffset() + 4 + fbeStringSize) > _buffer.getSize())
+
2846 {
+
2847 size.value = 4;
+
2848 return "";
+
2849 }
+
2850
+
2851 size.value = 4 + fbeStringSize;
+
2852 return readString(fbeOffset() + 4, fbeStringSize);
+
2853 }
+
2854
+
2855 // Set the string value
+
2856 public long set(String value)
+
2857 {
+
2858 assert (value != null) : "Invalid string value!";
+
2859 if (value == null)
+
2860 throw new IllegalArgumentException("Invalid string value!");
+
2861
+
2862 assert ((_buffer.getOffset() + fbeOffset() + 4) <= _buffer.getSize()) : "Model is broken!";
+
2863 if ((_buffer.getOffset() + fbeOffset() + 4) > _buffer.getSize())
+
2864 return 0;
+
2865
+
2866 byte[] bytes = value.getBytes(java.nio.charset.StandardCharsets.UTF_8);
+
2867
+
2868 int fbeStringSize = bytes.length;
+
2869 assert ((_buffer.getOffset() + fbeOffset() + 4 + fbeStringSize) <= _buffer.getSize()) : "Model is broken!";
+
2870 if ((_buffer.getOffset() + fbeOffset() + 4 + fbeStringSize) > _buffer.getSize())
+
2871 return 4;
+
2872
+
2873 write(fbeOffset(), fbeStringSize);
+
2874 write(fbeOffset() + 4, bytes);
+
2875 return 4 + fbeStringSize;
+
2876 }
+
2877}
+
2878)CODE";
+
2879
+
2880 // Prepare code template
+
2881 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2882
+
2883 Write(code);
+
2884
+
2885 // Generate footer
+
2886 GenerateFooter();
+
2887
+
2888 // Store the file
+
2889 WriteEnd();
+
2890 Store(file);
+
2891}
+
2892
+
2893void GeneratorJava::GenerateFBEFinalModelOptional(const std::string& domain, const std::string& package, const std::string& name, const std::string& type, const std::string& model)
+
2894{
+
2895 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "fbe";
+
2896
+
2897 // Create package path
+
2898 CppCommon::Directory::CreateTree(path);
+
2899
+
2900 // Generate the file
+
2901 CppCommon::Path file = path / ("FinalModelOptional" + name + ".java");
+
2902 WriteBegin();
+
2903
+
2904 // Generate headers
+
2905 GenerateHeader(CppCommon::Path(_input).filename().string());
+
2906 GenerateImports(domain, package + ".fbe");
+
2907
+
2908 std::string code = R"CODE(
+
2909// Fast Binary Encoding optional _NAME_ final model
+
2910public final class FinalModelOptional_NAME_ extends _DOMAIN_fbe.FinalModel
+
2911{
+
2912 public FinalModelOptional_NAME_(_DOMAIN_fbe.Buffer buffer, long offset)
+
2913 {
+
2914 super(buffer, offset);
+
2915 value = new _MODEL_(buffer, 0);
+
2916 }
+
2917
+
2918 // Get the allocation size
+
2919 public long fbeAllocationSize(_TYPE_ optional) { return 1 + ((optional != null) ? value.fbeAllocationSize(optional) : 0); }
+
2920
+
2921 // Checks if the object contains a value
+
2922 public boolean hasValue()
+
2923 {
+
2924 if ((_buffer.getOffset() + fbeOffset() + 1) > _buffer.getSize())
+
2925 return false;
+
2926
+
2927 byte fbeHasValue = readInt8(fbeOffset());
+
2928 return (fbeHasValue != 0);
+
2929 }
+
2930
+
2931 // Base final model value
+
2932 public final _MODEL_ value;
+
2933
+
2934 // Check if the optional value is valid
+
2935 @Override
+
2936 public long verify()
+
2937 {
+
2938 if ((_buffer.getOffset() + fbeOffset() + 1) > _buffer.getSize())
+
2939 return Long.MAX_VALUE;
+
2940
+
2941 byte fbeHasValue = readInt8(fbeOffset());
+
2942 if (fbeHasValue == 0)
+
2943 return 1;
+
2944
+
2945 _buffer.shift(fbeOffset() + 1);
+
2946 long fbeResult = value.verify();
+
2947 _buffer.unshift(fbeOffset() + 1);
+
2948 return 1 + fbeResult;
+
2949 }
+
2950
+
2951 // Get the optional value
+
2952 public _TYPE_ get(_DOMAIN_fbe.Size size)
+
2953 {
+
2954 assert ((_buffer.getOffset() + fbeOffset() + 1) <= _buffer.getSize()) : "Model is broken!";
+
2955 if ((_buffer.getOffset() + fbeOffset() + 1) > _buffer.getSize())
+
2956 {
+
2957 size.value = 0;
+
2958 return null;
+
2959 }
+
2960
+
2961 if (!hasValue())
+
2962 {
+
2963 size.value = 1;
+
2964 return null;
+
2965 }
+
2966
+
2967 _buffer.shift(fbeOffset() + 1);
+
2968 _TYPE_ optional = value.get(size);
+
2969 _buffer.unshift(fbeOffset() + 1);
+
2970 size.value += 1;
+
2971 return optional;
+
2972 }
+
2973
+
2974 // Set the optional value
+
2975 public long set(_TYPE_ optional)
+
2976 {
+
2977 assert ((_buffer.getOffset() + fbeOffset() + 1) <= _buffer.getSize()) : "Model is broken!";
+
2978 if ((_buffer.getOffset() + fbeOffset() + 1) > _buffer.getSize())
+
2979 return 0;
+
2980
+
2981 byte fbeHasValue = (byte)((optional != null) ? 1 : 0);
+
2982 write(fbeOffset(), fbeHasValue);
+
2983 if (fbeHasValue == 0)
+
2984 return 1;
+
2985
+
2986 _buffer.shift(fbeOffset() + 1);
+
2987 long size = value.set(optional);
+
2988 _buffer.unshift(fbeOffset() + 1);
+
2989 return 1 + size;
+
2990 }
+
2991}
+
2992)CODE";
+
2993
+
2994 std::string type_name = IsPackageType(type) ? type : (domain + package + "." + type);
+
2995
+
2996 // Prepare code template
+
2997 code = std::regex_replace(code, std::regex("_DOMAIN_"), domain);
+
2998 code = std::regex_replace(code, std::regex("_NAME_"), name);
+
2999 code = std::regex_replace(code, std::regex("_TYPE_"), type_name);
+
3000 code = std::regex_replace(code, std::regex("_MODEL_"), model);
+
3001 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
3002
+
3003 Write(code);
+
3004
+
3005 // Generate footer
+
3006 GenerateFooter();
+
3007
+
3008 // Store the file
+
3009 WriteEnd();
+
3010 Store(file);
+
3011}
+
3012
+
3013void GeneratorJava::GenerateFBEFinalModelArray(const std::string& domain, const std::string& package, const std::string& name, const std::string& type, const std::string& model, bool bytes)
+
3014{
+
3015 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "fbe";
+
3016
+
3017 // Create package path
+
3018 CppCommon::Directory::CreateTree(path);
+
3019
+
3020 // Generate the file
+
3021 CppCommon::Path file = path / ("FinalModelArray" + name + ".java");
+
3022 WriteBegin();
+
3023
+
3024 // Generate headers
+
3025 GenerateHeader(CppCommon::Path(_input).filename().string());
+
3026 GenerateImports(domain, package + ".fbe");
+
3027
+
3028 std::string code = R"CODE(
+
3029// Fast Binary Encoding _NAME_ array final model
+
3030public final class FinalModelArray_NAME_ extends _DOMAIN_fbe.FinalModel
+
3031{
+
3032 private final _MODEL_ _model;
+
3033 private final long _size;
+
3034
+
3035 public FinalModelArray_NAME_(_DOMAIN_fbe.Buffer buffer, long offset, long size)
+
3036 {
+
3037 super(buffer, offset);
+
3038 _model = new _MODEL_(buffer, offset);
+
3039 _size = size;
+
3040 }
+
3041
+
3042 // Get the allocation size
+
3043 public long fbeAllocationSize(_ARRAY_ values)
+
3044 {
+
3045 long size = 0;
+
3046 for (long i = 0; (i < values.length) && (i < _size); i++)
+
3047 size += _model.fbeAllocationSize(values[(int)i]);
+
3048 return size;
+
3049 }
+
3050 public long fbeAllocationSize(java.util.ArrayList<_TYPE_> values)
+
3051 {
+
3052 long size = 0;
+
3053 for (long i = 0; (i < values.size()) && (i < _size); i++)
+
3054 size += _model.fbeAllocationSize(values.get((int)i));
+
3055 return size;
+
3056 }
+
3057
+
3058 // Check if the array is valid
+
3059 @Override
+
3060 public long verify()
+
3061 {
+
3062 if ((_buffer.getOffset() + fbeOffset()) > _buffer.getSize())
+
3063 return Long.MAX_VALUE;
+
3064
+
3065 long size = 0;
+
3066 _model.fbeOffset(fbeOffset());
+
3067 for (long i = _size; i-- > 0;)
+
3068 {
+
3069 long offset = _model.verify();
+
3070 if (offset == Long.MAX_VALUE)
+
3071 return Long.MAX_VALUE;
+
3072 _model.fbeShift(offset);
+
3073 size += offset;
+
3074 }
+
3075 return size;
+
3076 }
+
3077
+
3078 // Get the array
+
3079 public _ARRAY_ get(_DOMAIN_fbe.Size size)
+
3080 {
+
3081 var values = _INIT_;
+
3082
+
3083 assert ((_buffer.getOffset() + fbeOffset()) <= _buffer.getSize()) : "Model is broken!";
+
3084 if ((_buffer.getOffset() + fbeOffset()) > _buffer.getSize())
+
3085 {
+
3086 size.value = 0;
+
3087 return values;
+
3088 }
+
3089
+
3090 size.value = 0;
+
3091 var offset = new _DOMAIN_fbe.Size();
+
3092 _model.fbeOffset(fbeOffset());
+
3093 for (long i = 0; i < _size; i++)
+
3094 {
+
3095 offset.value = 0;
+
3096 values[(int)i] = _model.get(offset);
+
3097 _model.fbeShift(offset.value);
+
3098 size.value += offset.value;
+
3099 }
+
3100 return values;
+
3101 }
+
3102
+
3103 // Get the array
+
3104 public long get(_ARRAY_ values)
+
3105 {
+
3106 assert (values != null) : "Invalid values parameter!";
+
3107 if (values == null)
+
3108 throw new IllegalArgumentException("Invalid values parameter!");
+
3109
+
3110 assert ((_buffer.getOffset() + fbeOffset()) <= _buffer.getSize()) : "Model is broken!";
+
3111 if ((_buffer.getOffset() + fbeOffset()) > _buffer.getSize())
+
3112 return 0;
+
3113
+
3114 long size = 0;
+
3115 var offset = new _DOMAIN_fbe.Size();
+
3116 _model.fbeOffset(fbeOffset());
+
3117 for (long i = 0; (i < values.length) && (i < _size); i++)
+
3118 {
+
3119 offset.value = 0;
+
3120 values[(int)i] = _model.get(offset);
+
3121 _model.fbeShift(offset.value);
+
3122 size += offset.value;
+
3123 }
+
3124 return size;
+
3125 }
+
3126
+
3127 // Get the array as java.util.ArrayList
+
3128 public long get(java.util.ArrayList<_TYPE_> values)
+
3129 {
+
3130 assert (values != null) : "Invalid values parameter!";
+
3131 if (values == null)
+
3132 throw new IllegalArgumentException("Invalid values parameter!");
+
3133
+
3134 values.clear();
+
3135
+
3136 assert ((_buffer.getOffset() + fbeOffset()) <= _buffer.getSize()) : "Model is broken!";
+
3137 if ((_buffer.getOffset() + fbeOffset()) > _buffer.getSize())
+
3138 return 0;
+
3139
+
3140 values.ensureCapacity((int)_size);
+
3141
+
3142 long size = 0;
+
3143 var offset = new _DOMAIN_fbe.Size();
+
3144 _model.fbeOffset(fbeOffset());
+
3145 for (long i = _size; i-- > 0;)
+
3146 {
+
3147 offset.value = 0;
+
3148 _TYPE_ value = _model.get(offset);
+
3149 values.add(value);
+
3150 _model.fbeShift(offset.value);
+
3151 size += offset.value;
+
3152 }
+
3153 return size;
+
3154 }
+
3155
+
3156 // Set the array
+
3157 public long set(_ARRAY_ values)
+
3158 {
+
3159 assert (values != null) : "Invalid values parameter!";
+
3160 if (values == null)
+
3161 throw new IllegalArgumentException("Invalid values parameter!");
+
3162
+
3163 assert ((_buffer.getOffset() + fbeOffset()) <= _buffer.getSize()) : "Model is broken!";
+
3164 if ((_buffer.getOffset() + fbeOffset()) > _buffer.getSize())
+
3165 return 0;
+
3166
+
3167 long size = 0;
+
3168 _model.fbeOffset(fbeOffset());
+
3169 for (long i = 0; (i < values.length) && (i < _size); i++)
+
3170 {
+
3171 long offset = _model.set(values[(int)i]);
+
3172 _model.fbeShift(offset);
+
3173 size += offset;
+
3174 }
+
3175 return size;
+
3176 }
+
3177
+
3178 // Set the array as java.util.ArrayList
+
3179 public long set(java.util.ArrayList<_TYPE_> values)
+
3180 {
+
3181 assert (values != null) : "Invalid values parameter!";
+
3182 if (values == null)
+
3183 throw new IllegalArgumentException("Invalid values parameter!");
+
3184
+
3185 assert ((_buffer.getOffset() + fbeOffset()) <= _buffer.getSize()) : "Model is broken!";
+
3186 if ((_buffer.getOffset() + fbeOffset()) > _buffer.getSize())
+
3187 return 0;
+
3188
+
3189 long size = 0;
+
3190 _model.fbeOffset(fbeOffset());
+
3191 for (long i = 0; (i < values.size()) && (i < _size); i++)
+
3192 {
+
3193 long offset = _model.set(values.get((int)i));
+
3194 _model.fbeShift(offset);
+
3195 size += offset;
+
3196 }
+
3197 return size;
+
3198 }
+
3199}
+
3200)CODE";
+
3201
+
3202 std::string type_name = IsPackageType(type) ? type : (domain + package + "." + type);
+
3203
+
3204 // Prepare code template
+
3205 code = std::regex_replace(code, std::regex("_DOMAIN_"), domain);
+
3206 code = std::regex_replace(code, std::regex("_NAME_"), name);
+
3207 code = std::regex_replace(code, std::regex("_TYPE_"), type_name);
+
3208 code = std::regex_replace(code, std::regex("_MODEL_"), model);
+
3209 code = std::regex_replace(code, std::regex("_ARRAY_"), (bytes ? "byte" : type_name) + "[]");
+
3210 code = std::regex_replace(code, std::regex("_INIT_"), ((type != "byte[]") ? ("new " + (bytes ? "byte" : type_name) + "[(int)_size]") : "new byte[(int)_size][]"));
+
3211 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
3212
+
3213 Write(code);
+
3214
+
3215 // Generate footer
+
3216 GenerateFooter();
+
3217
+
3218 // Store the file
+
3219 WriteEnd();
+
3220 Store(file);
+
3221}
+
3222
+
3223void GeneratorJava::GenerateFBEFinalModelVector(const std::string& domain, const std::string& package, const std::string& name, const std::string& type, const std::string& model)
+
3224{
+
3225 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "fbe";
+
3226
+
3227 // Create package path
+
3228 CppCommon::Directory::CreateTree(path);
+
3229
+
3230 // Generate the file
+
3231 CppCommon::Path file = path / ("FinalModelVector" + name + ".java");
+
3232 WriteBegin();
+
3233
+
3234 // Generate headers
+
3235 GenerateHeader(CppCommon::Path(_input).filename().string());
+
3236 GenerateImports(domain, package + ".fbe");
+
3237
+
3238 std::string code = R"CODE(
+
3239// Fast Binary Encoding _NAME_ vector final model
+
3240public final class FinalModelVector_NAME_ extends _DOMAIN_fbe.FinalModel
+
3241{
+
3242 private final _MODEL_ _model;
+
3243
+
3244 public FinalModelVector_NAME_(_DOMAIN_fbe.Buffer buffer, long offset)
+
3245 {
+
3246 super(buffer, offset);
+
3247 _model = new _MODEL_(buffer, offset);
+
3248 }
+
3249
+
3250 // Get the allocation size
+
3251 public long fbeAllocationSize(_TYPE_[] values)
+
3252 {
+
3253 long size = 4;
+
3254 for (var value : values)
+
3255 size += _model.fbeAllocationSize(value);
+
3256 return size;
+
3257 }
+
3258 public long fbeAllocationSize(java.util.ArrayList<_TYPE_> values)
+
3259 {
+
3260 long size = 4;
+
3261 for (var value : values)
+
3262 size += _model.fbeAllocationSize(value);
+
3263 return size;
+
3264 }
+
3265 public long fbeAllocationSize(java.util.LinkedList<_TYPE_> values)
+
3266 {
+
3267 long size = 4;
+
3268 for (var value : values)
+
3269 size += _model.fbeAllocationSize(value);
+
3270 return size;
+
3271 }
+
3272 public long fbeAllocationSize(java.util.HashSet<_TYPE_> values)
+
3273 {
+
3274 long size = 4;
+
3275 for (var value : values)
+
3276 size += _model.fbeAllocationSize(value);
+
3277 return size;
+
3278 }
+
3279
+
3280 // Check if the vector is valid
+
3281 @Override
+
3282 public long verify()
+
3283 {
+
3284 if ((_buffer.getOffset() + fbeOffset() + 4) > _buffer.getSize())
+
3285 return Long.MAX_VALUE;
+
3286
+
3287 int fbeVectorSize = readInt32(fbeOffset());
+
3288
+
3289 long size = 4;
+
3290 _model.fbeOffset(fbeOffset() + 4);
+
3291 for (int i = fbeVectorSize; i-- > 0;)
+
3292 {
+
3293 long offset = _model.verify();
+
3294 if (offset == Long.MAX_VALUE)
+
3295 return Long.MAX_VALUE;
+
3296 _model.fbeShift(offset);
+
3297 size += offset;
+
3298 }
+
3299 return size;
+
3300 }
+
3301
+
3302 // Get the vector as java.util.ArrayList
+
3303 public long get(java.util.ArrayList<_TYPE_> values)
+
3304 {
+
3305 assert (values != null) : "Invalid values parameter!";
+
3306 if (values == null)
+
3307 throw new IllegalArgumentException("Invalid values parameter!");
+
3308
+
3309 values.clear();
+
3310
+
3311 assert ((_buffer.getOffset() + fbeOffset() + 4) <= _buffer.getSize()) : "Model is broken!";
+
3312 if ((_buffer.getOffset() + fbeOffset() + 4) > _buffer.getSize())
+
3313 return 0;
+
3314
+
3315 long fbeVectorSize = readInt32(fbeOffset());
+
3316 if (fbeVectorSize == 0)
+
3317 return 4;
+
3318
+
3319 values.ensureCapacity((int)fbeVectorSize);
+
3320
+
3321 long size = 4;
+
3322 var offset = new _DOMAIN_fbe.Size();
+
3323 _model.fbeOffset(fbeOffset() + 4);
+
3324 for (long i = 0; i < fbeVectorSize; i++)
+
3325 {
+
3326 offset.value = 0;
+
3327 _TYPE_ value = _model.get(offset);
+
3328 values.add(value);
+
3329 _model.fbeShift(offset.value);
+
3330 size += offset.value;
+
3331 }
+
3332 return size;
+
3333 }
+
3334
+
3335 // Get the vector as java.util.LinkedList
+
3336 public long get(java.util.LinkedList<_TYPE_> values)
+
3337 {
+
3338 assert (values != null) : "Invalid values parameter!";
+
3339 if (values == null)
+
3340 throw new IllegalArgumentException("Invalid values parameter!");
+
3341
+
3342 values.clear();
+
3343
+
3344 assert ((_buffer.getOffset() + fbeOffset() + 4) <= _buffer.getSize()) : "Model is broken!";
+
3345 if ((_buffer.getOffset() + fbeOffset() + 4) > _buffer.getSize())
+
3346 return 0;
+
3347
+
3348 long fbeVectorSize = readInt32(fbeOffset());
+
3349 if (fbeVectorSize == 0)
+
3350 return 4;
+
3351
+
3352 long size = 4;
+
3353 var offset = new _DOMAIN_fbe.Size();
+
3354 _model.fbeOffset(fbeOffset() + 4);
+
3355 for (long i = 0; i < fbeVectorSize; i++)
+
3356 {
+
3357 offset.value = 0;
+
3358 _TYPE_ value = _model.get(offset);
+
3359 values.add(value);
+
3360 _model.fbeShift(offset.value);
+
3361 size += offset.value;
+
3362 }
+
3363 return size;
+
3364 }
+
3365
+
3366 // Get the vector as java.util.HashSet
+
3367 public long get(java.util.HashSet<_TYPE_> values)
+
3368 {
+
3369 assert (values != null) : "Invalid values parameter!";
+
3370 if (values == null)
+
3371 throw new IllegalArgumentException("Invalid values parameter!");
+
3372
+
3373 values.clear();
+
3374
+
3375 assert ((_buffer.getOffset() + fbeOffset() + 4) <= _buffer.getSize()) : "Model is broken!";
+
3376 if ((_buffer.getOffset() + fbeOffset() + 4) > _buffer.getSize())
+
3377 return 0;
+
3378
+
3379 long fbeVectorSize = readInt32(fbeOffset());
+
3380 if (fbeVectorSize == 0)
+
3381 return 4;
+
3382
+
3383 long size = 4;
+
3384 var offset = new _DOMAIN_fbe.Size();
+
3385 _model.fbeOffset(fbeOffset() + 4);
+
3386 for (long i = 0; i < fbeVectorSize; i++)
+
3387 {
+
3388 offset.value = 0;
+
3389 _TYPE_ value = _model.get(offset);
+
3390 values.add(value);
+
3391 _model.fbeShift(offset.value);
+
3392 size += offset.value;
+
3393 }
+
3394 return size;
+
3395 }
+
3396
+
3397 // Set the vector as java.util.ArrayList
+
3398 public long set(java.util.ArrayList<_TYPE_> values)
+
3399 {
+
3400 assert (values != null) : "Invalid values parameter!";
+
3401 if (values == null)
+
3402 throw new IllegalArgumentException("Invalid values parameter!");
+
3403
+
3404 assert ((_buffer.getOffset() + fbeOffset() + 4) <= _buffer.getSize()) : "Model is broken!";
+
3405 if ((_buffer.getOffset() + fbeOffset() + 4) > _buffer.getSize())
+
3406 return 0;
+
3407
+
3408 write(fbeOffset(), (int)values.size());
+
3409
+
3410 long size = 4;
+
3411 _model.fbeOffset(fbeOffset() + 4);
+
3412 for (var value : values)
+
3413 {
+
3414 long offset = _model.set(value);
+
3415 _model.fbeShift(offset);
+
3416 size += offset;
+
3417 }
+
3418 return size;
+
3419 }
+
3420
+
3421 // Set the vector as java.util.LinkedList
+
3422 public long set(java.util.LinkedList<_TYPE_> values)
+
3423 {
+
3424 assert (values != null) : "Invalid values parameter!";
+
3425 if (values == null)
+
3426 throw new IllegalArgumentException("Invalid values parameter!");
+
3427
+
3428 assert ((_buffer.getOffset() + fbeOffset() + 4) <= _buffer.getSize()) : "Model is broken!";
+
3429 if ((_buffer.getOffset() + fbeOffset() + 4) > _buffer.getSize())
+
3430 return 0;
+
3431
+
3432 write(fbeOffset(), (int)values.size());
+
3433
+
3434 long size = 4;
+
3435 _model.fbeOffset(fbeOffset() + 4);
+
3436 for (var value : values)
+
3437 {
+
3438 long offset = _model.set(value);
+
3439 _model.fbeShift(offset);
+
3440 size += offset;
+
3441 }
+
3442 return size;
+
3443 }
+
3444
+
3445 // Set the vector as java.util.HashSet
+
3446 public long set(java.util.HashSet<_TYPE_> values)
+
3447 {
+
3448 assert (values != null) : "Invalid values parameter!";
+
3449 if (values == null)
+
3450 throw new IllegalArgumentException("Invalid values parameter!");
+
3451
+
3452 assert ((_buffer.getOffset() + fbeOffset() + 4) <= _buffer.getSize()) : "Model is broken!";
+
3453 if ((_buffer.getOffset() + fbeOffset() + 4) > _buffer.getSize())
+
3454 return 0;
+
3455
+
3456 write(fbeOffset(), (int)values.size());
+
3457
+
3458 long size = 4;
+
3459 _model.fbeOffset(fbeOffset() + 4);
+
3460 for (var value : values)
+
3461 {
+
3462 long offset = _model.set(value);
+
3463 _model.fbeShift(offset);
+
3464 size += offset;
+
3465 }
+
3466 return size;
+
3467 }
+
3468}
+
3469)CODE";
+
3470
+
3471 std::string type_name = IsPackageType(type) ? type : (domain + package + "." + type);
+
3472
+
3473 // Prepare code template
+
3474 code = std::regex_replace(code, std::regex("_DOMAIN_"), domain);
+
3475 code = std::regex_replace(code, std::regex("_NAME_"), name);
+
3476 code = std::regex_replace(code, std::regex("_TYPE_"), type_name);
+
3477 code = std::regex_replace(code, std::regex("_MODEL_"), model);
+
3478 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
3479
+
3480 Write(code);
+
3481
+
3482 // Generate footer
+
3483 GenerateFooter();
+
3484
+
3485 // Store the file
+
3486 WriteEnd();
+
3487 Store(file);
+
3488}
+
3489
+
3490void GeneratorJava::GenerateFBEFinalModelMap(const std::string& domain, const std::string& package, const std::string& key_name, const std::string& key_type, const std::string& key_model, const std::string& value_name, const std::string& value_type, const std::string& value_model)
+
3491{
+
3492 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "fbe";
+
3493
+
3494 // Create package path
+
3495 CppCommon::Directory::CreateTree(path);
+
3496
+
3497 // Generate the file
+
3498 CppCommon::Path file = path / ("FinalModelMap" + key_name + value_name + ".java");
+
3499 WriteBegin();
+
3500
+
3501 // Generate headers
+
3502 GenerateHeader(CppCommon::Path(_input).filename().string());
+
3503 GenerateImports(domain, package + ".fbe");
+
3504
+
3505 std::string code = R"CODE(
+
3506// Fast Binary Encoding _KEY_NAME_->_VALUE_NAME_ map final model
+
3507public final class FinalModelMap_KEY_NAME__VALUE_NAME_ extends _DOMAIN_fbe.FinalModel
+
3508{
+
3509 private final _KEY_MODEL_ _modelKey;
+
3510 private final _VALUE_MODEL_ _modelValue;
+
3511
+
3512 public FinalModelMap_KEY_NAME__VALUE_NAME_(_DOMAIN_fbe.Buffer buffer, long offset)
+
3513 {
+
3514 super(buffer, offset);
+
3515 _modelKey = new _KEY_MODEL_(buffer, offset);
+
3516 _modelValue = new _VALUE_MODEL_(buffer, offset);
+
3517 }
+
3518
+
3519 // Get the allocation size
+
3520 public long fbeAllocationSize(java.util.TreeMap<_KEY_TYPE_, _VALUE_TYPE_> values)
+
3521 {
+
3522 long size = 4;
+
3523 for (var value : values.entrySet())
+
3524 {
+
3525 size += _modelKey.fbeAllocationSize(value.getKey());
+
3526 size += _modelValue.fbeAllocationSize(value.getValue());
+
3527 }
+
3528 return size;
+
3529 }
+
3530 public long fbeAllocationSize(java.util.HashMap<_KEY_TYPE_, _VALUE_TYPE_> values)
+
3531 {
+
3532 long size = 4;
+
3533 for (var value : values.entrySet())
+
3534 {
+
3535 size += _modelKey.fbeAllocationSize(value.getKey());
+
3536 size += _modelValue.fbeAllocationSize(value.getValue());
+
3537 }
+
3538 return size;
+
3539 }
+
3540
+
3541 // Check if the map is valid
+
3542 @Override
+
3543 public long verify()
+
3544 {
+
3545 if ((_buffer.getOffset() + fbeOffset() + 4) > _buffer.getSize())
+
3546 return Long.MAX_VALUE;
+
3547
+
3548 int fbeMapSize = readInt32(fbeOffset());
+
3549
+
3550 long size = 4;
+
3551 _modelKey.fbeOffset(fbeOffset() + 4);
+
3552 _modelValue.fbeOffset(fbeOffset() + 4);
+
3553 for (int i = fbeMapSize; i-- > 0;)
+
3554 {
+
3555 long offsetKey = _modelKey.verify();
+
3556 if (offsetKey == Long.MAX_VALUE)
+
3557 return Long.MAX_VALUE;
+
3558 _modelKey.fbeShift(offsetKey);
+
3559 _modelValue.fbeShift(offsetKey);
+
3560 size += offsetKey;
+
3561 long offsetValue = _modelValue.verify();
+
3562 if (offsetValue == Long.MAX_VALUE)
+
3563 return Long.MAX_VALUE;
+
3564 _modelKey.fbeShift(offsetValue);
+
3565 _modelValue.fbeShift(offsetValue);
+
3566 size += offsetValue;
+
3567 }
+
3568 return size;
+
3569 }
+
3570
+
3571 // Get the map as java.util.TreeMap
+
3572 public long get(java.util.TreeMap<_KEY_TYPE_, _VALUE_TYPE_> values)
+
3573 {
+
3574 assert (values != null) : "Invalid values parameter!";
+
3575 if (values == null)
+
3576 throw new IllegalArgumentException("Invalid values parameter!");
+
3577
+
3578 values.clear();
+
3579
+
3580 assert ((_buffer.getOffset() + fbeOffset() + 4) <= _buffer.getSize()) : "Model is broken!";
+
3581 if ((_buffer.getOffset() + fbeOffset() + 4) > _buffer.getSize())
+
3582 return 0;
+
3583
+
3584 long fbeMapSize = readInt32(fbeOffset());
+
3585 if (fbeMapSize == 0)
+
3586 return 4;
+
3587
+
3588 long size = 4;
+
3589 var offset = new _DOMAIN_fbe.Size();
+
3590 _modelKey.fbeOffset(fbeOffset() + 4);
+
3591 _modelValue.fbeOffset(fbeOffset() + 4);
+
3592 for (long i = fbeMapSize; i-- > 0;)
+
3593 {
+
3594 offset.value = 0;
+
3595 _KEY_TYPE_ key = _modelKey.get(offset);
+
3596 _modelKey.fbeShift(offset.value);
+
3597 _modelValue.fbeShift(offset.value);
+
3598 size += offset.value;
+
3599 offset.value = 0;
+
3600 _VALUE_TYPE_ value = _modelValue.get(offset);
+
3601 _modelKey.fbeShift(offset.value);
+
3602 _modelValue.fbeShift(offset.value);
+
3603 size += offset.value;
+
3604 values.put(key, value);
+
3605 }
+
3606 return size;
+
3607 }
+
3608
+
3609 // Get the map as java.util.HashMap
+
3610 public long get(java.util.HashMap<_KEY_TYPE_, _VALUE_TYPE_> values)
+
3611 {
+
3612 assert (values != null) : "Invalid values parameter!";
+
3613 if (values == null)
+
3614 throw new IllegalArgumentException("Invalid values parameter!");
+
3615
+
3616 values.clear();
+
3617
+
3618 assert ((_buffer.getOffset() + fbeOffset() + 4) <= _buffer.getSize()) : "Model is broken!";
+
3619 if ((_buffer.getOffset() + fbeOffset() + 4) > _buffer.getSize())
+
3620 return 0;
+
3621
+
3622 long fbeMapSize = readInt32(fbeOffset());
+
3623 if (fbeMapSize == 0)
+
3624 return 4;
+
3625
+
3626 long size = 4;
+
3627 var offset = new _DOMAIN_fbe.Size();
+
3628 _modelKey.fbeOffset(fbeOffset() + 4);
+
3629 _modelValue.fbeOffset(fbeOffset() + 4);
+
3630 for (long i = fbeMapSize; i-- > 0;)
+
3631 {
+
3632 offset.value = 0;
+
3633 _KEY_TYPE_ key = _modelKey.get(offset);
+
3634 _modelKey.fbeShift(offset.value);
+
3635 _modelValue.fbeShift(offset.value);
+
3636 size += offset.value;
+
3637 offset.value = 0;
+
3638 _VALUE_TYPE_ value = _modelValue.get(offset);
+
3639 _modelKey.fbeShift(offset.value);
+
3640 _modelValue.fbeShift(offset.value);
+
3641 size += offset.value;
+
3642
+
3643 values.put(key, value);
+
3644 }
+
3645 return size;
+
3646 }
+
3647
+
3648 // Set the map as java.util.TreeMap
+
3649 public long set(java.util.TreeMap<_KEY_TYPE_, _VALUE_TYPE_> values)
+
3650 {
+
3651 assert (values != null) : "Invalid values parameter!";
+
3652 if (values == null)
+
3653 throw new IllegalArgumentException("Invalid values parameter!");
+
3654
+
3655 assert ((_buffer.getOffset() + fbeOffset() + 4) <= _buffer.getSize()) : "Model is broken!";
+
3656 if ((_buffer.getOffset() + fbeOffset() + 4) > _buffer.getSize())
+
3657 return 0;
+
3658
+
3659 write(fbeOffset(), (int)values.size());
+
3660
+
3661 long size = 4;
+
3662 _modelKey.fbeOffset(fbeOffset() + 4);
+
3663 _modelValue.fbeOffset(fbeOffset() + 4);
+
3664 for (var value : values.entrySet())
+
3665 {
+
3666 long offsetKey = _modelKey.set(value.getKey());
+
3667 _modelKey.fbeShift(offsetKey);
+
3668 _modelValue.fbeShift(offsetKey);
+
3669 long offsetValue = _modelValue.set(value.getValue());
+
3670 _modelKey.fbeShift(offsetValue);
+
3671 _modelValue.fbeShift(offsetValue);
+
3672 size += offsetKey + offsetValue;
+
3673 }
+
3674 return size;
+
3675 }
+
3676
+
3677 // Set the map as java.util.HashMap
+
3678 public long set(java.util.HashMap<_KEY_TYPE_, _VALUE_TYPE_> values)
+
3679 {
+
3680 assert (values != null) : "Invalid values parameter!";
+
3681 if (values == null)
+
3682 throw new IllegalArgumentException("Invalid values parameter!");
+
3683
+
3684 assert ((_buffer.getOffset() + fbeOffset() + 4) <= _buffer.getSize()) : "Model is broken!";
+
3685 if ((_buffer.getOffset() + fbeOffset() + 4) > _buffer.getSize())
+
3686 return 0;
+
3687
+
3688 write(fbeOffset(), (int)values.size());
+
3689
+
3690 long size = 4;
+
3691 _modelKey.fbeOffset(fbeOffset() + 4);
+
3692 _modelValue.fbeOffset(fbeOffset() + 4);
+
3693 for (var value : values.entrySet())
+
3694 {
+
3695 long offsetKey = _modelKey.set(value.getKey());
+
3696 _modelKey.fbeShift(offsetKey);
+
3697 _modelValue.fbeShift(offsetKey);
+
3698 long offsetValue = _modelValue.set(value.getValue());
+
3699 _modelKey.fbeShift(offsetValue);
+
3700 _modelValue.fbeShift(offsetValue);
+
3701 size += offsetKey + offsetValue;
+
3702 }
+
3703 return size;
+
3704 }
+
3705}
+
3706)CODE";
+
3707
+
3708 std::string key_type_name = IsPackageType(key_type) ? key_type : (domain + package + "." + key_type);
+
3709 std::string value_type_name = IsPackageType(value_type) ? value_type : (domain + package + "." + value_type);
+
3710
+
3711 // Prepare code template
+
3712 code = std::regex_replace(code, std::regex("_DOMAIN_"), domain);
+
3713 code = std::regex_replace(code, std::regex("_KEY_NAME_"), key_name);
+
3714 code = std::regex_replace(code, std::regex("_KEY_TYPE_"), key_type_name);
+
3715 code = std::regex_replace(code, std::regex("_KEY_MODEL_"), key_model);
+
3716 code = std::regex_replace(code, std::regex("_VALUE_NAME_"), value_name);
+
3717 code = std::regex_replace(code, std::regex("_VALUE_TYPE_"), value_type_name);
+
3718 code = std::regex_replace(code, std::regex("_VALUE_MODEL_"), value_model);
+
3719 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
3720
+
3721 Write(code);
+
3722
+
3723 // Generate footer
+
3724 GenerateFooter();
+
3725
+
3726 // Store the file
+
3727 WriteEnd();
+
3728 Store(file);
+
3729}
+
3730
+
3731void GeneratorJava::GenerateFBEFinalModelEnumFlags(const std::string& domain, const std::string& package, const std::string& name, const std::string& type)
+
3732{
+
3733 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "fbe";
+
3734
+
3735 // Create package path
+
3736 CppCommon::Directory::CreateTree(path);
+
3737
+
3738 // Generate the file
+
3739 CppCommon::Path file = path / ("FinalModel" + name + ".java");
+
3740 WriteBegin();
+
3741
+
3742 // Generate headers
+
3743 GenerateHeader(CppCommon::Path(_input).filename().string());
+
3744 GenerateImports(domain, package + ".fbe");
+
3745
+
3746 std::string code = R"CODE(
+
3747// Fast Binary Encoding _NAME_ final model
+
3748public final class FinalModel_NAME_ extends _DOMAIN_fbe.FinalModel
+
3749{
+
3750 public FinalModel_NAME_(_DOMAIN_fbe.Buffer buffer, long offset) { super(buffer, offset); }
+
3751
+
3752 // Get the allocation size
+
3753 public long fbeAllocationSize(_DOMAIN__PACKAGE_._NAME_ value) { return fbeSize(); }
+
3754
+
3755 // Get the final size
+
3756 @Override
+
3757 public long fbeSize() { return _SIZE_; }
+
3758
+
3759 // Check if the value is valid
+
3760 @Override
+
3761 public long verify()
+
3762 {
+
3763 if ((_buffer.getOffset() + fbeOffset() + fbeSize()) > _buffer.getSize())
+
3764 return Long.MAX_VALUE;
+
3765
+
3766 return fbeSize();
+
3767 }
+
3768
+
3769 // Get the value
+
3770 public _DOMAIN__PACKAGE_._NAME_ get(_DOMAIN_fbe.Size size)
+
3771 {
+
3772 if ((_buffer.getOffset() + fbeOffset() + fbeSize()) > _buffer.getSize())
+
3773 return new _DOMAIN__PACKAGE_._NAME_();
+
3774
+
3775 size.value = fbeSize();
+
3776 return new _DOMAIN__PACKAGE_._NAME_(_READ_(fbeOffset()));
+
3777 }
+
3778
+
3779 // Set the value
+
3780 public long set(_DOMAIN__PACKAGE_._NAME_ value)
+
3781 {
+
3782 assert ((_buffer.getOffset() + fbeOffset() + fbeSize()) <= _buffer.getSize()) : "Model is broken!";
+
3783 if ((_buffer.getOffset() + fbeOffset() + fbeSize()) > _buffer.getSize())
+
3784 return 0;
+
3785
+
3786 write(fbeOffset(), value.getRaw());
+
3787 return fbeSize();
+
3788 }
+
3789}
+
3790)CODE";
+
3791
+
3792 // Prepare code template
+
3793 code = std::regex_replace(code, std::regex("_DOMAIN_"), domain);
+
3794 code = std::regex_replace(code, std::regex("_PACKAGE_"), package);
+
3795 code = std::regex_replace(code, std::regex("_NAME_"), name);
+
3796 code = std::regex_replace(code, std::regex("_SIZE_"), ConvertEnumSize(type));
+
3797 code = std::regex_replace(code, std::regex("_READ_"), ConvertEnumRead(type));
+
3798 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
3799
+
3800 Write(code);
+
3801
+
3802 // Generate footer
+
3803 GenerateFooter();
+
3804
+
3805 // Store the file
+
3806 WriteEnd();
+
3807 Store(file);
+
3808}
+
3809
+
3810void GeneratorJava::GenerateFBESender(const std::string& domain, const std::string& package)
+
3811{
+
3812 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
3813
+
3814 // Generate the file
+
3815 CppCommon::Path file = path / "Sender.java";
+
3816 WriteBegin();
+
3817
+
3818 // Generate headers
+
3819 GenerateHeader("FBE");
+
3820 GenerateImports(domain, package);
+
3821
+
3822 std::string code = R"CODE(
+
3823// Fast Binary Encoding base sender
+
3824public abstract class Sender
+
3825{
+
3826 private Buffer _buffer;
+
3827 private boolean _logging;
+
3828 private boolean _final;
+
3829
+
3830 // Get the bytes buffer
+
3831 public Buffer getBuffer() { return _buffer; }
+
3832
+
3833 // Get the final protocol flag
+
3834 public boolean getFinal() { return _final; }
+
3835
+
3836 // Get the logging flag
+
3837 public boolean getLogging() { return _logging; }
+
3838 // Enable/Disable logging
+
3839 public void setLogging(boolean enable) { _logging = enable; }
+
3840
+
3841 protected Sender(boolean finalProto) { _buffer = new Buffer(); _final = finalProto; }
+
3842 protected Sender(Buffer buffer, boolean finalProto) { _buffer = buffer; _final = finalProto; }
+
3843
+
3844 // Reset the sender buffer
+
3845 public void reset() { _buffer.reset(); }
+
3846
+
3847 // Send serialized buffer.
+
3848 // Direct call of the method requires knowledge about internals of FBE models serialization.
+
3849 // Use it with care!
+
3850 public long sendSerialized(long serialized)
+
3851 {
+
3852 assert (serialized > 0) : "Invalid size of the serialized buffer!";
+
3853 if (serialized <= 0)
+
3854 return 0;
+
3855
+
3856 // Shift the send buffer
+
3857 _buffer.shift(serialized);
+
3858
+
3859 // Send the value
+
3860 long sent = onSend(_buffer.getData(), 0, _buffer.getSize());
+
3861 _buffer.remove(0, sent);
+
3862 return sent;
+
3863 }
+
3864
+
3865 // Send message handler
+
3866 protected abstract long onSend(byte[] buffer, long offset, long size);
+
3867 // Send log message handler
+
3868 protected void onSendLog(String message) {}
+
3869}
+
3870)CODE";
+
3871
+
3872 // Prepare code template
+
3873 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
3874
+
3875 Write(code);
+
3876
+
3877 // Generate footer
+
3878 GenerateFooter();
+
3879
+
3880 // Store the file
+
3881 WriteEnd();
+
3882 Store(file);
+
3883}
+
3884
+
3885void GeneratorJava::GenerateFBEReceiver(const std::string& domain, const std::string& package)
+
3886{
+
3887 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
3888
+
3889 // Generate the file
+
3890 CppCommon::Path file = path / "Receiver.java";
+
3891 WriteBegin();
+
3892
+
3893 // Generate headers
+
3894 GenerateHeader("FBE");
+
3895 GenerateImports(domain, package);
+
3896
+
3897 std::string code = R"CODE(
+
3898// Fast Binary Encoding base receiver
+
3899public abstract class Receiver
+
3900{
+
3901 private Buffer _buffer;
+
3902 private boolean _logging;
+
3903 private boolean _final;
+
3904
+
3905 // Get the bytes buffer
+
3906 public Buffer getBuffer() { return _buffer; }
+
3907
+
3908 // Get the final protocol flag
+
3909 public boolean getFinal() { return _final; }
+
3910
+
3911 // Get the logging flag
+
3912 public boolean getLogging() { return _logging; }
+
3913 // Enable/Disable logging
+
3914 public void setLogging(boolean enable) { _logging = enable; }
+
3915
+
3916 protected Receiver(boolean finalProto) { _buffer = new Buffer(); _final = finalProto; }
+
3917 protected Receiver(Buffer buffer, boolean finalProto) { _buffer = buffer; _final = finalProto; }
+
3918
+
3919 // Reset the receiver buffer
+
3920 public void reset() { _buffer.reset(); }
+
3921
+
3922 // Receive data
+
3923 public void receive(Buffer buffer) { receive(buffer.getData(), 0, buffer.getSize()); }
+
3924 public void receive(byte[] buffer) { receive(buffer, 0, buffer.length); }
+
3925 public void receive(byte[] buffer, long offset, long size)
+
3926 {
+
3927 assert (buffer != null) : "Invalid buffer!";
+
3928 if (buffer == null)
+
3929 throw new IllegalArgumentException("Invalid buffer!");
+
3930 assert ((offset + size) <= buffer.length) : "Invalid offset & size!";
+
3931 if ((offset + size) > buffer.length)
+
3932 throw new IllegalArgumentException("Invalid offset & size!");
+
3933
+
3934 if (size == 0)
+
3935 return;
+
3936
+
3937 // Storage buffer
+
3938 long offset0 = _buffer.getOffset();
+
3939 long offset1 = _buffer.getSize();
+
3940 long size1 = _buffer.getSize();
+
3941
+
3942 // Receive buffer
+
3943 long offset2 = 0;
+
3944 long size2 = size;
+
3945
+
3946 // While receive buffer is available to handle...
+
3947 while (offset2 < size2)
+
3948 {
+
3949 byte[] messageBuffer = null;
+
3950 long messageOffset = 0;
+
3951 long messageSize = 0;
+
3952
+
3953 // Try to receive message size
+
3954 boolean messageSizeCopied = false;
+
3955 boolean messageSizeFound = false;
+
3956 while (!messageSizeFound)
+
3957 {
+
3958 // Look into the storage buffer
+
3959 if (offset0 < size1)
+
3960 {
+
3961 long count = Math.min(size1 - offset0, 4);
+
3962 if (count == 4)
+
3963 {
+
3964 messageSizeCopied = true;
+
3965 messageSizeFound = true;
+
3966 messageSize = _buffer.readInt32(_buffer.getData(), offset0);
+
3967 offset0 += 4;
+
3968 break;
+
3969 }
+
3970 else
+
3971 {
+
3972 // Fill remaining data from the receive buffer
+
3973 if (offset2 < size2)
+
3974 {
+
3975 count = Math.min(size2 - offset2, 4 - count);
+
3976
+
3977 // Allocate and refresh the storage buffer
+
3978 _buffer.allocate(count);
+
3979 size1 += count;
+
3980
+
3981 System.arraycopy(buffer, (int)(offset + offset2), _buffer.getData(), (int)offset1, (int)count);
+
3982 offset1 += count;
+
3983 offset2 += count;
+
3984 continue;
+
3985 }
+
3986 else
+
3987 break;
+
3988 }
+
3989 }
+
3990
+
3991 // Look into the receive buffer
+
3992 if (offset2 < size2)
+
3993 {
+
3994 long count = Math.min(size2 - offset2, 4);
+
3995 if (count == 4)
+
3996 {
+
3997 messageSizeFound = true;
+
3998 messageSize = _buffer.readInt32(buffer, offset + offset2);
+
3999 offset2 += 4;
+
4000 break;
+
4001 }
+
4002 else
+
4003 {
+
4004 // Allocate and refresh the storage buffer
+
4005 _buffer.allocate(count);
+
4006 size1 += count;
+
4007
+
4008 System.arraycopy(buffer, (int)(offset + offset2), _buffer.getData(), (int)offset1, (int)count);
+
4009 offset1 += count;
+
4010 offset2 += count;
+
4011 continue;
+
4012 }
+
4013 }
+
4014 else
+
4015 break;
+
4016 }
+
4017
+
4018 if (!messageSizeFound)
+
4019 return;
+
4020
+
4021 // Check the message full size
+
4022 long minSize = _final ? (4 + 4) : (4 + 4 + 4 + 4);
+
4023 assert (messageSize >= minSize) : "Invalid receive data!";
+
4024 if (messageSize < minSize)
+
4025 return;
+
4026
+
4027 // Try to receive message body
+
4028 boolean messageFound = false;
+
4029 while (!messageFound)
+
4030 {
+
4031 // Look into the storage buffer
+
4032 if (offset0 < size1)
+
4033 {
+
4034 long count = Math.min(size1 - offset0, messageSize - 4);
+
4035 if (count == (messageSize - 4))
+
4036 {
+
4037 messageFound = true;
+
4038 messageBuffer = _buffer.getData();
+
4039 messageOffset = offset0 - 4;
+
4040 offset0 += messageSize - 4;
+
4041 break;
+
4042 }
+
4043 else
+
4044 {
+
4045 // Fill remaining data from the receive buffer
+
4046 if (offset2 < size2)
+
4047 {
+
4048 // Copy message size into the storage buffer
+
4049 if (!messageSizeCopied)
+
4050 {
+
4051 // Allocate and refresh the storage buffer
+
4052 _buffer.allocate(4);
+
4053 size1 += 4;
+
4054
+
4055 _buffer.write(_buffer.getData(), offset0, (int)messageSize);
+
4056 offset0 += 4;
+
4057 offset1 += 4;
+
4058
+
4059 messageSizeCopied = true;
+
4060 }
+
4061
+
4062 count = Math.min(size2 - offset2, messageSize - 4 - count);
+
4063
+
4064 // Allocate and refresh the storage buffer
+
4065 _buffer.allocate(count);
+
4066 size1 += count;
+
4067
+
4068 System.arraycopy(buffer, (int)(offset + offset2), _buffer.getData(), (int)offset1, (int)count);
+
4069 offset1 += count;
+
4070 offset2 += count;
+
4071 continue;
+
4072 }
+
4073 else
+
4074 break;
+
4075 }
+
4076 }
+
4077
+
4078 // Look into the receive buffer
+
4079 if (offset2 < size2)
+
4080 {
+
4081 long count = Math.min(size2 - offset2, messageSize - 4);
+
4082 if (!messageSizeCopied && (count == (messageSize - 4)))
+
4083 {
+
4084 messageFound = true;
+
4085 messageBuffer = buffer;
+
4086 messageOffset = offset + offset2 - 4;
+
4087 offset2 += messageSize - 4;
+
4088 break;
+
4089 }
+
4090 else
+
4091 {
+
4092 // Copy message size into the storage buffer
+
4093 if (!messageSizeCopied)
+
4094 {
+
4095 // Allocate and refresh the storage buffer
+
4096 _buffer.allocate(4);
+
4097 size1 += 4;
+
4098
+
4099 _buffer.write(_buffer.getData(), offset0, (int)messageSize);
+
4100 offset0 += 4;
+
4101 offset1 += 4;
+
4102
+
4103 messageSizeCopied = true;
+
4104 }
+
4105
+
4106 // Allocate and refresh the storage buffer
+
4107 _buffer.allocate(count);
+
4108 size1 += count;
+
4109
+
4110 System.arraycopy(buffer, (int)(offset + offset2), _buffer.getData(), (int)offset1, (int)count);
+
4111 offset1 += count;
+
4112 offset2 += count;
+
4113 continue;
+
4114 }
+
4115 }
+
4116 else
+
4117 break;
+
4118 }
+
4119
+
4120 if (!messageFound)
+
4121 {
+
4122 // Copy message size into the storage buffer
+
4123 if (!messageSizeCopied)
+
4124 {
+
4125 // Allocate and refresh the storage buffer
+
4126 _buffer.allocate(4);
+
4127 size1 += 4;
+
4128
+
4129 _buffer.write(_buffer.getData(), offset0, (int)messageSize);
+
4130 offset0 += 4;
+
4131 offset1 += 4;
+
4132
+
4133 messageSizeCopied = true;
+
4134 }
+
4135 return;
+
4136 }
+
4137
+
4138 int fbeStructSize;
+
4139 int fbeStructType;
+
4140
+
4141 // Read the message parameters
+
4142 if (_final)
+
4143 {
+
4144 fbeStructSize = Buffer.readInt32(messageBuffer, messageOffset);
+
4145 fbeStructType = Buffer.readInt32(messageBuffer, messageOffset + 4);
+
4146 }
+
4147 else
+
4148 {
+
4149 int fbeStructOffset = Buffer.readInt32(messageBuffer, messageOffset + 4);
+
4150 fbeStructSize = Buffer.readInt32(messageBuffer, messageOffset + fbeStructOffset);
+
4151 fbeStructType = Buffer.readInt32(messageBuffer, messageOffset + fbeStructOffset + 4);
+
4152 }
+
4153
+
4154 // Handle the message
+
4155 onReceive(fbeStructType, messageBuffer, messageOffset, messageSize);
+
4156
+
4157 // Reset the storage buffer
+
4158 _buffer.reset();
+
4159
+
4160 // Refresh the storage buffer
+
4161 offset0 = _buffer.getOffset();
+
4162 offset1 = _buffer.getSize();
+
4163 size1 = _buffer.getSize();
+
4164 }
+
4165 }
+
4166
+
4167 // Receive message handler
+
4168 public abstract boolean onReceive(long type, byte[] buffer, long offset, long size);
+
4169 // Receive log message handler
+
4170 protected void onReceiveLog(String message) {}
+
4171}
+
4172)CODE";
+
4173
+
4174 // Prepare code template
+
4175 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
4176
+
4177 Write(code);
+
4178
+
4179 // Generate footer
+
4180 GenerateFooter();
+
4181
+
4182 // Store the file
+
4183 WriteEnd();
+
4184 Store(file);
+
4185}
+
4186
+
4187void GeneratorJava::GenerateFBEJson(const std::string& domain, const std::string& package)
+
4188{
+
4189 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
4190
+
4191 // Generate the file
+
4192 CppCommon::Path file = path / "Json.java";
+
4193 WriteBegin();
+
4194
+
4195 // Generate headers
+
4196 GenerateHeader("FBE");
+
4197 GenerateImports(domain, package);
+
4198
+
4199 std::string code = R"CODE(
+
4200final class ByteBufferJson implements com.google.gson.JsonSerializer<java.nio.ByteBuffer>, com.google.gson.JsonDeserializer<java.nio.ByteBuffer>
+
4201{
+
4202 @Override
+
4203 public com.google.gson.JsonElement serialize(java.nio.ByteBuffer src, java.lang.reflect.Type typeOfSrc, com.google.gson.JsonSerializationContext context)
+
4204 {
+
4205 return new com.google.gson.JsonPrimitive(java.util.Base64.getEncoder().encodeToString(src.array()));
+
4206 }
+
4207
+
4208 @Override
+
4209 public java.nio.ByteBuffer deserialize(com.google.gson.JsonElement json, java.lang.reflect.Type type, com.google.gson.JsonDeserializationContext context) throws com.google.gson.JsonParseException
+
4210 {
+
4211 return java.nio.ByteBuffer.wrap(java.util.Base64.getDecoder().decode(json.getAsString()));
+
4212 }
+
4213}
+
4214
+
4215final class CharacterJson implements com.google.gson.JsonSerializer<Character>, com.google.gson.JsonDeserializer<Character>
+
4216{
+
4217 @Override
+
4218 public com.google.gson.JsonElement serialize(Character src, java.lang.reflect.Type typeOfSrc, com.google.gson.JsonSerializationContext context)
+
4219 {
+
4220 return new com.google.gson.JsonPrimitive((long)src);
+
4221 }
+
4222
+
4223 @Override
+
4224 public Character deserialize(com.google.gson.JsonElement json, java.lang.reflect.Type type, com.google.gson.JsonDeserializationContext context) throws com.google.gson.JsonParseException
+
4225 {
+
4226 return (char)json.getAsLong();
+
4227 }
+
4228}
+
4229
+
4230final class DateJson implements com.google.gson.JsonSerializer<java.util.Date>, com.google.gson.JsonDeserializer<java.util.Date>
+
4231{
+
4232 @Override
+
4233 public com.google.gson.JsonElement serialize(java.util.Date src, java.lang.reflect.Type typeOfSrc, com.google.gson.JsonSerializationContext context)
+
4234 {
+
4235 long nanoseconds = src.getTime() * 1000;
+
4236 return new com.google.gson.JsonPrimitive(nanoseconds);
+
4237 }
+
4238
+
4239 @Override
+
4240 public java.util.Date deserialize(com.google.gson.JsonElement json, java.lang.reflect.Type type, com.google.gson.JsonDeserializationContext context) throws com.google.gson.JsonParseException
+
4241 {
+
4242 long nanoseconds = json.getAsJsonPrimitive().getAsLong();
+
4243 return new java.util.Date(nanoseconds / 1000000);
+
4244 }
+
4245}
+
4246
+
4247final class InstantJson implements com.google.gson.JsonSerializer<java.time.Instant>, com.google.gson.JsonDeserializer<java.time.Instant>
+
4248{
+
4249 @Override
+
4250 public com.google.gson.JsonElement serialize(java.time.Instant src, java.lang.reflect.Type typeOfSrc, com.google.gson.JsonSerializationContext context)
+
4251 {
+
4252 long nanoseconds = src.getEpochSecond() * 1000000000 + src.getNano();
+
4253 return new com.google.gson.JsonPrimitive(nanoseconds);
+
4254 }
+
4255
+
4256 @Override
+
4257 public java.time.Instant deserialize(com.google.gson.JsonElement json, java.lang.reflect.Type type, com.google.gson.JsonDeserializationContext context) throws com.google.gson.JsonParseException
+
4258 {
+
4259 long nanoseconds = json.getAsJsonPrimitive().getAsLong();
+
4260 return java.time.Instant.ofEpochSecond(nanoseconds / 1000000000, nanoseconds % 1000000000);
+
4261 }
+
4262}
+
4263
+
4264final class BigDecimalJson implements com.google.gson.JsonSerializer<java.math.BigDecimal>, com.google.gson.JsonDeserializer<java.math.BigDecimal>
+
4265{
+
4266 @Override
+
4267 public com.google.gson.JsonElement serialize(java.math.BigDecimal src, java.lang.reflect.Type typeOfSrc, com.google.gson.JsonSerializationContext context)
+
4268 {
+
4269 return new com.google.gson.JsonPrimitive(src.toPlainString());
+
4270 }
+
4271
+
4272 @Override
+
4273 public java.math.BigDecimal deserialize(com.google.gson.JsonElement json, java.lang.reflect.Type type, com.google.gson.JsonDeserializationContext context) throws com.google.gson.JsonParseException
+
4274 {
+
4275 return new java.math.BigDecimal(json.getAsJsonPrimitive().getAsString());
+
4276 }
+
4277}
+
4278
+
4279final class UUIDJson implements com.google.gson.JsonSerializer<java.util.UUID>, com.google.gson.JsonDeserializer<java.util.UUID>
+
4280{
+
4281 @Override
+
4282 public com.google.gson.JsonElement serialize(java.util.UUID src, java.lang.reflect.Type typeOfSrc, com.google.gson.JsonSerializationContext context)
+
4283 {
+
4284 return new com.google.gson.JsonPrimitive(src.toString());
+
4285 }
+
4286
+
4287 @Override
+
4288 public java.util.UUID deserialize(com.google.gson.JsonElement json, java.lang.reflect.Type type, com.google.gson.JsonDeserializationContext context) throws com.google.gson.JsonParseException
+
4289 {
+
4290 return java.util.UUID.fromString(json.getAsJsonPrimitive().getAsString());
+
4291 }
+
4292}
+
4293
+
4294// Fast Binary Encoding base JSON engine
+
4295public final class Json
+
4296{
+
4297 private static final com.google.gson.Gson _engine;
+
4298
+
4299 // Get the JSON engine
+
4300 public static com.google.gson.Gson getEngine() { return _engine; }
+
4301
+
4302 static
+
4303 {
+
4304 _engine = register(new com.google.gson.GsonBuilder()).create();
+
4305 }
+
4306
+
4307 private Json() {}
+
4308
+
4309 public static com.google.gson.GsonBuilder register(com.google.gson.GsonBuilder builder)
+
4310 {
+
4311 builder.serializeNulls();
+
4312 builder.registerTypeAdapter(java.nio.ByteBuffer.class, new ByteBufferJson());
+
4313 builder.registerTypeAdapter(char.class, new CharacterJson());
+
4314 builder.registerTypeAdapter(Character.class, new CharacterJson());
+
4315 builder.registerTypeAdapter(java.util.Date.class, new DateJson());
+
4316 builder.registerTypeAdapter(java.time.Instant.class, new InstantJson());
+
4317 builder.registerTypeAdapter(java.math.BigDecimal.class, new BigDecimalJson());
+
4318 builder.registerTypeAdapter(java.util.UUID.class, new UUIDJson());
+
4319 return builder;
+
4320 }
+
4321}
+
4322)CODE";
+
4323
+
4324 // Prepare code template
+
4325 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
4326
+
4327 Write(code);
+
4328
+
4329 // Generate footer
+
4330 GenerateFooter();
+
4331
+
4332 // Store the file
+
4333 WriteEnd();
+
4334 Store(file);
+
4335}
+
4336
+
4337void GeneratorJava::GenerateContainers(const std::shared_ptr<Package>& p, bool final)
+
4338{
+
4339 std::string domain = (p->domain && !p->domain->empty()) ? (*p->domain + ".") : "";
+
4340 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, *p->name);
+
4341
+
4342 // Create package path
+
4343 CppCommon::Directory::CreateTree(path);
+
4344
+
4345 if (p->body)
+
4346 {
+
4347 // Check all structs in the package
+
4348 for (const auto& s : p->body->structs)
+
4349 {
+
4350 if (s->body)
+
4351 {
+
4352 // Check all fields in the struct
+
4353 for (const auto& field : s->body->fields)
+
4354 {
+
4355 if (field->array)
+
4356 {
+
4357 if (final)
+
4358 GenerateFBEFinalModelArray(domain, *p->name, (field->optional ? "Optional" : "") + ConvertTypeFieldName(*field->type), ConvertTypeFieldType(domain, *field->type, field->optional), ConvertTypeFieldDeclaration(domain, *field->type, field->optional, final), ((*field->type == "byte") && !field->optional));
+
4359 else
+
4360 GenerateFBEFieldModelArray(domain, *p->name, (field->optional ? "Optional" : "") + ConvertTypeFieldName(*field->type), ConvertTypeFieldType(domain, *field->type, field->optional), ConvertTypeFieldDeclaration(domain, *field->type, field->optional, final), ((*field->type == "byte") && !field->optional));
+
4361 }
+
4362 if (field->vector || field->list || field->set)
+
4363 {
+
4364 if (final)
+
4365 GenerateFBEFinalModelVector(domain, *p->name, (field->optional ? "Optional" : "") + ConvertTypeFieldName(*field->type), ConvertTypeFieldType(domain, *field->type, field->optional), ConvertTypeFieldDeclaration(domain, *field->type, field->optional, final));
+
4366 else
+
4367 GenerateFBEFieldModelVector(domain, *p->name, (field->optional ? "Optional" : "") + ConvertTypeFieldName(*field->type), ConvertTypeFieldType(domain, *field->type, field->optional), ConvertTypeFieldDeclaration(domain, *field->type, field->optional, final));
+
4368 }
+
4369 if (field->map || field->hash)
+
4370 {
+
4371 if (final)
+
4372 GenerateFBEFinalModelMap(domain, *p->name, ConvertTypeFieldName(*field->key), ConvertTypeFieldType(domain, *field->key, false), ConvertTypeFieldDeclaration(domain, *field->key, false, final), (field->optional ? "Optional" : "") + ConvertTypeFieldName(*field->type), ConvertTypeFieldType(domain, *field->type, field->optional), ConvertTypeFieldDeclaration(domain, *field->type, field->optional, final));
+
4373 else
+
4374 GenerateFBEFieldModelMap(domain, *p->name, ConvertTypeFieldName(*field->key), ConvertTypeFieldType(domain, *field->key, false), ConvertTypeFieldDeclaration(domain, *field->key, false, final), (field->optional ? "Optional" : "") + ConvertTypeFieldName(*field->type), ConvertTypeFieldType(domain, *field->type, field->optional), ConvertTypeFieldDeclaration(domain, *field->type, field->optional, final));
+
4375 }
+
4376 if (field->optional)
+
4377 {
+
4378 if (final)
+
4379 GenerateFBEFinalModelOptional(domain, *p->name, ConvertTypeFieldName(*field->type), ConvertTypeFieldType(domain, *field->type, field->optional), ConvertTypeFieldDeclaration(domain, *field->type, false, final));
+
4380 else
+
4381 GenerateFBEFieldModelOptional(domain, *p->name, ConvertTypeFieldName(*field->type), ConvertTypeFieldType(domain, *field->type, field->optional), ConvertTypeFieldDeclaration(domain, *field->type, false, final));
+
4382 }
+
4383 }
+
4384 }
+
4385 }
+
4386 }
+
4387}
+
4388
+
4389void GeneratorJava::GeneratePackage(const std::shared_ptr<Package>& p)
+
4390{
+
4391 std::string domain = (p->domain && !p->domain->empty()) ? (*p->domain + ".") : "";
+
4392 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, *p->name);
+
4393
+
4394 // Create package path
+
4395 CppCommon::Directory::CreateTree(path);
+
4396
+
4397 // Generate namespace
+
4398 if (p->body)
+
4399 {
+
4400 // Generate child enums
+
4401 for (const auto& child_e : p->body->enums)
+
4402 GenerateEnum(p, child_e, path);
+
4403
+
4404 // Generate child flags
+
4405 for (const auto& child_f : p->body->flags)
+
4406 GenerateFlags(p, child_f, path);
+
4407
+
4408 // Generate child structs
+
4409 for (const auto& child_s : p->body->structs)
+
4410 GenerateStruct(p, child_s, path);
+
4411 }
+
4412
+
4413 // Generate containers
+
4414 GenerateContainers(p, false);
+
4415 if (Final())
+
4416 GenerateContainers(p, true);
+
4417
+
4418 // Generate protocol
+
4419 if (Proto())
+
4420 {
+
4421 // Generate protocol version
+
4422 GenerateProtocolVersion(p);
+
4423
+
4424 // Generate sender & receiver
+
4425 GenerateSender(p, false);
+
4426 GenerateReceiver(p, false);
+
4427 GenerateProxy(p, false);
+
4428 if (Final())
+
4429 {
+
4430 GenerateSender(p, true);
+
4431 GenerateReceiver(p, true);
+
4432 }
+
4433 }
+
4434
+
4435 // Generate JSON engine
+
4436 if (JSON())
+
4437 GenerateJson(p);
+
4438}
+
4439
+
4440void GeneratorJava::GenerateEnum(const std::shared_ptr<Package>& p, const std::shared_ptr<EnumType>& e, const CppCommon::Path& path)
+
4441{
+
4442 std::string enum_name = *e->name + "Enum";
+
4443
+
4444 // Generate the output file
+
4445 CppCommon::Path output = path / (enum_name + ".java");
+
4446 WriteBegin();
+
4447
+
4448 // Generate enum header
+
4449 GenerateHeader(CppCommon::Path(_input).filename().string());
+
4450 GenerateImports(p);
+
4451
+
4452 std::string enum_type = (e->base && !e->base->empty()) ? *e->base : "int32";
+
4453 std::string enum_base_type = ConvertEnumType(enum_type);
+
4454 std::string enum_mapping_type = ConvertEnumBase(enum_type);
+
4455
+
4456 // Generate enum body
+
4457 WriteLine();
+
4458 WriteLineIndent("public enum " + enum_name);
+
4459 WriteLineIndent("{");
+
4460 Indent(1);
+
4461 if (e->body)
+
4462 {
+
4463 int index = 0;
+
4464 bool first = true;
+
4465 std::string last = ConvertEnumConstant(enum_type, "0");
+
4466 for (const auto& value : e->body->values)
+
4467 {
+
4468 WriteIndent(std::string(first ? "" : ", ") + *value->name + "(");
+
4469 if (value->value)
+
4470 {
+
4471 if (value->value->constant && !value->value->constant->empty())
+
4472 {
+
4473 index = 0;
+
4474 last = ConvertEnumConstant(enum_type, *value->value->constant);
+
4475 Write(last + " + " + std::to_string(index++));
+
4476 }
+
4477 else if (value->value->reference && !value->value->reference->empty())
+
4478 {
+
4479 index = 0;
+
4480 last = ConvertEnumConstant("", *value->value->reference);
+
4481 Write(last);
+
4482 }
+
4483 }
+
4484 else
+
4485 Write(last + " + " + std::to_string(index++));
+
4486 WriteLine(")");
+
4487 first = false;
+
4488 }
+
4489 WriteLineIndent(";");
+
4490 WriteLine();
+
4491 }
+
4492
+
4493 // Generate enum value
+
4494 WriteLineIndent("private " + enum_base_type + " value;");
+
4495
+
4496 // Generate enum constructors
+
4497 WriteLine();
+
4498 if (enum_base_type != "int")
+
4499 WriteLineIndent(enum_name + "(" + enum_base_type + " value) { this.value = value; }");
+
4500 WriteLineIndent(enum_name + "(int value) { this.value = (" + enum_base_type + ")value; }");
+
4501 WriteLineIndent(enum_name + "(" + enum_name + " value) { this.value = value.value; }");
+
4502
+
4503 // Generate enum getRaw() method
+
4504 WriteLine();
+
4505 WriteLineIndent("public " + enum_base_type + " getRaw() { return value; }");
+
4506
+
4507 // Generate enum mapValue() method
+
4508 WriteLine();
+
4509 WriteLineIndent("public static " + enum_name + " mapValue(" + enum_base_type + " value) { return mapping.get(value); }");
+
4510
+
4511 // Generate enum toString() method
+
4512 WriteLine();
+
4513 WriteLineIndent("@Override");
+
4514 WriteLineIndent("public String toString()");
+
4515 WriteLineIndent("{");
+
4516 Indent(1);
+
4517 if (e->body && !e->body->values.empty())
+
4518 {
+
4519 for (const auto& value : e->body->values)
+
4520 WriteLineIndent("if (this == " + *value->name + ")" + " return \"" + *value->name + "\";");
+
4521 WriteLineIndent("return \"<unknown>\";");
+
4522 }
+
4523 else
+
4524 WriteLineIndent("return \"<empty>\";");
+
4525 Indent(-1);
+
4526 WriteLineIndent("}");
+
4527
+
4528 // Generate enum mapping
+
4529 WriteLine();
+
4530 WriteLineIndent("private static final java.util.Map<" + enum_mapping_type + ", " + enum_name + "> mapping = new java.util.HashMap<>();");
+
4531 WriteLineIndent("static");
+
4532 WriteLineIndent("{");
+
4533 Indent(1);
+
4534 WriteLineIndent("for (var value : " + enum_name + ".values())");
+
4535 Indent(1);
+
4536 WriteLineIndent("mapping.put(value.value, value);");
+
4537 Indent(-1);
+
4538 Indent(-1);
+
4539 WriteLineIndent("}");
+
4540
+
4541 Indent(-1);
+
4542 WriteLineIndent("}");
+
4543
+
4544 // Generate enum footer
+
4545 GenerateFooter();
+
4546
+
4547 // Store the output file
+
4548 WriteEnd();
+
4549 Store(output);
+
4550
+
4551 // Generate enum wrapper class
+
4552 GenerateEnumClass(p, e, path);
+
4553
+
4554 // Generate enum JSON adapter
+
4555 if (JSON())
+
4556 GenerateEnumJson(p, e);
+
4557
+
4558 std::string domain = (p->domain && !p->domain->empty()) ? (*p->domain + ".") : "";
+
4559
+
4560 // Generate enum field model
+
4561 GenerateFBEFieldModelEnumFlags(domain, *p->name, *e->name, enum_type);
+
4562
+
4563 // Generate enum final model
+
4564 if (Final())
+
4565 GenerateFBEFinalModelEnumFlags(domain, *p->name, *e->name, enum_type);
+
4566}
+
4567
+
4568void GeneratorJava::GenerateEnumClass(const std::shared_ptr<Package>& p, const std::shared_ptr<EnumType>& e, const CppCommon::Path& path)
+
4569{
+
4570 std::string enum_name = *e->name;
+
4571 std::string enum_type_name = *e->name + "Enum";
+
4572
+
4573 // Generate the output file
+
4574 CppCommon::Path output = path / (enum_name + ".java");
+
4575 WriteBegin();
+
4576
+
4577 // Generate enum class header
+
4578 GenerateHeader(CppCommon::Path(_input).filename().string());
+
4579 GenerateImports(p);
+
4580
+
4581 std::string enum_type = (e->base && !e->base->empty()) ? *e->base : "int32";
+
4582 std::string enum_base_type = ConvertEnumType(enum_type);
+
4583
+
4584 // Generate enum class body
+
4585 WriteLine();
+
4586 WriteLineIndent("public final class " + enum_name + " implements Comparable<" + enum_name + ">");
+
4587 WriteLineIndent("{");
+
4588 Indent(1);
+
4589 if (e->body)
+
4590 {
+
4591 for (const auto& value : e->body->values)
+
4592 WriteLineIndent("public static final " + enum_name + " " + *value->name + " = new " + enum_name + "(" + enum_type_name + "." + *value->name + ");");
+
4593 WriteLine();
+
4594 }
+
4595
+
4596 // Generate enum class value
+
4597 WriteLineIndent("private " + enum_type_name + " value = " + enum_type_name + ".values()[0];");
+
4598
+
4599 // Generate enum class constructors
+
4600 WriteLine();
+
4601 WriteLineIndent("public " + enum_name + "() {}");
+
4602 WriteLineIndent("public " + enum_name + "(" + enum_base_type + " value) { setEnum(value); }");
+
4603 WriteLineIndent("public " + enum_name + "(" + enum_type_name + " value) { setEnum(value); }");
+
4604 WriteLineIndent("public " + enum_name + "(" + enum_name + " value) { setEnum(value); }");
+
4605
+
4606 // Generate enum class getEnum() and getRaw() methods
+
4607 WriteLine();
+
4608 WriteLineIndent("public " + enum_type_name + " getEnum() { return value; }");
+
4609 WriteLineIndent("public " + enum_base_type + " getRaw() { return value.getRaw(); }");
+
4610
+
4611 // Generate enum class setDefault() method
+
4612 WriteLine();
+
4613 WriteLineIndent("public void setDefault() { setEnum((" + enum_base_type + ")0); }");
+
4614
+
4615 // Generate enum class setEnum() methods
+
4616 WriteLine();
+
4617 WriteLineIndent("public void setEnum(" + enum_base_type + " value) { this.value = " + enum_type_name + ".mapValue(value); }");
+
4618 WriteLineIndent("public void setEnum(" + enum_type_name + " value) { this.value = value; }");
+
4619 WriteLineIndent("public void setEnum(" + enum_name + " value) { this.value = value.value; }");
+
4620
+
4621 // Generate enum class compareTo() method
+
4622 WriteLine();
+
4623 WriteLineIndent("@Override");
+
4624 WriteLineIndent("public int compareTo(" + enum_name + " other)");
+
4625 WriteLineIndent("{");
+
4626 Indent(1);
+
4627 WriteLineIndent("if (value == null)");
+
4628 Indent(1);
+
4629 WriteLineIndent("return -1;");
+
4630 Indent(-1);
+
4631 WriteLineIndent("if (other.value == null)");
+
4632 Indent(1);
+
4633 WriteLineIndent("return 1;");
+
4634 Indent(-1);
+
4635 WriteLineIndent("return (int)(value.getRaw() - other.value.getRaw());");
+
4636 Indent(-1);
+
4637 WriteLineIndent("}");
+
4638
+
4639 // Generate enum class equals() method
+
4640 WriteLine();
+
4641 WriteLineIndent("@Override");
+
4642 WriteLineIndent("public boolean equals(Object other)");
+
4643 WriteLineIndent("{");
+
4644 Indent(1);
+
4645 WriteLineIndent("if (other == null)");
+
4646 Indent(1);
+
4647 WriteLineIndent("return false;");
+
4648 Indent(-1);
+
4649 WriteLine();
+
4650 WriteLineIndent("if (!" + enum_name + ".class.isAssignableFrom(other.getClass()))");
+
4651 Indent(1);
+
4652 WriteLineIndent("return false;");
+
4653 Indent(-1);
+
4654 WriteLine();
+
4655 WriteLineIndent("final " + enum_name + " enm = (" + enum_name + ")other;");
+
4656 WriteLine();
+
4657 WriteLineIndent("if ((value == null) || (enm.value == null))");
+
4658 Indent(1);
+
4659 WriteLineIndent("return false;");
+
4660 Indent(-1);
+
4661 WriteLineIndent("if (value.getRaw() != enm.value.getRaw())");
+
4662 Indent(1);
+
4663 WriteLineIndent("return false;");
+
4664 Indent(-1);
+
4665 WriteLineIndent("return true;");
+
4666 Indent(-1);
+
4667 WriteLineIndent("}");
+
4668
+
4669 // Generate enum class hashCode() method
+
4670 WriteLine();
+
4671 WriteLineIndent("@Override");
+
4672 WriteLineIndent("public int hashCode()");
+
4673 WriteLineIndent("{");
+
4674 Indent(1);
+
4675 WriteLineIndent("int hash = 17;");
+
4676 WriteLineIndent("hash = hash * 31 + ((value != null) ? value.hashCode() : 0);");
+
4677 WriteLineIndent("return hash;");
+
4678 Indent(-1);
+
4679 WriteLineIndent("}");
+
4680
+
4681 // Generate enum class toString() method
+
4682 WriteLine();
+
4683 WriteLineIndent("@Override");
+
4684 WriteLineIndent("public String toString() { return (value != null) ? value.toString() : \"<unknown>\"; }");
+
4685
+
4686 Indent(-1);
+
4687 WriteLineIndent("}");
+
4688
+
4689 // Generate enum class footer
+
4690 GenerateFooter();
+
4691
+
4692 // Store the output file
+
4693 WriteEnd();
+
4694 Store(output);
+
4695}
+
4696
+
4697void GeneratorJava::GenerateEnumJson(const std::shared_ptr<Package>& p, const std::shared_ptr<EnumType>& e)
+
4698{
+
4699 std::string domain = (p->domain && !p->domain->empty()) ? (*p->domain + ".") : "";
+
4700 std::string package = *p->name;
+
4701 std::string enum_name = domain + package + "." + *e->name;
+
4702 std::string adapter_name = *e->name + "Json";
+
4703
+
4704 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "fbe";
+
4705
+
4706 // Create package path
+
4707 CppCommon::Directory::CreateTree(path);
+
4708
+
4709 // Generate the output file
+
4710 CppCommon::Path output = path / (adapter_name + ".java");
+
4711 WriteBegin();
+
4712
+
4713 // Generate headers
+
4714 GenerateHeader(CppCommon::Path(_input).filename().string());
+
4715 GenerateImports(domain, package + ".fbe;");
+
4716
+
4717 std::string enum_type = (e->base && !e->base->empty()) ? *e->base : "int32";
+
4718
+
4719 // Generate JSON adapter body
+
4720 WriteLine();
+
4721 WriteLineIndent("public final class " + adapter_name + " implements com.google.gson.JsonSerializer<" + enum_name + ">, com.google.gson.JsonDeserializer<" + enum_name + ">");
+
4722 WriteLineIndent("{");
+
4723 Indent(1);
+
4724
+
4725 // Generate JSON adapter serialize() method
+
4726 WriteLineIndent("@Override");
+
4727 WriteLineIndent("public com.google.gson.JsonElement serialize(" + enum_name + " src, java.lang.reflect.Type typeOfSrc, com.google.gson.JsonSerializationContext context)");
+
4728 WriteLineIndent("{");
+
4729 Indent(1);
+
4730 WriteLineIndent("return new com.google.gson.JsonPrimitive(src.getRaw());");
+
4731 Indent(-1);
+
4732 WriteLineIndent("}");
+
4733
+
4734 // Generate JSON adapter deserialize() method
+
4735 WriteLine();
+
4736 WriteLineIndent("@Override");
+
4737 WriteLineIndent("public " + enum_name + " deserialize(com.google.gson.JsonElement json, java.lang.reflect.Type type, com.google.gson.JsonDeserializationContext context) throws com.google.gson.JsonParseException");
+
4738 WriteLineIndent("{");
+
4739 Indent(1);
+
4740 WriteLineIndent("return new " + enum_name + "(json.getAsJsonPrimitive()." + ConvertEnumGet(enum_type) + "());");
+
4741 Indent(-1);
+
4742 WriteLineIndent("}");
+
4743
+
4744 Indent(-1);
+
4745 WriteLineIndent("}");
+
4746
+
4747 // Generate JSON adapter footer
+
4748 GenerateFooter();
+
4749
+
4750 // Store the output file
+
4751 WriteEnd();
+
4752 Store(output);
+
4753}
+
4754
+
4755void GeneratorJava::GenerateFlags(const std::shared_ptr<Package>& p, const std::shared_ptr<FlagsType>& f, const CppCommon::Path& path)
+
4756{
+
4757 std::string flags_name = *f->name + "Enum";
+
4758
+
4759 // Generate the output file
+
4760 CppCommon::Path output = path / (flags_name + ".java");
+
4761 WriteBegin();
+
4762
+
4763 // Generate flags header
+
4764 GenerateHeader(CppCommon::Path(_input).filename().string());
+
4765 GenerateImports(p);
+
4766
+
4767 std::string flags_type = (f->base && !f->base->empty()) ? *f->base : "int32";
+
4768 std::string flags_base_type = ConvertEnumType(flags_type);
+
4769 std::string flags_mapping_type = ConvertEnumBase(flags_type);
+
4770
+
4771 // Generate flags body
+
4772 WriteLine();
+
4773 WriteLineIndent("public enum " + flags_name);
+
4774 WriteLineIndent("{");
+
4775 Indent(1);
+
4776 if (f->body)
+
4777 {
+
4778 bool first = true;
+
4779 for (const auto& value : f->body->values)
+
4780 {
+
4781 WriteIndent(std::string(first ? "" : ", ") + *value->name + "(");
+
4782 if (value->value)
+
4783 {
+
4784 if (value->value->constant && !value->value->constant->empty())
+
4785 Write(ConvertEnumConstant(flags_type, *value->value->constant));
+
4786 else if (value->value->reference && !value->value->reference->empty())
+
4787 Write(ConvertEnumConstant("", *value->value->reference));
+
4788 }
+
4789 WriteLine(")");
+
4790 first = false;
+
4791 }
+
4792 WriteLineIndent(";");
+
4793 WriteLine();
+
4794 }
+
4795 else
+
4796 WriteIndent("unknown(0);");
+
4797
+
4798 // Generate flags class value
+
4799 WriteLineIndent("private " + flags_base_type + " value;");
+
4800
+
4801 // Generate flags class constructors
+
4802 WriteLine();
+
4803 if (flags_base_type != "int")
+
4804 WriteLineIndent(flags_name + "(" + flags_base_type + " value) { this.value = value; }");
+
4805 WriteLineIndent(flags_name + "(int value) { this.value = (" + flags_base_type + ")value; }");
+
4806 WriteLineIndent(flags_name + "(" + flags_name + " value) { this.value = value.value; }");
+
4807
+
4808 // Generate flags getRaw() method
+
4809 WriteLine();
+
4810 WriteLineIndent("public " + flags_base_type + " getRaw() { return value; }");
+
4811
+
4812 // Generate flags mapValue() method
+
4813 WriteLine();
+
4814 WriteLineIndent("public static " + flags_name + " mapValue(" + flags_base_type + " value) { return mapping.get(value); }");
+
4815
+
4816 // Generate flags hasFlags() methods
+
4817 WriteLine();
+
4818 WriteLineIndent("public boolean hasFlags(" + flags_base_type + " flags) { return (((value & flags) != 0) && ((value & flags) == flags)); }");
+
4819 WriteLineIndent("public boolean hasFlags(" + flags_name + " flags) { return hasFlags(flags.value); }");
+
4820
+
4821 // Generate flags getAllSet(), getNoneSet(), getCurrentSet() methods
+
4822 WriteLine();
+
4823 WriteLineIndent("public java.util.EnumSet<" + flags_name + "> getAllSet() { return java.util.EnumSet.allOf(" + flags_name + ".class); }");
+
4824 WriteLineIndent("public java.util.EnumSet<" + flags_name + "> getNoneSet() { return java.util.EnumSet.noneOf(" + flags_name + ".class); }");
+
4825 WriteLineIndent("public java.util.EnumSet<" + flags_name + "> getCurrentSet()");
+
4826 WriteLineIndent("{");
+
4827 Indent(1);
+
4828 WriteLineIndent("java.util.EnumSet<" + flags_name + "> result = java.util.EnumSet.noneOf(" + flags_name + ".class);");
+
4829 if (f->body)
+
4830 {
+
4831 for (const auto& value : f->body->values)
+
4832 {
+
4833 WriteLineIndent("if ((value & " + *value->name + ".getRaw()) != 0)");
+
4834 WriteLineIndent("{");
+
4835 Indent(1);
+
4836 WriteLineIndent("result.add(" + *value->name + ");");
+
4837 Indent(-1);
+
4838 WriteLineIndent("}");
+
4839 }
+
4840 }
+
4841 WriteLineIndent("return result;");
+
4842 Indent(-1);
+
4843 WriteLineIndent("}");
+
4844
+
4845 // Generate flags toString() method
+
4846 WriteLine();
+
4847 WriteLineIndent("@Override");
+
4848 WriteLineIndent("public String toString()");
+
4849 WriteLineIndent("{");
+
4850 Indent(1);
+
4851 WriteLineIndent("var sb = new StringBuilder();");
+
4852 if (f->body && !f->body->values.empty())
+
4853 {
+
4854 WriteLineIndent("boolean first = true;");
+
4855 for (const auto& value : f->body->values)
+
4856 {
+
4857 WriteLineIndent("if (hasFlags(" + *value->name + "))");
+
4858 WriteLineIndent("{");
+
4859 Indent(1);
+
4860 WriteLineIndent("sb.append(first ? \"\" : \"|\").append(\"" + *value->name + "\");");
+
4861 WriteLineIndent("first = false;");
+
4862 Indent(-1);
+
4863 WriteLineIndent("}");
+
4864 }
+
4865 }
+
4866 WriteLineIndent("return sb.toString();");
+
4867 Indent(-1);
+
4868 WriteLineIndent("}");
+
4869
+
4870 // Generate flags mapping
+
4871 WriteLine();
+
4872 WriteLineIndent("private static final java.util.Map<" + flags_mapping_type + ", " + flags_name + "> mapping = new java.util.HashMap<>();");
+
4873 WriteLineIndent("static");
+
4874 WriteLineIndent("{");
+
4875 Indent(1);
+
4876 WriteLineIndent("for (var value : " + flags_name + ".values())");
+
4877 Indent(1);
+
4878 WriteLineIndent("mapping.put(value.value, value);");
+
4879 Indent(-1);
+
4880 Indent(-1);
+
4881 WriteLineIndent("}");
+
4882
+
4883 Indent(-1);
+
4884 WriteLineIndent("}");
+
4885
+
4886 // Generate flags footer
+
4887 GenerateFooter();
+
4888
+
4889 // Store the output file
+
4890 WriteEnd();
+
4891 Store(output);
+
4892
+
4893 // Generate flags wrapper class
+
4894 GenerateFlagsClass(p, f, path);
+
4895
+
4896 // Generate flags JSON adapter
+
4897 if (JSON())
+
4898 GenerateFlagsJson(p, f);
+
4899
+
4900 std::string domain = (p->domain && !p->domain->empty()) ? (*p->domain + ".") : "";
+
4901
+
4902 // Generate flags field model
+
4903 GenerateFBEFieldModelEnumFlags(domain, *p->name, *f->name, flags_type);
+
4904
+
4905 // Generate flags final model
+
4906 if (Final())
+
4907 GenerateFBEFinalModelEnumFlags(domain, *p->name, *f->name, flags_type);
+
4908}
+
4909
+
4910void GeneratorJava::GenerateFlagsClass(const std::shared_ptr<Package>& p, const std::shared_ptr<FlagsType>& f, const CppCommon::Path& path)
+
4911{
+
4912 std::string flags_name = *f->name;
+
4913 std::string flags_type_name = *f->name + "Enum";
+
4914
+
4915 // Generate the output file
+
4916 CppCommon::Path output = path / (flags_name + ".java");
+
4917 WriteBegin();
+
4918
+
4919 // Generate flags class header
+
4920 GenerateHeader(CppCommon::Path(_input).filename().string());
+
4921 GenerateImports(p);
+
4922
+
4923 std::string flags_type = (f->base && !f->base->empty()) ? *f->base : "int32";
+
4924 std::string flags_base_type = ConvertEnumType(flags_type);
+
4925
+
4926 // Generate flags class body
+
4927 WriteLine();
+
4928 WriteLineIndent("public final class " + flags_name + " implements Comparable<" + flags_name + ">");
+
4929 WriteLineIndent("{");
+
4930 Indent(1);
+
4931 if (f->body)
+
4932 {
+
4933 for (const auto& value : f->body->values)
+
4934 WriteLineIndent("public static final " + flags_name + " " + *value->name + " = new " + flags_name + "(" + flags_type_name + "." + *value->name + ");");
+
4935 WriteLine();
+
4936 }
+
4937
+
4938 // Generate flags class value and flags
+
4939 WriteLineIndent("private " + flags_type_name + " value = " + flags_type_name + ".values()[0];");
+
4940 WriteLineIndent("private " + flags_base_type + " flags = value.getRaw();");
+
4941
+
4942 // Generate flags class constructors
+
4943 WriteLine();
+
4944 WriteLineIndent("public " + flags_name + "() {}");
+
4945 WriteLineIndent("public " + flags_name + "(" + flags_base_type + " value) { setEnum(value); }");
+
4946 WriteLineIndent("public " + flags_name + "(" + flags_type_name + " value) { setEnum(value); }");
+
4947 WriteLineIndent("public " + flags_name + "(java.util.EnumSet<" + flags_type_name + "> value) { setEnum(value); }");
+
4948 WriteLineIndent("public " + flags_name + "(" + flags_name + " value) { setEnum(value); }");
+
4949
+
4950 // Generate flags class getEnum() and getRaw() methods
+
4951 WriteLine();
+
4952 WriteLineIndent("public " + flags_type_name + " getEnum() { return value; }");
+
4953 WriteLineIndent("public " + flags_base_type + " getRaw() { return flags; }");
+
4954
+
4955 // Generate flags class setDefault() method
+
4956 WriteLine();
+
4957 WriteLineIndent("public void setDefault() { setEnum((" + flags_base_type + ")0); }");
+
4958
+
4959 // Generate flags class setEnum() methods
+
4960 WriteLine();
+
4961 WriteLineIndent("public void setEnum(" + flags_base_type + " value) { this.flags = value; this.value = " + flags_type_name + ".mapValue(value); }");
+
4962 WriteLineIndent("public void setEnum(" + flags_type_name + " value) { this.value = value; this.flags = value.getRaw(); }");
+
4963 WriteLineIndent("public void setEnum(java.util.EnumSet<" + flags_type_name + "> value) { setEnum(" + flags_name + ".fromSet(value)); }");
+
4964 WriteLineIndent("public void setEnum(" + flags_name + " value) { this.value = value.value; this.flags = value.flags; }");
+
4965
+
4966 // Generate flags class hasFlags() methods
+
4967 WriteLine();
+
4968 WriteLineIndent("public boolean hasFlags(" + flags_base_type + " flags) { return (((this.flags & flags) != 0) && ((this.flags & flags) == flags)); }");
+
4969 WriteLineIndent("public boolean hasFlags(" + flags_type_name + " flags) { return hasFlags(flags.getRaw()); }");
+
4970 WriteLineIndent("public boolean hasFlags(" + flags_name + " flags) { return hasFlags(flags.flags); }");
+
4971
+
4972 // Generate flags class setFlags() methods
+
4973 WriteLine();
+
4974 WriteLineIndent("public " + flags_name + " setFlags(" + flags_base_type + " flags) { setEnum((" + flags_base_type + ")(this.flags | flags)); return this; }");
+
4975 WriteLineIndent("public " + flags_name + " setFlags(" + flags_type_name + " flags) { setFlags(flags.getRaw()); return this; }");
+
4976 WriteLineIndent("public " + flags_name + " setFlags(" + flags_name + " flags) { setFlags(flags.flags); return this; }");
+
4977
+
4978 // Generate flags class removeFlags() methods
+
4979 WriteLine();
+
4980 WriteLineIndent("public " + flags_name + " removeFlags(" + flags_base_type + " flags) { setEnum((" + flags_base_type + ")(this.flags & ~flags)); return this; }");
+
4981 WriteLineIndent("public " + flags_name + " removeFlags(" + flags_type_name + " flags) { removeFlags(flags.getRaw()); return this; }");
+
4982 WriteLineIndent("public " + flags_name + " removeFlags(" + flags_name + " flags) { removeFlags(flags.flags); return this; }");
+
4983
+
4984 // Generate flags class getAllSet(), getNoneSet() and getCurrentSet() methods
+
4985 WriteLine();
+
4986 WriteLineIndent("public java.util.EnumSet<" + flags_type_name + "> getAllSet() { return value.getAllSet(); }");
+
4987 WriteLineIndent("public java.util.EnumSet<" + flags_type_name + "> getNoneSet() { return value.getNoneSet(); }");
+
4988 WriteLineIndent("public java.util.EnumSet<" + flags_type_name + "> getCurrentSet() { return value.getCurrentSet(); }");
+
4989
+
4990 // Generate flags class fromSet() method
+
4991 WriteLine();
+
4992 WriteLineIndent("public static " + flags_name + " fromSet(java.util.EnumSet<" + flags_type_name + "> set)");
+
4993 WriteLineIndent("{");
+
4994 Indent(1);
+
4995 WriteLineIndent(flags_base_type + " result = 0;");
+
4996 if (f->body)
+
4997 {
+
4998 for (const auto& value : f->body->values)
+
4999 {
+
5000 WriteLineIndent("if (set.contains(" + *value->name + ".getEnum()))");
+
5001 WriteLineIndent("{");
+
5002 Indent(1);
+
5003 WriteLineIndent("result |= " + *value->name + ".flags;");
+
5004 Indent(-1);
+
5005 WriteLineIndent("}");
+
5006 }
+
5007 }
+
5008 WriteLineIndent("return new " + flags_name + "(result);");
+
5009 Indent(-1);
+
5010 WriteLineIndent("}");
+
5011
+
5012 // Generate flags class compareTo() method
+
5013 WriteLine();
+
5014 WriteLineIndent("@Override");
+
5015 WriteLineIndent("public int compareTo(" + flags_name + " other)");
+
5016 WriteLineIndent("{");
+
5017 Indent(1);
+
5018 WriteLineIndent("return (int)(flags - other.flags);");
+
5019 Indent(-1);
+
5020 WriteLineIndent("}");
+
5021
+
5022 // Generate flags class equals() method
+
5023 WriteLine();
+
5024 WriteLineIndent("@Override");
+
5025 WriteLineIndent("public boolean equals(Object other)");
+
5026 WriteLineIndent("{");
+
5027 Indent(1);
+
5028 WriteLineIndent("if (other == null)");
+
5029 Indent(1);
+
5030 WriteLineIndent("return false;");
+
5031 Indent(-1);
+
5032 WriteLine();
+
5033 WriteLineIndent("if (!" + flags_name + ".class.isAssignableFrom(other.getClass()))");
+
5034 Indent(1);
+
5035 WriteLineIndent("return false;");
+
5036 Indent(-1);
+
5037 WriteLine();
+
5038 WriteLineIndent("final " + flags_name + " flg = (" + flags_name + ")other;");
+
5039 WriteLine();
+
5040 WriteLineIndent("if (flags != flg.flags)");
+
5041 Indent(1);
+
5042 WriteLineIndent("return false;");
+
5043 Indent(-1);
+
5044 WriteLineIndent("return true;");
+
5045 Indent(-1);
+
5046 WriteLineIndent("}");
+
5047
+
5048 // Generate flags class hashCode() method
+
5049 WriteLine();
+
5050 WriteLineIndent("@Override");
+
5051 WriteLineIndent("public int hashCode()");
+
5052 WriteLineIndent("{");
+
5053 Indent(1);
+
5054 WriteLineIndent("int hash = 17;");
+
5055 WriteLineIndent("hash = hash * 31 + (int)flags;");
+
5056 WriteLineIndent("return hash;");
+
5057 Indent(-1);
+
5058 WriteLineIndent("}");
+
5059
+
5060 // Generate flags class toString() method
+
5061 WriteLine();
+
5062 WriteLineIndent("@Override");
+
5063 WriteLineIndent("public String toString()");
+
5064 WriteLineIndent("{");
+
5065 Indent(1);
+
5066 WriteLineIndent("var sb = new StringBuilder();");
+
5067 WriteLineIndent("boolean first = true;");
+
5068 if (f->body)
+
5069 {
+
5070 for (const auto& value : f->body->values)
+
5071 {
+
5072 WriteLineIndent("if (hasFlags(" + *value->name + ".flags))");
+
5073 WriteLineIndent("{");
+
5074 Indent(1);
+
5075 WriteLineIndent("sb.append(first ? \"\" : \"|\").append(\"" + *value->name + "\");");
+
5076 WriteLineIndent("first = false;");
+
5077 Indent(-1);
+
5078 WriteLineIndent("}");
+
5079 }
+
5080 }
+
5081 WriteLineIndent("return sb.toString();");
+
5082 Indent(-1);
+
5083 WriteLineIndent("}");
+
5084
+
5085 Indent(-1);
+
5086 WriteLineIndent("}");
+
5087
+
5088 // Generate flags class footer
+
5089 GenerateFooter();
+
5090
+
5091 // Store the output file
+
5092 WriteEnd();
+
5093 Store(output);
+
5094}
+
5095
+
5096void GeneratorJava::GenerateFlagsJson(const std::shared_ptr<Package>& p, const std::shared_ptr<FlagsType>& f)
+
5097{
+
5098 std::string domain = (p->domain && !p->domain->empty()) ? (*p->domain + ".") : "";
+
5099 std::string package = *p->name;
+
5100 std::string flags_name = domain + package + "." + *f->name;
+
5101 std::string adapter_name = *f->name + "Json";
+
5102
+
5103 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "fbe";
+
5104
+
5105 // Create package path
+
5106 CppCommon::Directory::CreateTree(path);
+
5107
+
5108 // Generate the output file
+
5109 CppCommon::Path output = path / (adapter_name + ".java");
+
5110 WriteBegin();
+
5111
+
5112 // Generate headers
+
5113 GenerateHeader(CppCommon::Path(_input).filename().string());
+
5114 GenerateImports(domain, package + ".fbe;");
+
5115
+
5116 std::string flags_type = (f->base && !f->base->empty()) ? *f->base : "int32";
+
5117
+
5118 // Generate JSON adapter body
+
5119 WriteLine();
+
5120 WriteLineIndent("public final class " + adapter_name + " implements com.google.gson.JsonSerializer<" + flags_name + ">, com.google.gson.JsonDeserializer<" + flags_name + ">");
+
5121 WriteLineIndent("{");
+
5122 Indent(1);
+
5123
+
5124 // Generate JSON adapter serialize() method
+
5125 WriteLine();
+
5126 WriteLineIndent("@Override");
+
5127 WriteLineIndent("public com.google.gson.JsonElement serialize(" + flags_name + " src, java.lang.reflect.Type typeOfSrc, com.google.gson.JsonSerializationContext context)");
+
5128 WriteLineIndent("{");
+
5129 Indent(1);
+
5130 WriteLineIndent("return new com.google.gson.JsonPrimitive(src.getRaw());");
+
5131 Indent(-1);
+
5132 WriteLineIndent("}");
+
5133
+
5134 // Generate JSON adapter deserialize() method
+
5135 WriteLine();
+
5136 WriteLineIndent("@Override");
+
5137 WriteLineIndent("public " + flags_name + " deserialize(com.google.gson.JsonElement json, java.lang.reflect.Type type, com.google.gson.JsonDeserializationContext context) throws com.google.gson.JsonParseException");
+
5138 WriteLineIndent("{");
+
5139 Indent(1);
+
5140 WriteLineIndent("return new " + flags_name + "(json.getAsJsonPrimitive()." + ConvertEnumGet(flags_type) + "());");
+
5141 Indent(-1);
+
5142 WriteLineIndent("}");
+
5143
+
5144 Indent(-1);
+
5145 WriteLineIndent("}");
+
5146
+
5147 // Generate JSON adapter footer
+
5148 GenerateFooter();
+
5149
+
5150 // Store the output file
+
5151 WriteEnd();
+
5152 Store(output);
+
5153}
+
5154
+
5155void GeneratorJava::GenerateStruct(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s, const CppCommon::Path& path)
+
5156{
+
5157 std::string domain = (p->domain && !p->domain->empty()) ? (*p->domain + ".") : "";
+
5158 bool first;
+
5159
+
5160 // Generate the output file
+
5161 CppCommon::Path output = path / (*s->name + ".java");
+
5162 WriteBegin();
+
5163
+
5164 // Generate struct header
+
5165 GenerateHeader(CppCommon::Path(_input).filename().string());
+
5166 GenerateImports(p);
+
5167
+
5168 // Generate struct begin
+
5169 WriteLine();
+
5170 WriteIndent("public class " + *s->name);
+
5171 if (s->base && !s->base->empty())
+
5172 Write(" extends " + ConvertTypeName(domain, "", *s->base, false));
+
5173 else
+
5174 Write(" implements Comparable<Object>");
+
5175 WriteLine();
+
5176 WriteLineIndent("{");
+
5177 Indent(1);
+
5178
+
5179 // Generate struct body
+
5180 if (s->body && !s->body->fields.empty())
+
5181 {
+
5182 for (const auto& field : s->body->fields)
+
5183 WriteLineIndent("public " + ConvertTypeName(domain, "", *field) + " " + *field->name + " = " + ConvertDefault(domain, "", *field) + ";");
+
5184 WriteLine();
+
5185 }
+
5186
+
5187 // Generate struct FBE type property
+
5188 if (s->base && !s->base->empty() && (s->type == 0))
+
5189 WriteLineIndent("public static final long fbeTypeConst = " + ConvertTypeName(domain, "", *s->base, false) + ".fbeTypeConst;");
+
5190 else
+
5191 WriteLineIndent("public static final long fbeTypeConst = " + std::to_string(s->type) + ";");
+
5192 WriteLineIndent("public long fbeType() { return fbeTypeConst; }");
+
5193
+
5194 // Generate struct default constructor
+
5195 WriteLine();
+
5196 WriteLineIndent("public " + *s->name + "() {}");
+
5197
+
5198 // Generate struct initialization constructor
+
5199 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
5200 {
+
5201 first = true;
+
5202 WriteLine();
+
5203 WriteIndent("public " + *s->name + "(");
+
5204 if (s->base && !s->base->empty())
+
5205 {
+
5206 Write(ConvertTypeName(domain, "", *s->base, false) + " parent");
+
5207 first = false;
+
5208 }
+
5209 if (s->body)
+
5210 {
+
5211 for (const auto& field : s->body->fields)
+
5212 {
+
5213 Write(std::string(first ? "" : ", ") + ConvertTypeName(domain, "", *field) + " " + *field->name);
+
5214 first = false;
+
5215 }
+
5216 }
+
5217 WriteLine(")");
+
5218 WriteLineIndent("{");
+
5219 Indent(1);
+
5220 if (s->base && !s->base->empty())
+
5221 WriteLineIndent("super(parent);");
+
5222 if (s->body)
+
5223 for (const auto& field : s->body->fields)
+
5224 WriteLineIndent("this." + *field->name + " = " + *field->name + ";");
+
5225 Indent(-1);
+
5226 WriteLineIndent("}");
+
5227 }
+
5228
+
5229 // Generate struct copy constructor
+
5230 WriteLine();
+
5231 WriteLineIndent("public " + *s->name + "(" + *s->name +" other)");
+
5232 WriteLineIndent("{");
+
5233 Indent(1);
+
5234 if (s->base && !s->base->empty())
+
5235 WriteLineIndent("super(other);");
+
5236 if (s->body)
+
5237 for (const auto& field : s->body->fields)
+
5238 WriteLineIndent("this." + *field->name + " = other." + *field->name + ";");
+
5239 Indent(-1);
+
5240 WriteLineIndent("}");
+
5241
+
5242 // Generate struct clone() method
+
5243 WriteLine();
+
5244 WriteLineIndent("public " + *s->name + " clone()");
+
5245 WriteLineIndent("{");
+
5246 Indent(1);
+
5247 WriteLineIndent("// Serialize the struct to the FBE stream");
+
5248 WriteLineIndent("var writer = new " + domain + *p->name + ".fbe." + *s->name + "Model();");
+
5249 WriteLineIndent("writer.serialize(this);");
+
5250 WriteLine();
+
5251 WriteLineIndent("// Deserialize the struct from the FBE stream");
+
5252 WriteLineIndent("var reader = new " + domain + *p->name + ".fbe." + *s->name + "Model();");
+
5253 WriteLineIndent("reader.attach(writer.getBuffer());");
+
5254 WriteLineIndent("return reader.deserialize();");
+
5255 Indent(-1);
+
5256 WriteLineIndent("}");
+
5257
+
5258 // Generate struct compareTo() method
+
5259 WriteLine();
+
5260 WriteLineIndent("@Override");
+
5261 WriteLineIndent("public int compareTo(Object other)");
+
5262 WriteLineIndent("{");
+
5263 Indent(1);
+
5264 WriteLineIndent("if (other == null)");
+
5265 Indent(1);
+
5266 WriteLineIndent("return -1;");
+
5267 Indent(-1);
+
5268 WriteLine();
+
5269 WriteLineIndent("if (!" + *s->name + ".class.isAssignableFrom(other.getClass()))");
+
5270 Indent(1);
+
5271 WriteLineIndent("return -1;");
+
5272 Indent(-1);
+
5273 WriteLine();
+
5274 WriteLineIndent("final " + *s->name + " obj = (" + *s->name + ")other;");
+
5275 WriteLine();
+
5276 WriteLineIndent("int result = 0;");
+
5277 if (s->base && !s->base->empty())
+
5278 {
+
5279 WriteLineIndent("result = super.compareTo(obj);");
+
5280 WriteLineIndent("if (result != 0)");
+
5281 Indent(1);
+
5282 WriteLineIndent("return result;");
+
5283 Indent(-1);
+
5284 }
+
5285 if (s->body)
+
5286 {
+
5287 for (const auto& field : s->body->fields)
+
5288 {
+
5289 if (field->keys)
+
5290 {
+
5291 if (IsPrimitiveType(*field->type, field->optional))
+
5292 WriteLineIndent("result = " + ConvertPrimitiveTypeName(*field->type) + ".compare(" + *field->name + ", obj." + *field->name + ");");
+
5293 else
+
5294 WriteLineIndent("result = " + *field->name + ".compareTo(obj." + *field->name + ");");
+
5295 WriteLineIndent("if (result != 0)");
+
5296 Indent(1);
+
5297 WriteLineIndent("return result;");
+
5298 Indent(-1);
+
5299 }
+
5300 }
+
5301 }
+
5302 WriteLineIndent("return result;");
+
5303 Indent(-1);
+
5304 WriteLineIndent("}");
+
5305
+
5306 // Generate struct equals() method
+
5307 WriteLine();
+
5308 WriteLineIndent("@Override");
+
5309 WriteLineIndent("public boolean equals(Object other)");
+
5310 WriteLineIndent("{");
+
5311 Indent(1);
+
5312 WriteLineIndent("if (other == null)");
+
5313 Indent(1);
+
5314 WriteLineIndent("return false;");
+
5315 Indent(-1);
+
5316 WriteLine();
+
5317 WriteLineIndent("if (!" + *s->name + ".class.isAssignableFrom(other.getClass()))");
+
5318 Indent(1);
+
5319 WriteLineIndent("return false;");
+
5320 Indent(-1);
+
5321 WriteLine();
+
5322 WriteLineIndent("final " + *s->name + " obj = (" + *s->name + ")other;");
+
5323 WriteLine();
+
5324 if (s->base && !s->base->empty())
+
5325 {
+
5326 WriteLineIndent("if (!super.equals(obj))");
+
5327 Indent(1);
+
5328 WriteLineIndent("return false;");
+
5329 Indent(-1);
+
5330 }
+
5331 if (s->body)
+
5332 {
+
5333 for (const auto& field : s->body->fields)
+
5334 {
+
5335 if (field->keys)
+
5336 {
+
5337 if (IsPrimitiveType(*field->type, field->optional))
+
5338 WriteLineIndent("if (" + *field->name + " != obj." + *field->name + ")");
+
5339 else
+
5340 WriteLineIndent("if (!" + *field->name + ".equals(obj." + *field->name + "))");
+
5341 Indent(1);
+
5342 WriteLineIndent("return false;");
+
5343 Indent(-1);
+
5344 }
+
5345 }
+
5346 }
+
5347 WriteLineIndent("return true;");
+
5348 Indent(-1);
+
5349 WriteLineIndent("}");
+
5350
+
5351 // Generate struct hashCode() method
+
5352 WriteLine();
+
5353 WriteLineIndent("@Override");
+
5354 WriteLineIndent("public int hashCode()");
+
5355 WriteLineIndent("{");
+
5356 Indent(1);
+
5357 WriteLineIndent("int hash = 17;");
+
5358 if (s->base && !s->base->empty())
+
5359 WriteLineIndent("hash = hash * 31 + super.hashCode();");
+
5360 if (s->body)
+
5361 {
+
5362 for (const auto& field : s->body->fields)
+
5363 {
+
5364 if (field->keys)
+
5365 {
+
5366 if (IsPrimitiveType(*field->type, field->optional))
+
5367 WriteLineIndent("hash = hash * 31 + " + ConvertPrimitiveTypeName(*field->type) + ".hashCode(" + *field->name + ");");
+
5368 else
+
5369 WriteLineIndent("hash = hash * 31 + " + *field->name + ".hashCode();");
+
5370 }
+
5371 }
+
5372 }
+
5373 WriteLineIndent("return hash;");
+
5374 Indent(-1);
+
5375 WriteLineIndent("}");
+
5376
+
5377 // Generate struct toString() method
+
5378 WriteLine();
+
5379 WriteLineIndent("@Override");
+
5380 WriteLineIndent("public String toString()");
+
5381 WriteLineIndent("{");
+
5382 Indent(1);
+
5383 WriteLineIndent("var sb = new StringBuilder();");
+
5384 WriteLineIndent("sb.append(\"" + *s->name + "(\");");
+
5385 first = true;
+
5386 if (s->base && !s->base->empty())
+
5387 {
+
5388 WriteLineIndent("sb.append(super.toString());");
+
5389 first = false;
+
5390 }
+
5391 if (s->body)
+
5392 {
+
5393 for (const auto& field : s->body->fields)
+
5394 {
+
5395 if (field->attributes && field->attributes->hidden)
+
5396 WriteLineIndent("sb.append(\"" + std::string(first ? "" : ",") + *field->name + "=***\");");
+
5397 else if (field->array)
+
5398 {
+
5399 WriteLineIndent("if (" + *field->name + " != null)");
+
5400 WriteLineIndent("{");
+
5401 Indent(1);
+
5402 WriteLineIndent("boolean first = true;");
+
5403 WriteLineIndent("sb.append(\"" + std::string(first ? "" : ",") + *field->name + "=[\").append(" + *field->name + ".length" + ").append(\"][\");");
+
5404 WriteLineIndent("for (var item : " + *field->name + ")");
+
5405 WriteLineIndent("{");
+
5406 Indent(1);
+
5407 WriteLineIndent(ConvertOutputStreamValue(*field->type, "item", field->optional, true));
+
5408 WriteLineIndent("first = false;");
+
5409 Indent(-1);
+
5410 WriteLineIndent("}");
+
5411 WriteLineIndent("sb.append(\"]\");");
+
5412 Indent(-1);
+
5413 WriteLineIndent("}");
+
5414 WriteLineIndent("else");
+
5415 Indent(1);
+
5416 WriteLineIndent("sb.append(\"" + std::string(first ? "" : ",") + *field->name + "=[0][]\");");
+
5417 Indent(-1);
+
5418 }
+
5419 else if (field->vector)
+
5420 {
+
5421 WriteLineIndent("if (" + *field->name + " != null)");
+
5422 WriteLineIndent("{");
+
5423 Indent(1);
+
5424 WriteLineIndent("boolean first = true;");
+
5425 WriteLineIndent("sb.append(\"" + std::string(first ? "" : ",") + *field->name + "=[\").append(" + *field->name + ".size()" + ").append(\"][\");");
+
5426 WriteLineIndent("for (var item : " + *field->name + ")");
+
5427 WriteLineIndent("{");
+
5428 Indent(1);
+
5429 WriteLineIndent(ConvertOutputStreamValue(*field->type, "item", field->optional, true));
+
5430 WriteLineIndent("first = false;");
+
5431 Indent(-1);
+
5432 WriteLineIndent("}");
+
5433 WriteLineIndent("sb.append(\"]\");");
+
5434 Indent(-1);
+
5435 WriteLineIndent("}");
+
5436 WriteLineIndent("else");
+
5437 Indent(1);
+
5438 WriteLineIndent("sb.append(\"" + std::string(first ? "" : ",") + *field->name + "=[0][]\");");
+
5439 Indent(-1);
+
5440 }
+
5441 else if (field->list)
+
5442 {
+
5443 WriteLineIndent("if (" + *field->name + " != null)");
+
5444 WriteLineIndent("{");
+
5445 Indent(1);
+
5446 WriteLineIndent("boolean first = true;");
+
5447 WriteLineIndent("sb.append(\"" + std::string(first ? "" : ",") + *field->name + "=[\").append(" + *field->name + ".size()" + ").append(\"]<\");");
+
5448 WriteLineIndent("for (var item : " + *field->name + ")");
+
5449 WriteLineIndent("{");
+
5450 Indent(1);
+
5451 WriteLineIndent(ConvertOutputStreamValue(*field->type, "item", field->optional, true));
+
5452 WriteLineIndent("first = false;");
+
5453 Indent(-1);
+
5454 WriteLineIndent("}");
+
5455 WriteLineIndent("sb.append(\">\");");
+
5456 Indent(-1);
+
5457 WriteLineIndent("}");
+
5458 WriteLineIndent("else");
+
5459 Indent(1);
+
5460 WriteLineIndent("sb.append(\"" + std::string(first ? "" : ",") + *field->name + "=[0]<>\");");
+
5461 Indent(-1);
+
5462 }
+
5463 else if (field->set)
+
5464 {
+
5465 WriteLineIndent("if (" + *field->name + " != null)");
+
5466 WriteLineIndent("{");
+
5467 Indent(1);
+
5468 WriteLineIndent("boolean first = true;");
+
5469 WriteLineIndent("sb.append(\"" + std::string(first ? "" : ",") + *field->name + "=[\").append(" + *field->name + ".size()" + ").append(\"]{\");");
+
5470 WriteLineIndent("for (var item : " + *field->name + ")");
+
5471 WriteLineIndent("{");
+
5472 Indent(1);
+
5473 WriteLineIndent(ConvertOutputStreamValue(*field->type, "item", field->optional, true));
+
5474 WriteLineIndent("first = false;");
+
5475 Indent(-1);
+
5476 WriteLineIndent("}");
+
5477 WriteLineIndent("sb.append(\"}\");");
+
5478 Indent(-1);
+
5479 WriteLineIndent("}");
+
5480 WriteLineIndent("else");
+
5481 Indent(1);
+
5482 WriteLineIndent("sb.append(\"" + std::string(first ? "" : ",") + *field->name + "=[0]{}\");");
+
5483 Indent(-1);
+
5484 }
+
5485 else if (field->map)
+
5486 {
+
5487 WriteLineIndent("if (" + *field->name + " != null)");
+
5488 WriteLineIndent("{");
+
5489 Indent(1);
+
5490 WriteLineIndent("boolean first = true;");
+
5491 WriteLineIndent("sb.append(\"" + std::string(first ? "" : ",") + *field->name + "=[\").append(" + *field->name + ".size()" + ").append(\"]<{\");");
+
5492 WriteLineIndent("for (var item : " + *field->name + ".entrySet())");
+
5493 WriteLineIndent("{");
+
5494 Indent(1);
+
5495 WriteLineIndent(ConvertOutputStreamValue(*field->key, "item.getKey()", false, true));
+
5496 WriteLineIndent("sb.append(\"->\");");
+
5497 WriteLineIndent(ConvertOutputStreamValue(*field->type, "item.getValue()", field->optional, false));
+
5498 WriteLineIndent("first = false;");
+
5499 Indent(-1);
+
5500 WriteLineIndent("}");
+
5501 WriteLineIndent("sb.append(\"}>\");");
+
5502 Indent(-1);
+
5503 WriteLineIndent("}");
+
5504 WriteLineIndent("else");
+
5505 Indent(1);
+
5506 WriteLineIndent("sb.append(\"" + std::string(first ? "" : ",") + *field->name + "=[0]<{}>\");");
+
5507 Indent(-1);
+
5508 }
+
5509 else if (field->hash)
+
5510 {
+
5511 WriteLineIndent("if (" + *field->name + " != null)");
+
5512 WriteLineIndent("{");
+
5513 Indent(1);
+
5514 WriteLineIndent("boolean first = true;");
+
5515 WriteLineIndent("sb.append(\"" + std::string(first ? "" : ",") + *field->name + "=[\").append(" + *field->name + ".size()" + ").append(\"][{\");");
+
5516 WriteLineIndent("for (var item : " + *field->name + ".entrySet())");
+
5517 WriteLineIndent("{");
+
5518 Indent(1);
+
5519 WriteLineIndent(ConvertOutputStreamValue(*field->key, "item.getKey()", false, true));
+
5520 WriteLineIndent("sb.append(\"->\");");
+
5521 WriteLineIndent(ConvertOutputStreamValue(*field->type, "item.getValue()", field->optional, false));
+
5522 WriteLineIndent("first = false;");
+
5523 Indent(-1);
+
5524 WriteLineIndent("}");
+
5525 WriteLineIndent("sb.append(\"}]\");");
+
5526 Indent(-1);
+
5527 WriteLineIndent("}");
+
5528 WriteLineIndent("else");
+
5529 Indent(1);
+
5530 WriteLineIndent("sb.append(\"" + std::string(first ? "" : ",") + *field->name + "=[0][{}]\");");
+
5531 Indent(-1);
+
5532 }
+
5533 else
+
5534 WriteLineIndent("sb.append(\"" + std::string(first ? "" : ",") + *field->name + "=\"); " + ConvertOutputStreamValue(*field->type, *field->name, field->optional, false));
+
5535 first = false;
+
5536 }
+
5537 }
+
5538 WriteLineIndent("sb.append(\")\");");
+
5539 WriteLineIndent("return sb.toString();");
+
5540 Indent(-1);
+
5541 WriteLineIndent("}");
+
5542
+
5543 // Generate struct JSON methods
+
5544 if (JSON())
+
5545 {
+
5546 WriteLine();
+
5547 WriteLineIndent("public String toJson() { return " + domain + *p->name + ".fbe.Json.getEngine().toJson(this); }");
+
5548 WriteLineIndent("public static " + *s->name + " fromJson(String json) { return " + domain + *p->name + ".fbe.Json.getEngine().fromJson(json, " + *s->name + ".class); }");
+
5549 }
+
5550
+
5551 // Generate struct end
+
5552 Indent(-1);
+
5553 WriteLineIndent("}");
+
5554
+
5555 // Generate struct footer
+
5556 GenerateFooter();
+
5557
+
5558 // Store the output file
+
5559 WriteEnd();
+
5560 Store(output);
+
5561
+
5562 // Generate struct field models
+
5563 GenerateStructFieldModel(p, s);
+
5564 GenerateStructModel(p, s);
+
5565
+
5566 // Generate struct final models
+
5567 if (Final())
+
5568 {
+
5569 GenerateStructFinalModel(p, s);
+
5570 GenerateStructModelFinal(p, s);
+
5571 }
+
5572}
+
5573
+
5574void GeneratorJava::GenerateStructFieldModel(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s)
+
5575{
+
5576 std::string domain = (p->domain && !p->domain->empty()) ? (*p->domain + ".") : "";
+
5577 std::string package = *p->name;
+
5578 std::string struct_name = domain + *p->name + "." + *s->name;
+
5579
+
5580 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "fbe";
+
5581
+
5582 // Create package path
+
5583 CppCommon::Directory::CreateTree(path);
+
5584
+
5585 // Generate the file
+
5586 CppCommon::Path file = path / ("FieldModel" + *s->name + ".java");
+
5587 WriteBegin();
+
5588
+
5589 // Generate headers
+
5590 GenerateHeader(CppCommon::Path(_input).filename().string());
+
5591 GenerateImports(domain, package + ".fbe");
+
5592
+
5593 // Generate struct field model begin
+
5594 WriteLine();
+
5595 WriteLineIndent("// Fast Binary Encoding " + *s->name + " field model");
+
5596 WriteLineIndent("public final class FieldModel" + *s->name + " extends " + domain + "fbe.FieldModel");
+
5597 WriteLineIndent("{");
+
5598 Indent(1);
+
5599
+
5600 // Generate struct field model accessors
+
5601 if (s->base && !s->base->empty())
+
5602 WriteLineIndent("public final " + ConvertBaseFieldName(domain, *s->base, false) + " parent;");
+
5603 if (s->body)
+
5604 for (const auto& field : s->body->fields)
+
5605 WriteLineIndent("public final " + ConvertTypeFieldDeclaration(domain, *field, false) + " " + *field->name + ";");
+
5606
+
5607 // Generate struct field model constructor
+
5608 WriteLine();
+
5609 WriteLineIndent("public FieldModel" + *s->name + "(" + domain + "fbe.Buffer buffer, long offset)");
+
5610 WriteLineIndent("{");
+
5611 Indent(1);
+
5612 WriteLineIndent("super(buffer, offset);");
+
5613 std::string prev_offset("4");
+
5614 std::string prev_size("4");
+
5615 if (s->base && !s->base->empty())
+
5616 {
+
5617 WriteLineIndent("parent = new " + ConvertBaseFieldName(domain, *s->base, false) + "(buffer, " + prev_offset + " + " + prev_size + ");");
+
5618 prev_offset = "parent.fbeOffset()";
+
5619 prev_size = "parent.fbeBody() - 4 - 4";
+
5620 }
+
5621 if (s->body)
+
5622 {
+
5623 for (const auto& field : s->body->fields)
+
5624 {
+
5625 WriteLineIndent(*field->name + " = " + ConvertTypeFieldInitialization(domain, *field, prev_offset + " + " + prev_size, false) + ";");
+
5626 prev_offset = *field->name + ".fbeOffset()";
+
5627 prev_size = *field->name + ".fbeSize()";
+
5628 }
+
5629 }
+
5630 Indent(-1);
+
5631 WriteLineIndent("}");
+
5632
+
5633 // Generate struct field model FBE properties
+
5634 WriteLine();
+
5635 WriteLineIndent("// Get the field size");
+
5636 WriteLineIndent("@Override");
+
5637 WriteLineIndent("public long fbeSize() { return 4; }");
+
5638 WriteLineIndent("// Get the field body size");
+
5639 WriteLineIndent("public long fbeBody()");
+
5640 WriteLineIndent("{");
+
5641 Indent(1);
+
5642 WriteLineIndent("long fbeResult = 4 + 4");
+
5643 Indent(1);
+
5644 if (s->base && !s->base->empty())
+
5645 WriteLineIndent("+ parent.fbeBody() - 4 - 4");
+
5646 if (s->body)
+
5647 for (const auto& field : s->body->fields)
+
5648 WriteLineIndent("+ " + *field->name + ".fbeSize()");
+
5649 WriteLineIndent(";");
+
5650 Indent(-1);
+
5651 WriteLineIndent("return fbeResult;");
+
5652 Indent(-1);
+
5653 WriteLineIndent("}");
+
5654 WriteLineIndent("// Get the field extra size");
+
5655 WriteLineIndent("@Override");
+
5656 WriteLineIndent("public long fbeExtra()");
+
5657 WriteLineIndent("{");
+
5658 Indent(1);
+
5659 WriteLineIndent("if ((_buffer.getOffset() + fbeOffset() + fbeSize()) > _buffer.getSize())");
+
5660 Indent(1);
+
5661 WriteLineIndent("return 0;");
+
5662 Indent(-1);
+
5663 WriteLine();
+
5664 WriteLineIndent("int fbeStructOffset = readInt32(fbeOffset());");
+
5665 WriteLineIndent("if ((fbeStructOffset == 0) || ((_buffer.getOffset() + fbeStructOffset + 4) > _buffer.getSize()))");
+
5666 Indent(1);
+
5667 WriteLineIndent("return 0;");
+
5668 Indent(-1);
+
5669 WriteLine();
+
5670 WriteLineIndent("_buffer.shift(fbeStructOffset);");
+
5671 WriteLine();
+
5672 WriteLineIndent("long fbeResult = fbeBody()");
+
5673 Indent(1);
+
5674 if (s->base && !s->base->empty())
+
5675 WriteLineIndent("+ parent.fbeExtra()");
+
5676 if (s->body)
+
5677 for (const auto& field : s->body->fields)
+
5678 WriteLineIndent("+ " + *field->name + ".fbeExtra()");
+
5679 WriteLineIndent(";");
+
5680 Indent(-1);
+
5681 WriteLine();
+
5682 WriteLineIndent("_buffer.unshift(fbeStructOffset);");
+
5683 WriteLine();
+
5684 WriteLineIndent("return fbeResult;");
+
5685 Indent(-1);
+
5686 WriteLineIndent("}");
+
5687 WriteLineIndent("// Get the field type");
+
5688 if (s->base && !s->base->empty() && (s->type == 0))
+
5689 WriteLineIndent("public static final long fbeTypeConst = " + ConvertBaseFieldName(domain, *s->base, false) + ".fbeTypeConst;");
+
5690 else
+
5691 WriteLineIndent("public static final long fbeTypeConst = " + std::to_string(s->type) + ";");
+
5692 WriteLineIndent("public long fbeType() { return fbeTypeConst; }");
+
5693
+
5694 // Generate struct field model verify() methods
+
5695 WriteLine();
+
5696 WriteLineIndent("// Check if the struct value is valid");
+
5697 WriteLineIndent("@Override");
+
5698 WriteLineIndent("public boolean verify() { return verify(true); }");
+
5699 WriteLineIndent("public boolean verify(boolean fbeVerifyType)");
+
5700 WriteLineIndent("{");
+
5701 Indent(1);
+
5702 WriteLineIndent("if ((_buffer.getOffset() + fbeOffset() + fbeSize()) > _buffer.getSize())");
+
5703 Indent(1);
+
5704 WriteLineIndent("return true;");
+
5705 Indent(-1);
+
5706 WriteLine();
+
5707 WriteLineIndent("int fbeStructOffset = readInt32(fbeOffset());");
+
5708 WriteLineIndent("if ((fbeStructOffset == 0) || ((_buffer.getOffset() + fbeStructOffset + 4 + 4) > _buffer.getSize()))");
+
5709 Indent(1);
+
5710 WriteLineIndent("return false;");
+
5711 Indent(-1);
+
5712 WriteLine();
+
5713 WriteLineIndent("int fbeStructSize = readInt32(fbeStructOffset);");
+
5714 WriteLineIndent("if (fbeStructSize < (4 + 4))");
+
5715 Indent(1);
+
5716 WriteLineIndent("return false;");
+
5717 Indent(-1);
+
5718 WriteLine();
+
5719 WriteLineIndent("int fbeStructType = readInt32(fbeStructOffset + 4);");
+
5720 WriteLineIndent("if (fbeVerifyType && (fbeStructType != fbeType()))");
+
5721 Indent(1);
+
5722 WriteLineIndent("return false;");
+
5723 Indent(-1);
+
5724 WriteLine();
+
5725 WriteLineIndent("_buffer.shift(fbeStructOffset);");
+
5726 WriteLineIndent("boolean fbeResult = verifyFields(fbeStructSize);");
+
5727 WriteLineIndent("_buffer.unshift(fbeStructOffset);");
+
5728 WriteLineIndent("return fbeResult;");
+
5729 Indent(-1);
+
5730 WriteLineIndent("}");
+
5731
+
5732 // Generate struct field model verifyFields() method
+
5733 WriteLine();
+
5734 WriteLineIndent("// Check if the struct fields are valid");
+
5735 WriteLineIndent("public boolean verifyFields(long fbeStructSize)");
+
5736 WriteLineIndent("{");
+
5737 Indent(1);
+
5738 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
5739 {
+
5740 WriteLineIndent("long fbeCurrentSize = 4 + 4;");
+
5741 if (s->base && !s->base->empty())
+
5742 {
+
5743 WriteLine();
+
5744 WriteLineIndent("if ((fbeCurrentSize + parent.fbeBody() - 4 - 4) > fbeStructSize)");
+
5745 Indent(1);
+
5746 WriteLineIndent("return true;");
+
5747 Indent(-1);
+
5748 WriteLineIndent("if (!parent.verifyFields(fbeStructSize))");
+
5749 Indent(1);
+
5750 WriteLineIndent("return false;");
+
5751 Indent(-1);
+
5752 WriteLineIndent("fbeCurrentSize += parent.fbeBody() - 4 - 4;");
+
5753 }
+
5754 if (s->body)
+
5755 {
+
5756 for (const auto& field : s->body->fields)
+
5757 {
+
5758 WriteLine();
+
5759 WriteLineIndent("if ((fbeCurrentSize + " + *field->name + ".fbeSize()) > fbeStructSize)");
+
5760 Indent(1);
+
5761 WriteLineIndent("return true;");
+
5762 Indent(-1);
+
5763 WriteLineIndent("if (!" + *field->name + ".verify())");
+
5764 Indent(1);
+
5765 WriteLineIndent("return false;");
+
5766 Indent(-1);
+
5767 WriteLineIndent("fbeCurrentSize += " + *field->name + ".fbeSize();");
+
5768 }
+
5769 }
+
5770 WriteLine();
+
5771 }
+
5772 WriteLineIndent("return true;");
+
5773 Indent(-1);
+
5774 WriteLineIndent("}");
+
5775
+
5776 // Generate struct field model getBegin() method
+
5777 WriteLine();
+
5778 WriteLineIndent("// Get the struct value (begin phase)");
+
5779 WriteLineIndent("public long getBegin()");
+
5780 WriteLineIndent("{");
+
5781 Indent(1);
+
5782 WriteLineIndent("if ((_buffer.getOffset() + fbeOffset() + fbeSize()) > _buffer.getSize())");
+
5783 Indent(1);
+
5784 WriteLineIndent("return 0;");
+
5785 Indent(-1);
+
5786 WriteLine();
+
5787 WriteLineIndent("int fbeStructOffset = readInt32(fbeOffset());");
+
5788 WriteLineIndent("assert ((fbeStructOffset > 0) && ((_buffer.getOffset() + fbeStructOffset + 4 + 4) <= _buffer.getSize())) : \"Model is broken!\";");
+
5789 WriteLineIndent("if ((fbeStructOffset == 0) || ((_buffer.getOffset() + fbeStructOffset + 4 + 4) > _buffer.getSize()))");
+
5790 Indent(1);
+
5791 WriteLineIndent("return 0;");
+
5792 Indent(-1);
+
5793 WriteLine();
+
5794 WriteLineIndent("int fbeStructSize = readInt32(fbeStructOffset);");
+
5795 WriteLineIndent("assert (fbeStructSize >= (4 + 4)) : \"Model is broken!\";");
+
5796 WriteLineIndent("if (fbeStructSize < (4 + 4))");
+
5797 Indent(1);
+
5798 WriteLineIndent("return 0;");
+
5799 Indent(-1);
+
5800 WriteLine();
+
5801 WriteLineIndent("_buffer.shift(fbeStructOffset);");
+
5802 WriteLineIndent("return fbeStructOffset;");
+
5803 Indent(-1);
+
5804 WriteLineIndent("}");
+
5805
+
5806 // Generate struct field model getEnd() method
+
5807 WriteLine();
+
5808 WriteLineIndent("// Get the struct value (end phase)");
+
5809 WriteLineIndent("public void getEnd(long fbeBegin)");
+
5810 WriteLineIndent("{");
+
5811 Indent(1);
+
5812 WriteLineIndent("_buffer.unshift(fbeBegin);");
+
5813 Indent(-1);
+
5814 WriteLineIndent("}");
+
5815
+
5816 // Generate struct field model get() methods
+
5817 WriteLine();
+
5818 WriteLineIndent("// Get the struct value");
+
5819 WriteLineIndent("public " + struct_name + " get() { return get(new " + struct_name + "()); }");
+
5820 WriteLineIndent("public " + struct_name + " get(" + struct_name + " fbeValue)");
+
5821 WriteLineIndent("{");
+
5822 Indent(1);
+
5823 WriteLineIndent("long fbeBegin = getBegin();");
+
5824 WriteLineIndent("if (fbeBegin == 0)");
+
5825 Indent(1);
+
5826 WriteLineIndent("return fbeValue;");
+
5827 Indent(-1);
+
5828 WriteLine();
+
5829 WriteLineIndent("int fbeStructSize = readInt32(0);");
+
5830 WriteLineIndent("getFields(fbeValue, fbeStructSize);");
+
5831 WriteLineIndent("getEnd(fbeBegin);");
+
5832 WriteLineIndent("return fbeValue;");
+
5833 Indent(-1);
+
5834 WriteLineIndent("}");
+
5835
+
5836 // Generate struct field model getFields() method
+
5837 WriteLine();
+
5838 WriteLineIndent("// Get the struct fields values");
+
5839 WriteLineIndent("public void getFields(" + struct_name + " fbeValue, long fbeStructSize)");
+
5840 WriteLineIndent("{");
+
5841 Indent(1);
+
5842 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
5843 {
+
5844 WriteLineIndent("long fbeCurrentSize = 4 + 4;");
+
5845 if (s->base && !s->base->empty())
+
5846 {
+
5847 WriteLine();
+
5848 WriteLineIndent("if ((fbeCurrentSize + parent.fbeBody() - 4 - 4) <= fbeStructSize)");
+
5849 Indent(1);
+
5850 WriteLineIndent("parent.getFields(fbeValue, fbeStructSize);");
+
5851 Indent(-1);
+
5852 WriteLineIndent("fbeCurrentSize += parent.fbeBody() - 4 - 4;");
+
5853 }
+
5854 if (s->body)
+
5855 {
+
5856 for (const auto& field : s->body->fields)
+
5857 {
+
5858 WriteLine();
+
5859 WriteLineIndent("if ((fbeCurrentSize + " + *field->name + ".fbeSize()) <= fbeStructSize)");
+
5860 Indent(1);
+
5861 if (field->array || field->vector || field->list || field->set || field->map || field->hash)
+
5862 WriteLineIndent(*field->name + ".get(fbeValue." + *field->name + ");");
+
5863 else
+
5864 WriteLineIndent("fbeValue." + *field->name + " = " + *field->name + ".get(" + (field->value ? ConvertConstant(domain, package, *field->type, *field->value, field->optional) : "") + ");");
+
5865 Indent(-1);
+
5866 WriteLineIndent("else");
+
5867 Indent(1);
+
5868 if (field->vector || field->list || field->set || field->map || field->hash)
+
5869 WriteLineIndent("fbeValue." + *field->name + ".clear();");
+
5870 else
+
5871 WriteLineIndent("fbeValue." + *field->name + " = " + ConvertDefault(domain, package, *field) + ";");
+
5872 Indent(-1);
+
5873 WriteLineIndent("fbeCurrentSize += " + *field->name + ".fbeSize();");
+
5874 }
+
5875 }
+
5876 }
+
5877 Indent(-1);
+
5878 WriteLineIndent("}");
+
5879
+
5880 // Generate struct field model setBegin() method
+
5881 WriteLine();
+
5882 WriteLineIndent("// Set the struct value (begin phase)");
+
5883 WriteLineIndent("public long setBegin()");
+
5884 WriteLineIndent("{");
+
5885 Indent(1);
+
5886 WriteLineIndent("assert ((_buffer.getOffset() + fbeOffset() + fbeSize()) <= _buffer.getSize()) : \"Model is broken!\";");
+
5887 WriteLineIndent("if ((_buffer.getOffset() + fbeOffset() + fbeSize()) > _buffer.getSize())");
+
5888 Indent(1);
+
5889 WriteLineIndent("return 0;");
+
5890 Indent(-1);
+
5891 WriteLine();
+
5892 WriteLineIndent("int fbeStructSize = (int)fbeBody();");
+
5893 WriteLineIndent("int fbeStructOffset = (int)(_buffer.allocate(fbeStructSize) - _buffer.getOffset());");
+
5894 WriteLineIndent("assert ((fbeStructOffset > 0) && ((_buffer.getOffset() + fbeStructOffset + fbeStructSize) <= _buffer.getSize())) : \"Model is broken!\";");
+
5895 WriteLineIndent("if ((fbeStructOffset <= 0) || ((_buffer.getOffset() + fbeStructOffset + fbeStructSize) > _buffer.getSize()))");
+
5896 Indent(1);
+
5897 WriteLineIndent("return 0;");
+
5898 Indent(-1);
+
5899 WriteLine();
+
5900 WriteLineIndent("write(fbeOffset(), fbeStructOffset);");
+
5901 WriteLineIndent("write(fbeStructOffset, fbeStructSize);");
+
5902 WriteLineIndent("write(fbeStructOffset + 4, (int)fbeType());");
+
5903 WriteLine();
+
5904 WriteLineIndent("_buffer.shift(fbeStructOffset);");
+
5905 WriteLineIndent("return fbeStructOffset;");
+
5906 Indent(-1);
+
5907 WriteLineIndent("}");
+
5908
+
5909 // Generate struct field model setEnd() method
+
5910 WriteLine();
+
5911 WriteLineIndent("// Set the struct value (end phase)");
+
5912 WriteLineIndent("public void setEnd(long fbeBegin)");
+
5913 WriteLineIndent("{");
+
5914 Indent(1);
+
5915 WriteLineIndent("_buffer.unshift(fbeBegin);");
+
5916 Indent(-1);
+
5917 WriteLineIndent("}");
+
5918
+
5919 // Generate struct field model set() method
+
5920 WriteLine();
+
5921 WriteLineIndent("// Set the struct value");
+
5922 WriteLineIndent("public void set(" + struct_name + " fbeValue)");
+
5923 WriteLineIndent("{");
+
5924 Indent(1);
+
5925 WriteLineIndent("long fbeBegin = setBegin();");
+
5926 WriteLineIndent("if (fbeBegin == 0)");
+
5927 Indent(1);
+
5928 WriteLineIndent("return;");
+
5929 Indent(-1);
+
5930 WriteLine();
+
5931 WriteLineIndent("setFields(fbeValue);");
+
5932 WriteLineIndent("setEnd(fbeBegin);");
+
5933 Indent(-1);
+
5934 WriteLineIndent("}");
+
5935
+
5936 // Generate struct field model setFields() method
+
5937 WriteLine();
+
5938 WriteLineIndent("// Set the struct fields values");
+
5939 WriteLineIndent("public void setFields(" + struct_name + " fbeValue)");
+
5940 WriteLineIndent("{");
+
5941 Indent(1);
+
5942 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
5943 {
+
5944 if (s->base && !s->base->empty())
+
5945 WriteLineIndent("parent.setFields(fbeValue);");
+
5946 if (s->body)
+
5947 for (const auto& field : s->body->fields)
+
5948 WriteLineIndent(*field->name + ".set(fbeValue." + *field->name + ");");
+
5949 }
+
5950 Indent(-1);
+
5951 WriteLineIndent("}");
+
5952
+
5953 // Generate struct field model end
+
5954 Indent(-1);
+
5955 WriteLineIndent("}");
+
5956
+
5957 // Generate footer
+
5958 GenerateFooter();
+
5959
+
5960 // Store the file
+
5961 WriteEnd();
+
5962 Store(file);
+
5963}
+
5964
+
5965void GeneratorJava::GenerateStructModel(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s)
+
5966{
+
5967 std::string domain = (p->domain && !p->domain->empty()) ? (*p->domain + ".") : "";
+
5968 std::string package = *p->name;
+
5969 std::string struct_name = domain + package + "." + *s->name;
+
5970
+
5971 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "fbe";
+
5972
+
5973 // Create package path
+
5974 CppCommon::Directory::CreateTree(path);
+
5975
+
5976 // Generate the file
+
5977 CppCommon::Path file = path / (*s->name + "Model.java");
+
5978 WriteBegin();
+
5979
+
5980 // Generate headers
+
5981 GenerateHeader(CppCommon::Path(_input).filename().string());
+
5982 GenerateImports(domain, package + ".fbe");
+
5983
+
5984 // Generate struct model begin
+
5985 WriteLine();
+
5986 WriteLineIndent("// Fast Binary Encoding " + *s->name + " model");
+
5987 WriteLineIndent("public final class " + *s->name + "Model extends " + domain + "fbe." + "Model");
+
5988 WriteLineIndent("{");
+
5989 Indent(1);
+
5990
+
5991 // Generate struct model accessor
+
5992 WriteLineIndent("public final FieldModel" + *s->name + " model;");
+
5993
+
5994 // Generate struct model constructors
+
5995 WriteLine();
+
5996 WriteLineIndent("public " + *s->name + "Model() { model = new FieldModel" + *s->name + "(getBuffer(), 4); }");
+
5997 WriteLineIndent("public " + *s->name + "Model(" + domain + "fbe.Buffer buffer) { super(buffer); model = new FieldModel" + *s->name + "(getBuffer(), 4); }");
+
5998
+
5999 // Generate struct model FBE properties
+
6000 WriteLine();
+
6001 WriteLineIndent("// Get the model size");
+
6002 WriteLineIndent("public long fbeSize() { return model.fbeSize() + model.fbeExtra(); }");
+
6003 WriteLineIndent("// Get the model type");
+
6004 WriteLineIndent("public static final long fbeTypeConst = FieldModel" + *s->name + ".fbeTypeConst;");
+
6005 WriteLineIndent("public long fbeType() { return fbeTypeConst; }");
+
6006
+
6007 // Generate struct model verify() method
+
6008 WriteLine();
+
6009 WriteLineIndent("// Check if the struct value is valid");
+
6010 WriteLineIndent("public boolean verify()");
+
6011 WriteLineIndent("{");
+
6012 Indent(1);
+
6013 WriteLineIndent("if ((getBuffer().getOffset() + model.fbeOffset() - 4) > getBuffer().getSize())");
+
6014 Indent(1);
+
6015 WriteLineIndent("return false;");
+
6016 Indent(-1);
+
6017 WriteLine();
+
6018 WriteLineIndent("int fbeFullSize = readInt32(model.fbeOffset() - 4);");
+
6019 WriteLineIndent("if (fbeFullSize < model.fbeSize())");
+
6020 Indent(1);
+
6021 WriteLineIndent("return false;");
+
6022 Indent(-1);
+
6023 WriteLine();
+
6024 WriteLineIndent("return model.verify();");
+
6025 Indent(-1);
+
6026 WriteLineIndent("}");
+
6027
+
6028 // Generate struct model createBegin() method
+
6029 WriteLine();
+
6030 WriteLineIndent("// Create a new model (begin phase)");
+
6031 WriteLineIndent("public long createBegin()");
+
6032 WriteLineIndent("{");
+
6033 Indent(1);
+
6034 WriteLineIndent("long fbeBegin = getBuffer().allocate(4 + model.fbeSize());");
+
6035 WriteLineIndent("return fbeBegin;");
+
6036 Indent(-1);
+
6037 WriteLineIndent("}");
+
6038
+
6039 // Generate struct model createEnd() method
+
6040 WriteLine();
+
6041 WriteLineIndent("// Create a new model (end phase)");
+
6042 WriteLineIndent("public long createEnd(long fbeBegin)");
+
6043 WriteLineIndent("{");
+
6044 Indent(1);
+
6045 WriteLineIndent("long fbeEnd = getBuffer().getSize();");
+
6046 WriteLineIndent("int fbeFullSize = (int)(fbeEnd - fbeBegin);");
+
6047 WriteLineIndent("write(model.fbeOffset() - 4, fbeFullSize);");
+
6048 WriteLineIndent("return fbeFullSize;");
+
6049 Indent(-1);
+
6050 WriteLineIndent("}");
+
6051
+
6052 // Generate struct model serialize() method
+
6053 WriteLine();
+
6054 WriteLineIndent("// Serialize the struct value");
+
6055 WriteLineIndent("public long serialize(" + struct_name + " value)");
+
6056 WriteLineIndent("{");
+
6057 Indent(1);
+
6058 WriteLineIndent("long fbeBegin = createBegin();");
+
6059 WriteLineIndent("model.set(value);");
+
6060 WriteLineIndent("long fbeFullSize = createEnd(fbeBegin);");
+
6061 WriteLineIndent("return fbeFullSize;");
+
6062 Indent(-1);
+
6063 WriteLineIndent("}");
+
6064
+
6065 // Generate struct model deserialize() methods
+
6066 WriteLine();
+
6067 WriteLineIndent("// Deserialize the struct value");
+
6068 WriteLineIndent("public " + struct_name + " deserialize() { var value = new " + struct_name + "(); deserialize(value); return value; }");
+
6069 WriteLineIndent("public long deserialize(" + struct_name + " value)");
+
6070 WriteLineIndent("{");
+
6071 Indent(1);
+
6072 WriteLineIndent("if ((getBuffer().getOffset() + model.fbeOffset() - 4) > getBuffer().getSize())");
+
6073 WriteLineIndent("{");
+
6074 Indent(1);
+
6075 WriteLineIndent("value = new " + struct_name + "();");
+
6076 WriteLineIndent("return 0;");
+
6077 Indent(-1);
+
6078 WriteLineIndent("}");
+
6079 WriteLine();
+
6080 WriteLineIndent("int fbeFullSize = readInt32(model.fbeOffset() - 4);");
+
6081 WriteLineIndent("assert (fbeFullSize >= model.fbeSize()) : \"Model is broken!\";");
+
6082 WriteLineIndent("if (fbeFullSize < model.fbeSize())");
+
6083 WriteLineIndent("{");
+
6084 Indent(1);
+
6085 WriteLineIndent("value = new " + struct_name + "();");
+
6086 WriteLineIndent("return 0;");
+
6087 Indent(-1);
+
6088 WriteLineIndent("}");
+
6089 WriteLine();
+
6090 WriteLineIndent("value = model.get(value);");
+
6091 WriteLineIndent("return fbeFullSize;");
+
6092 Indent(-1);
+
6093 WriteLineIndent("}");
+
6094
+
6095 // Generate struct model next() method
+
6096 WriteLine();
+
6097 WriteLineIndent("// Move to the next struct value");
+
6098 WriteLineIndent("public void next(long prev)");
+
6099 WriteLineIndent("{");
+
6100 Indent(1);
+
6101 WriteLineIndent("model.fbeShift(prev);");
+
6102 Indent(-1);
+
6103 WriteLineIndent("}");
+
6104
+
6105 // Generate struct model end
+
6106 Indent(-1);
+
6107 WriteLineIndent("}");
+
6108
+
6109 // Generate footer
+
6110 GenerateFooter();
+
6111
+
6112 // Store the file
+
6113 WriteEnd();
+
6114 Store(file);
+
6115}
+
6116
+
6117void GeneratorJava::GenerateStructFinalModel(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s)
+
6118{
+
6119 std::string domain = (p->domain && !p->domain->empty()) ? (*p->domain + ".") : "";
+
6120 std::string package = *p->name;
+
6121 std::string struct_name = domain + *p->name + "." + *s->name;
+
6122
+
6123 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "fbe";
+
6124
+
6125 // Create package path
+
6126 CppCommon::Directory::CreateTree(path);
+
6127
+
6128 // Generate the file
+
6129 CppCommon::Path file = path / ("FinalModel" + *s->name + ".java");
+
6130 WriteBegin();
+
6131
+
6132 // Generate headers
+
6133 GenerateHeader(CppCommon::Path(_input).filename().string());
+
6134 GenerateImports(domain, package + ".fbe");
+
6135
+
6136 // Generate struct final model begin
+
6137 WriteLine();
+
6138 WriteLineIndent("// Fast Binary Encoding " + *s->name + " final model");
+
6139 WriteLineIndent("public final class FinalModel" + *s->name + " extends " + domain + "fbe." + "FinalModel");
+
6140 WriteLineIndent("{");
+
6141 Indent(1);
+
6142
+
6143 // Generate struct final model accessors
+
6144 if (s->base && !s->base->empty())
+
6145 WriteLineIndent("public final " + ConvertBaseFieldName(domain, *s->base, true) + " parent;");
+
6146 if (s->body)
+
6147 for (const auto& field : s->body->fields)
+
6148 WriteLineIndent("public final " + ConvertTypeFieldDeclaration(domain, *field, true) + " " + *field->name + ";");
+
6149
+
6150 // Generate struct final model constructor
+
6151 WriteLine();
+
6152 WriteLineIndent("public FinalModel" + *s->name + "(" + domain + "fbe.Buffer buffer, long offset)");
+
6153 WriteLineIndent("{");
+
6154 Indent(1);
+
6155 WriteLineIndent("super(buffer, offset);");
+
6156 if (s->base && !s->base->empty())
+
6157 WriteLineIndent("parent = new " + ConvertBaseFieldName(domain, *s->base, true) + "(buffer, 0);");
+
6158 if (s->body)
+
6159 for (const auto& field : s->body->fields)
+
6160 WriteLineIndent(*field->name + " = " + ConvertTypeFieldInitialization(domain, *field, "0", true) + ";");
+
6161 Indent(-1);
+
6162 WriteLineIndent("}");
+
6163
+
6164 // Generate struct final model FBE properties
+
6165 WriteLine();
+
6166 WriteLineIndent("// Get the allocation size");
+
6167 WriteLineIndent("public long fbeAllocationSize(" + struct_name + " fbeValue)");
+
6168 WriteLineIndent("{");
+
6169 Indent(1);
+
6170 WriteLineIndent("long fbeResult = 0");
+
6171 Indent(1);
+
6172 if (s->base && !s->base->empty())
+
6173 WriteLineIndent("+ parent.fbeAllocationSize(fbeValue)");
+
6174 if (s->body)
+
6175 for (const auto& field : s->body->fields)
+
6176 WriteLineIndent("+ " + *field->name + ".fbeAllocationSize(fbeValue." + *field->name + ")");
+
6177 WriteLineIndent(";");
+
6178 Indent(-1);
+
6179 WriteLineIndent("return fbeResult;");
+
6180 Indent(-1);
+
6181 WriteLineIndent("}");
+
6182 WriteLine();
+
6183 WriteLineIndent("// Get the final type");
+
6184 if (s->base && !s->base->empty() && (s->type == 0))
+
6185 WriteLineIndent("public static final long fbeTypeConst = " + ConvertBaseFieldName(domain, *s->base, true) + ".fbeTypeConst;");
+
6186 else
+
6187 WriteLineIndent("public static final long fbeTypeConst = " + std::to_string(s->type) + ";");
+
6188 WriteLineIndent("public long fbeType() { return fbeTypeConst; }");
+
6189
+
6190 // Generate struct final model verify() methods
+
6191 WriteLine();
+
6192 WriteLineIndent("// Check if the struct value is valid");
+
6193 WriteLineIndent("@Override");
+
6194 WriteLineIndent("public long verify()");
+
6195 WriteLineIndent("{");
+
6196 Indent(1);
+
6197 WriteLineIndent("_buffer.shift(fbeOffset());");
+
6198 WriteLineIndent("long fbeResult = verifyFields();");
+
6199 WriteLineIndent("_buffer.unshift(fbeOffset());");
+
6200 WriteLineIndent("return fbeResult;");
+
6201 Indent(-1);
+
6202 WriteLineIndent("}");
+
6203
+
6204 // Generate struct final model verifyFields() method
+
6205 WriteLine();
+
6206 WriteLineIndent("// Check if the struct fields are valid");
+
6207 WriteLineIndent("public long verifyFields()");
+
6208 WriteLineIndent("{");
+
6209 Indent(1);
+
6210 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
6211 {
+
6212 WriteLineIndent("long fbeCurrentOffset = 0;");
+
6213 WriteLineIndent("long fbeFieldSize = 0;");
+
6214 if (s->base && !s->base->empty())
+
6215 {
+
6216 WriteLine();
+
6217 WriteLineIndent("parent.fbeOffset(fbeCurrentOffset);");
+
6218 WriteLineIndent("fbeFieldSize = parent.verifyFields();");
+
6219 WriteLineIndent("if (fbeFieldSize == Long.MAX_VALUE)");
+
6220 Indent(1);
+
6221 WriteLineIndent("return Long.MAX_VALUE;");
+
6222 Indent(-1);
+
6223 WriteLineIndent("fbeCurrentOffset += fbeFieldSize;");
+
6224 }
+
6225 if (s->body)
+
6226 {
+
6227 for (const auto& field : s->body->fields)
+
6228 {
+
6229 WriteLine();
+
6230 WriteLineIndent(*field->name + ".fbeOffset(fbeCurrentOffset);");
+
6231 WriteLineIndent("fbeFieldSize = " + *field->name + ".verify();");
+
6232 WriteLineIndent("if (fbeFieldSize == Long.MAX_VALUE)");
+
6233 Indent(1);
+
6234 WriteLineIndent("return Long.MAX_VALUE;");
+
6235 Indent(-1);
+
6236 WriteLineIndent("fbeCurrentOffset += fbeFieldSize;");
+
6237 }
+
6238 }
+
6239 WriteLine();
+
6240 WriteLineIndent("return fbeCurrentOffset;");
+
6241 }
+
6242 else
+
6243 WriteLineIndent("return 0;");
+
6244 Indent(-1);
+
6245 WriteLineIndent("}");
+
6246
+
6247 // Generate struct final model get() methods
+
6248 WriteLine();
+
6249 WriteLineIndent("// Get the struct value");
+
6250 WriteLineIndent("public " + struct_name + " get(" + domain + "fbe.Size fbeSize) { return get(fbeSize, new " + struct_name + "()); }");
+
6251 WriteLineIndent("public " + struct_name + " get(" + domain + "fbe.Size fbeSize, " + struct_name + " fbeValue)");
+
6252 WriteLineIndent("{");
+
6253 Indent(1);
+
6254 WriteLineIndent("_buffer.shift(fbeOffset());");
+
6255 WriteLineIndent("fbeSize.value = getFields(fbeValue);");
+
6256 WriteLineIndent("_buffer.unshift(fbeOffset());");
+
6257 WriteLineIndent("return fbeValue;");
+
6258 Indent(-1);
+
6259 WriteLineIndent("}");
+
6260
+
6261 // Generate struct final model getFields() method
+
6262 WriteLine();
+
6263 WriteLineIndent("// Get the struct fields values");
+
6264 WriteLineIndent("public long getFields(" + struct_name + " fbeValue)");
+
6265 WriteLineIndent("{");
+
6266 Indent(1);
+
6267 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
6268 {
+
6269 WriteLineIndent("long fbeCurrentOffset = 0;");
+
6270 WriteLineIndent("long fbeCurrentSize = 0;");
+
6271 WriteLineIndent("var fbeFieldSize = new " + domain + "fbe.Size(0);");
+
6272 if (s->base && !s->base->empty())
+
6273 {
+
6274 WriteLine();
+
6275 WriteLineIndent("parent.fbeOffset(fbeCurrentOffset);");
+
6276 WriteLineIndent("fbeFieldSize.value = parent.getFields(fbeValue);");
+
6277 WriteLineIndent("fbeCurrentOffset += fbeFieldSize.value;");
+
6278 WriteLineIndent("fbeCurrentSize += fbeFieldSize.value;");
+
6279 }
+
6280 if (s->body)
+
6281 {
+
6282 for (const auto& field : s->body->fields)
+
6283 {
+
6284 WriteLine();
+
6285 WriteLineIndent(*field->name + ".fbeOffset(fbeCurrentOffset);");
+
6286 if (field->array || field->vector || field->list || field->set || field->map || field->hash)
+
6287 WriteLineIndent("fbeFieldSize.value = " + *field->name + ".get(fbeValue." + *field->name + ");");
+
6288 else
+
6289 WriteLineIndent("fbeValue." + *field->name + " = " + *field->name + ".get(fbeFieldSize);");
+
6290 WriteLineIndent("fbeCurrentOffset += fbeFieldSize.value;");
+
6291 WriteLineIndent("fbeCurrentSize += fbeFieldSize.value;");
+
6292 }
+
6293 }
+
6294 WriteLine();
+
6295 WriteLineIndent("return fbeCurrentSize;");
+
6296 }
+
6297 else
+
6298 WriteLineIndent("return 0;");
+
6299 Indent(-1);
+
6300 WriteLineIndent("}");
+
6301
+
6302 // Generate struct final model set() method
+
6303 WriteLine();
+
6304 WriteLineIndent("// Set the struct value");
+
6305 WriteLineIndent("public long set(" + struct_name + " fbeValue)");
+
6306 WriteLineIndent("{");
+
6307 Indent(1);
+
6308 WriteLineIndent("_buffer.shift(fbeOffset());");
+
6309 WriteLineIndent("long fbeSize = setFields(fbeValue);");
+
6310 WriteLineIndent("_buffer.unshift(fbeOffset());");
+
6311 WriteLineIndent("return fbeSize;");
+
6312 Indent(-1);
+
6313 WriteLineIndent("}");
+
6314
+
6315 // Generate struct final model setFields() method
+
6316 WriteLine();
+
6317 WriteLineIndent("// Set the struct fields values");
+
6318 WriteLineIndent("public long setFields(" + struct_name + " fbeValue)");
+
6319 WriteLineIndent("{");
+
6320 Indent(1);
+
6321 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
6322 {
+
6323 WriteLineIndent("long fbeCurrentOffset = 0;");
+
6324 WriteLineIndent("long fbeCurrentSize = 0;");
+
6325 WriteLineIndent("var fbeFieldSize = new " + domain + "fbe.Size();");
+
6326 if (s->base && !s->base->empty())
+
6327 {
+
6328 WriteLine();
+
6329 WriteLineIndent("parent.fbeOffset(fbeCurrentOffset);");
+
6330 WriteLineIndent("fbeFieldSize.value = parent.setFields(fbeValue);");
+
6331 WriteLineIndent("fbeCurrentOffset += fbeFieldSize.value;");
+
6332 WriteLineIndent("fbeCurrentSize += fbeFieldSize.value;");
+
6333 }
+
6334 if (s->body)
+
6335 {
+
6336 for (const auto& field : s->body->fields)
+
6337 {
+
6338 WriteLine();
+
6339 WriteLineIndent(*field->name + ".fbeOffset(fbeCurrentOffset);");
+
6340 WriteLineIndent("fbeFieldSize.value = " + *field->name + ".set(fbeValue." + *field->name + ");");
+
6341 WriteLineIndent("fbeCurrentOffset += fbeFieldSize.value;");
+
6342 WriteLineIndent("fbeCurrentSize += fbeFieldSize.value;");
+
6343 }
+
6344 }
+
6345 WriteLine();
+
6346 WriteLineIndent("return fbeCurrentSize;");
+
6347 }
+
6348 else
+
6349 WriteLineIndent("return 0;");
+
6350 Indent(-1);
+
6351 WriteLineIndent("}");
+
6352
+
6353 // Generate struct final model end
+
6354 Indent(-1);
+
6355 WriteLineIndent("}");
+
6356
+
6357 // Generate footer
+
6358 GenerateFooter();
+
6359
+
6360 // Store the file
+
6361 WriteEnd();
+
6362 Store(file);
+
6363}
+
6364
+
6365void GeneratorJava::GenerateStructModelFinal(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s)
+
6366{
+
6367 std::string domain = (p->domain && !p->domain->empty()) ? (*p->domain + ".") : "";
+
6368 std::string package = *p->name;
+
6369 std::string struct_name = domain + package + "." + *s->name;
+
6370
+
6371 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "fbe";
+
6372
+
6373 // Create package path
+
6374 CppCommon::Directory::CreateTree(path);
+
6375
+
6376 // Generate the file
+
6377 CppCommon::Path file = path / (*s->name + "FinalModel.java");
+
6378 WriteBegin();
+
6379
+
6380 // Generate headers
+
6381 GenerateHeader(CppCommon::Path(_input).filename().string());
+
6382 GenerateImports(domain, package + ".fbe");
+
6383
+
6384 // Generate struct model final begin
+
6385 WriteLine();
+
6386 WriteLineIndent("// Fast Binary Encoding " + *s->name + " final model");
+
6387 WriteLineIndent("public final class " + *s->name + "FinalModel extends " + domain + "fbe." + "Model");
+
6388 WriteLineIndent("{");
+
6389 Indent(1);
+
6390
+
6391 // Generate struct model final accessor
+
6392 WriteLineIndent("private final FinalModel" + *s->name + " _model;");
+
6393
+
6394 // Generate struct model final constructors
+
6395 WriteLine();
+
6396 WriteLineIndent("public " + *s->name + "FinalModel() { _model = new FinalModel" + *s->name + "(getBuffer(), 8); }");
+
6397 WriteLineIndent("public " + *s->name + "FinalModel(" + domain + "fbe.Buffer buffer) { super(buffer); _model = new FinalModel" + *s->name + "(getBuffer(), 8); }");
+
6398
+
6399 // Generate struct model final FBE properties
+
6400 WriteLine();
+
6401 WriteLineIndent("// Get the model type");
+
6402 WriteLineIndent("public static final long fbeTypeConst = FinalModel" + *s->name + ".fbeTypeConst;");
+
6403 WriteLineIndent("public long fbeType() { return fbeTypeConst; }");
+
6404
+
6405 // Generate struct model final verify() method
+
6406 WriteLine();
+
6407 WriteLineIndent("// Check if the struct value is valid");
+
6408 WriteLineIndent("public boolean verify()");
+
6409 WriteLineIndent("{");
+
6410 Indent(1);
+
6411 WriteLineIndent("if ((getBuffer().getOffset() + _model.fbeOffset()) > getBuffer().getSize())");
+
6412 Indent(1);
+
6413 WriteLineIndent("return false;");
+
6414 Indent(-1);
+
6415 WriteLine();
+
6416 WriteLineIndent("int fbeStructSize = readInt32(_model.fbeOffset() - 8);");
+
6417 WriteLineIndent("int fbeStructType = readInt32(_model.fbeOffset() - 4);");
+
6418 WriteLineIndent("if ((fbeStructSize <= 0) || (fbeStructType != fbeType()))");
+
6419 Indent(1);
+
6420 WriteLineIndent("return false;");
+
6421 Indent(-1);
+
6422 WriteLine();
+
6423 WriteLineIndent("return ((8 + _model.verify()) == fbeStructSize);");
+
6424 Indent(-1);
+
6425 WriteLineIndent("}");
+
6426
+
6427 // Generate struct model final serialize() method
+
6428 WriteLine();
+
6429 WriteLineIndent("// Serialize the struct value");
+
6430 WriteLineIndent("public long serialize(" + struct_name + " value)");
+
6431 WriteLineIndent("{");
+
6432 Indent(1);
+
6433 WriteLineIndent("long fbeInitialSize = getBuffer().getSize();");
+
6434 WriteLine();
+
6435 WriteLineIndent("int fbeStructType = (int)fbeType();");
+
6436 WriteLineIndent("int fbeStructSize = (int)(8 + _model.fbeAllocationSize(value));");
+
6437 WriteLineIndent("int fbeStructOffset = (int)(getBuffer().allocate(fbeStructSize) - getBuffer().getOffset());");
+
6438 WriteLineIndent("assert ((getBuffer().getOffset() + fbeStructOffset + fbeStructSize) <= getBuffer().getSize()) : \"Model is broken!\";");
+
6439 WriteLineIndent("if ((getBuffer().getOffset() + fbeStructOffset + fbeStructSize) > getBuffer().getSize())");
+
6440 Indent(1);
+
6441 WriteLineIndent("return 0;");
+
6442 Indent(-1);
+
6443 WriteLine();
+
6444 WriteLineIndent("fbeStructSize = (int)(8 + _model.set(value));");
+
6445 WriteLineIndent("getBuffer().resize(fbeInitialSize + fbeStructSize);");
+
6446 WriteLine();
+
6447 WriteLineIndent("write(_model.fbeOffset() - 8, fbeStructSize);");
+
6448 WriteLineIndent("write(_model.fbeOffset() - 4, fbeStructType);");
+
6449 WriteLine();
+
6450 WriteLineIndent("return fbeStructSize;");
+
6451 Indent(-1);
+
6452 WriteLineIndent("}");
+
6453
+
6454 // Generate struct model final deserialize() methods
+
6455 WriteLine();
+
6456 WriteLineIndent("// Deserialize the struct value");
+
6457 WriteLineIndent("public " + struct_name + " deserialize() { var value = new " + struct_name + "(); deserialize(value); return value; }");
+
6458 WriteLineIndent("public long deserialize(" + struct_name + " value)");
+
6459 WriteLineIndent("{");
+
6460 Indent(1);
+
6461 WriteLineIndent("assert ((getBuffer().getOffset() + _model.fbeOffset()) <= getBuffer().getSize()) : \"Model is broken!\";");
+
6462 WriteLineIndent("if ((getBuffer().getOffset() + _model.fbeOffset()) > getBuffer().getSize())");
+
6463 Indent(1);
+
6464 WriteLineIndent("return 0;");
+
6465 Indent(-1);
+
6466 WriteLine();
+
6467 WriteLineIndent("long fbeStructSize = readInt32(_model.fbeOffset() - 8);");
+
6468 WriteLineIndent("long fbeStructType = readInt32(_model.fbeOffset() - 4);");
+
6469 WriteLineIndent("assert ((fbeStructSize > 0) && (fbeStructType == fbeType())) : \"Model is broken!\";");
+
6470 WriteLineIndent("if ((fbeStructSize <= 0) || (fbeStructType != fbeType()))");
+
6471 Indent(1);
+
6472 WriteLineIndent("return 8;");
+
6473 Indent(-1);
+
6474 WriteLine();
+
6475 WriteLineIndent("var fbeSize = new " + domain + "fbe.Size();");
+
6476 WriteLineIndent("value = _model.get(fbeSize, value);");
+
6477 WriteLineIndent("return 8 + fbeSize.value;");
+
6478 Indent(-1);
+
6479 WriteLineIndent("}");
+
6480
+
6481 // Generate struct model final next() method
+
6482 WriteLine();
+
6483 WriteLineIndent("// Move to the next struct value");
+
6484 WriteLineIndent("public void next(long prev)");
+
6485 WriteLineIndent("{");
+
6486 Indent(1);
+
6487 WriteLineIndent("_model.fbeShift(prev);");
+
6488 Indent(-1);
+
6489 WriteLineIndent("}");
+
6490
+
6491 // Generate struct model final end
+
6492 Indent(-1);
+
6493 WriteLineIndent("}");
+
6494
+
6495 // Generate footer
+
6496 GenerateFooter();
+
6497
+
6498 // Store the file
+
6499 WriteEnd();
+
6500 Store(file);
+
6501}
+
6502
+
6503void GeneratorJava::GenerateProtocolVersion(const std::shared_ptr<Package>& p)
+
6504{
+
6505 std::string domain = (p->domain && !p->domain->empty()) ? (*p->domain + ".") : "";
+
6506 std::string package = *p->name;
+
6507
+
6508 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "fbe";
+
6509
+
6510 // Create package path
+
6511 CppCommon::Directory::CreateTree(path);
+
6512
+
6513 // Generate the file
+
6514 CppCommon::Path file = path / ("ProtocolVersion.java");
+
6515 WriteBegin();
+
6516
+
6517 // Generate headers
+
6518 GenerateHeader(CppCommon::Path(_input).filename().string());
+
6519 GenerateImports(domain, package + ".fbe");
+
6520
+
6521 // Generate protocol version class
+
6522 WriteLine();
+
6523 WriteLineIndent("// Fast Binary Encoding " + domain + *p->name + " protocol version");
+
6524 WriteLineIndent("public final class ProtocolVersion");
+
6525 WriteLineIndent("{");
+
6526 Indent(1);
+
6527 WriteLineIndent("// Protocol major version");
+
6528 WriteLineIndent("public static final int Major = " + std::to_string(p->version->major) + ";");
+
6529 WriteLineIndent("// Protocol minor version");
+
6530 WriteLineIndent("public static final int Minor = " + std::to_string(p->version->minor) + ";");
+
6531 Indent(-1);
+
6532 WriteLineIndent("}");
+
6533
+
6534 // Generate footer
+
6535 GenerateFooter();
+
6536
+
6537 // Store the file
+
6538 WriteEnd();
+
6539 Store(file);
+
6540}
+
6541
+
6542void GeneratorJava::GenerateSender(const std::shared_ptr<Package>& p, bool final)
+
6543{
+
6544 std::string domain = (p->domain && !p->domain->empty()) ? (*p->domain + ".") : "";
+
6545 std::string package = *p->name;
+
6546
+
6547 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "fbe";
+
6548
+
6549 // Create package path
+
6550 CppCommon::Directory::CreateTree(path);
+
6551
+
6552 std::string sender = (final ? "FinalSender" : "Sender");
+
6553 std::string model = (final ? "FinalModel" : "Model");
+
6554
+
6555 // Generate the file
+
6556 CppCommon::Path file = path / (sender + ".java");
+
6557 WriteBegin();
+
6558
+
6559 // Generate headers
+
6560 GenerateHeader(CppCommon::Path(_input).filename().string());
+
6561 GenerateImports(domain, package + ".fbe");
+
6562
+
6563 // Generate sender begin
+
6564 WriteLine();
+
6565 if (final)
+
6566 WriteLineIndent("// Fast Binary Encoding " + domain + *p->name + " final sender");
+
6567 else
+
6568 WriteLineIndent("// Fast Binary Encoding " + domain + *p->name + " sender");
+
6569 WriteLineIndent("public class " + sender + " extends " + domain + "fbe.Sender");
+
6570 WriteLineIndent("{");
+
6571 Indent(1);
+
6572
+
6573 // Generate imported senders accessors
+
6574 if (p->import)
+
6575 {
+
6576 WriteLineIndent("// Imported senders");
+
6577 for (const auto& import : p->import->imports)
+
6578 WriteLineIndent("public final " + domain + *import + ".fbe." + sender + " " + *import + "Sender;");
+
6579 WriteLine();
+
6580 }
+
6581
+
6582 // Generate sender models accessors
+
6583 if (p->body)
+
6584 {
+
6585 WriteLineIndent("// Sender models accessors");
+
6586 for (const auto& s : p->body->structs)
+
6587 if (s->message)
+
6588 WriteLineIndent("public final " + *s->name + model + " " + *s->name + "Model;");
+
6589 WriteLine();
+
6590 }
+
6591
+
6592 // Generate sender constructors
+
6593 WriteLineIndent("public " + sender + "()");
+
6594 WriteLineIndent("{");
+
6595 Indent(1);
+
6596 WriteLineIndent("super(" + std::string(final ? "true" : "false") + ");");
+
6597 if (p->import)
+
6598 {
+
6599 for (const auto& import : p->import->imports)
+
6600 WriteLineIndent(*import + "Sender = new " + domain + *import + ".fbe." + sender + "(getBuffer());");
+
6601 }
+
6602 if (p->body)
+
6603 {
+
6604 for (const auto& s : p->body->structs)
+
6605 if (s->message)
+
6606 WriteLineIndent(*s->name + "Model = new " + *s->name + model + "(getBuffer());");
+
6607 }
+
6608 Indent(-1);
+
6609 WriteLineIndent("}");
+
6610 WriteLineIndent("public " + sender + "(" + domain + "fbe.Buffer buffer)");
+
6611 WriteLineIndent("{");
+
6612 Indent(1);
+
6613 WriteLineIndent("super(buffer, " + std::string(final ? "true" : "false") + ");");
+
6614 if (p->import)
+
6615 {
+
6616 for (const auto& import : p->import->imports)
+
6617 WriteLineIndent(*import + "Sender = new " + domain + *import + ".fbe." + sender + "(getBuffer());");
+
6618 }
+
6619 if (p->body)
+
6620 {
+
6621 for (const auto& s : p->body->structs)
+
6622 if (s->message)
+
6623 WriteLineIndent(*s->name + "Model = new " + *s->name + model + "(getBuffer());");
+
6624 }
+
6625 Indent(-1);
+
6626 WriteLineIndent("}");
+
6627 WriteLine();
+
6628
+
6629 // Generate generic sender method
+
6630 WriteLineIndent("public long send(Object obj)");
+
6631 WriteLineIndent("{");
+
6632 Indent(1);
+
6633 if (p->body)
+
6634 {
+
6635 for (const auto& s : p->body->structs)
+
6636 {
+
6637 if (s->message)
+
6638 {
+
6639 std::string struct_name = domain + *p->name + "." + *s->name;
+
6640 WriteLineIndent("if (obj instanceof " + struct_name + ")");
+
6641 WriteLineIndent("{");
+
6642 Indent(1);
+
6643 WriteLineIndent(struct_name + " value = (" + struct_name + ")obj;");
+
6644 WriteLineIndent("if (value.fbeType() == " + *s->name + "Model.fbeType())");
+
6645 Indent(1);
+
6646 WriteLineIndent("return send(value);");
+
6647 Indent(-1);
+
6648 Indent(-1);
+
6649 WriteLineIndent("}");
+
6650 }
+
6651 }
+
6652 }
+
6653 WriteLine();
+
6654 if (p->import)
+
6655 {
+
6656 WriteLineIndent("// Try to send using imported senders");
+
6657 WriteLineIndent("long result = 0;");
+
6658 for (const auto& import : p->import->imports)
+
6659 {
+
6660 WriteLineIndent("result = " + *import + "Sender.send(obj);");
+
6661 WriteLineIndent("if (result > 0)");
+
6662 Indent(1);
+
6663 WriteLineIndent("return result;");
+
6664 Indent(-1);
+
6665 }
+
6666 WriteLine();
+
6667 }
+
6668 WriteLineIndent("return 0;");
+
6669 Indent(-1);
+
6670 WriteLineIndent("}");
+
6671 WriteLine();
+
6672
+
6673 // Generate sender methods
+
6674 if (p->body)
+
6675 {
+
6676 for (const auto& s : p->body->structs)
+
6677 {
+
6678 if (s->message)
+
6679 {
+
6680 std::string struct_name = domain + *p->name + "." + *s->name;
+
6681 WriteLineIndent("public long send(" + struct_name + " value)");
+
6682 WriteLineIndent("{");
+
6683 Indent(1);
+
6684 WriteLineIndent("// Serialize the value into the FBE stream");
+
6685 WriteLineIndent("long serialized = " + *s->name + "Model.serialize(value);");
+
6686 WriteLineIndent("assert (serialized > 0) : \"" + struct_name + " serialization failed!\";");
+
6687 WriteLineIndent("assert " + *s->name + "Model.verify() : \"" + struct_name + " validation failed!\";");
+
6688 WriteLine();
+
6689 WriteLineIndent("// Log the value");
+
6690 WriteLineIndent("if (getLogging())");
+
6691 WriteLineIndent("{");
+
6692 Indent(1);
+
6693 WriteLineIndent("String message = value.toString();");
+
6694 WriteLineIndent("onSendLog(message);");
+
6695 Indent(-1);
+
6696 WriteLineIndent("}");
+
6697 WriteLine();
+
6698 WriteLineIndent("// Send the serialized value");
+
6699 WriteLineIndent("return sendSerialized(serialized);");
+
6700 Indent(-1);
+
6701 WriteLineIndent("}");
+
6702 }
+
6703 }
+
6704 }
+
6705
+
6706 // Generate sender message handler
+
6707 WriteLine();
+
6708 WriteLineIndent("// Send message handler");
+
6709 WriteLineIndent("@Override");
+
6710 WriteLineIndent("protected long onSend(byte[] buffer, long offset, long size) { throw new UnsupportedOperationException(\"" + domain + *p->name + ".fbe.Sender.onSend() not implemented!\"); }");
+
6711
+
6712 // Generate sender end
+
6713 Indent(-1);
+
6714 WriteLineIndent("}");
+
6715
+
6716 // Generate footer
+
6717 GenerateFooter();
+
6718
+
6719 // Store the file
+
6720 WriteEnd();
+
6721 Store(file);
+
6722}
+
6723
+
6724void GeneratorJava::GenerateReceiver(const std::shared_ptr<Package>& p, bool final)
+
6725{
+
6726 std::string domain = (p->domain && !p->domain->empty()) ? (*p->domain + ".") : "";
+
6727 std::string package = *p->name;
+
6728
+
6729 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "fbe";
+
6730
+
6731 // Create package path
+
6732 CppCommon::Directory::CreateTree(path);
+
6733
+
6734 std::string receiver = (final ? "FinalReceiver" : "Receiver");
+
6735 std::string model = (final ? "FinalModel" : "Model");
+
6736
+
6737 // Generate the file
+
6738 CppCommon::Path file = path / (receiver + ".java");
+
6739 WriteBegin();
+
6740
+
6741 // Generate headers
+
6742 GenerateHeader(CppCommon::Path(_input).filename().string());
+
6743 GenerateImports(domain, package + ".fbe");
+
6744
+
6745 // Generate receiver begin
+
6746 WriteLine();
+
6747 if (final)
+
6748 WriteLineIndent("// Fast Binary Encoding " + domain + *p->name + " final receiver");
+
6749 else
+
6750 WriteLineIndent("// Fast Binary Encoding " + domain + *p->name + " receiver");
+
6751 WriteLineIndent("public class " + receiver + " extends " + domain + "fbe.Receiver");
+
6752 WriteLineIndent("{");
+
6753 Indent(1);
+
6754
+
6755 // Generate imported receivers accessors
+
6756 if (p->import)
+
6757 {
+
6758 WriteLineIndent("// Imported receivers");
+
6759 for (const auto& import : p->import->imports)
+
6760 WriteLineIndent("public " + domain + *import + ".fbe." + receiver + " " + *import + "Receiver;");
+
6761 WriteLine();
+
6762 }
+
6763
+
6764 // Generate receiver models accessors
+
6765 if (p->body)
+
6766 {
+
6767 WriteLineIndent("// Receiver values accessors");
+
6768 for (const auto& s : p->body->structs)
+
6769 {
+
6770 if (s->message)
+
6771 {
+
6772 std::string struct_name = domain + *p->name + "." + *s->name;
+
6773 WriteLineIndent("private final " + struct_name + " " + *s->name + "Value;");
+
6774 }
+
6775 }
+
6776 WriteLine();
+
6777 WriteLineIndent("// Receiver models accessors");
+
6778 for (const auto& s : p->body->structs)
+
6779 if (s->message)
+
6780 WriteLineIndent("private final " + *s->name + model + " " + *s->name + "Model;");
+
6781 WriteLine();
+
6782 }
+
6783
+
6784 // Generate receiver constructors
+
6785 WriteLineIndent("public " + receiver + "()");
+
6786 WriteLineIndent("{");
+
6787 Indent(1);
+
6788 WriteLineIndent("super(" + std::string(final ? "true" : "false") + ");");
+
6789 if (p->import)
+
6790 {
+
6791 for (const auto& import : p->import->imports)
+
6792 WriteLineIndent(*import + "Receiver = new " + domain + *import + ".fbe." + receiver + "(getBuffer());");
+
6793 }
+
6794 if (p->body)
+
6795 {
+
6796 for (const auto& s : p->body->structs)
+
6797 {
+
6798 if (s->message)
+
6799 {
+
6800 std::string struct_name = domain + *p->name + "." + *s->name;
+
6801 WriteLineIndent(*s->name + "Value = new " + struct_name + "();");
+
6802 WriteLineIndent(*s->name + "Model = new " + *s->name + model + "();");
+
6803 }
+
6804 }
+
6805 }
+
6806 Indent(-1);
+
6807 WriteLineIndent("}");
+
6808 WriteLineIndent("public " + receiver + "(" + domain + "fbe.Buffer buffer)");
+
6809 WriteLineIndent("{");
+
6810 Indent(1);
+
6811 WriteLineIndent("super(buffer, " + std::string(final ? "true" : "false") + ");");
+
6812 if (p->import)
+
6813 {
+
6814 for (const auto& import : p->import->imports)
+
6815 WriteLineIndent(*import + "Receiver = new " + domain + *import + ".fbe." + receiver + "(getBuffer());");
+
6816 }
+
6817 if (p->body)
+
6818 {
+
6819 for (const auto& s : p->body->structs)
+
6820 {
+
6821 if (s->message)
+
6822 {
+
6823 std::string struct_name = domain + *p->name + "." + *s->name;
+
6824 WriteLineIndent(*s->name + "Value = new " + struct_name + "();");
+
6825 WriteLineIndent(*s->name + "Model = new " + *s->name + model + "();");
+
6826 }
+
6827 }
+
6828 }
+
6829 Indent(-1);
+
6830 WriteLineIndent("}");
+
6831 WriteLine();
+
6832
+
6833 // Generate receiver handlers
+
6834 if (p->body)
+
6835 {
+
6836 WriteLineIndent("// Receive handlers");
+
6837 for (const auto& s : p->body->structs)
+
6838 {
+
6839 if (s->message)
+
6840 {
+
6841 std::string struct_name = domain + *p->name + "." + *s->name;
+
6842 WriteLineIndent("protected void onReceive(" + struct_name + " value) {}");
+
6843 }
+
6844 }
+
6845 WriteLine();
+
6846 }
+
6847
+
6848 // Generate receiver message handler
+
6849 WriteLineIndent("@Override");
+
6850 WriteLineIndent("public boolean onReceive(long type, byte[] buffer, long offset, long size)");
+
6851 WriteLineIndent("{");
+
6852 Indent(1);
+
6853 if (p->body)
+
6854 {
+
6855 WriteLineIndent("switch ((int)type)");
+
6856 WriteLineIndent("{");
+
6857 Indent(1);
+
6858 for (const auto& s : p->body->structs)
+
6859 {
+
6860 if (s->message)
+
6861 {
+
6862 WriteLineIndent("case (int)" + domain + package + ".fbe." + *s->name + model + ".fbeTypeConst:");
+
6863 WriteLineIndent("{");
+
6864 Indent(1);
+
6865 WriteLineIndent("// Deserialize the value from the FBE stream");
+
6866 WriteLineIndent(*s->name + "Model.attach(buffer, offset);");
+
6867 WriteLineIndent("assert " + *s->name + "Model.verify() : \"" + *p->name + "." + *s->name + " validation failed!\";");
+
6868 WriteLineIndent("long deserialized = " + *s->name + "Model.deserialize(" + *s->name + "Value);");
+
6869 WriteLineIndent("assert (deserialized > 0) : \"" + *p->name + "." + *s->name + " deserialization failed!\";");
+
6870 WriteLine();
+
6871 WriteLineIndent("// Log the value");
+
6872 WriteLineIndent("if (getLogging())");
+
6873 WriteLineIndent("{");
+
6874 Indent(1);
+
6875 WriteLineIndent("String message = " + *s->name + "Value.toString();");
+
6876 WriteLineIndent("onReceiveLog(message);");
+
6877 Indent(-1);
+
6878 WriteLineIndent("}");
+
6879 WriteLine();
+
6880 WriteLineIndent("// Call receive handler with deserialized value");
+
6881 WriteLineIndent("onReceive(" + *s->name + "Value);");
+
6882 WriteLineIndent("return true;");
+
6883 Indent(-1);
+
6884 WriteLineIndent("}");
+
6885 }
+
6886 }
+
6887 WriteLineIndent("default: break;");
+
6888 Indent(-1);
+
6889 WriteLineIndent("}");
+
6890 }
+
6891 if (p->import)
+
6892 {
+
6893 WriteLine();
+
6894 for (const auto& import : p->import->imports)
+
6895 {
+
6896 WriteLineIndent("if ((" + *import + "Receiver != null) && " + *import + "Receiver.onReceive(type, buffer, offset, size))");
+
6897 Indent(1);
+
6898 WriteLineIndent("return true;");
+
6899 Indent(-1);
+
6900 }
+
6901 }
+
6902 WriteLine();
+
6903 WriteLineIndent("return false;");
+
6904 Indent(-1);
+
6905 WriteLineIndent("}");
+
6906
+
6907 // Generate receiver end
+
6908 Indent(-1);
+
6909 WriteLineIndent("}");
+
6910
+
6911 // Generate footer
+
6912 GenerateFooter();
+
6913
+
6914 // Store the file
+
6915 WriteEnd();
+
6916 Store(file);
+
6917}
+
6918
+
6919void GeneratorJava::GenerateProxy(const std::shared_ptr<Package>& p, bool final)
+
6920{
+
6921 std::string domain = (p->domain && !p->domain->empty()) ? (*p->domain + ".") : "";
+
6922 std::string package = *p->name;
+
6923
+
6924 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "fbe";
+
6925
+
6926 // Create package path
+
6927 CppCommon::Directory::CreateTree(path);
+
6928
+
6929 std::string proxy = (final ? "FinalProxy" : "Proxy");
+
6930 std::string model = (final ? "FinalModel" : "Model");
+
6931
+
6932 // Generate the file
+
6933 CppCommon::Path file = path / (proxy + ".java");
+
6934 WriteBegin();
+
6935
+
6936 // Generate headers
+
6937 GenerateHeader(CppCommon::Path(_input).filename().string());
+
6938 GenerateImports(domain, package + ".fbe");
+
6939
+
6940 // Generate proxy begin
+
6941 WriteLine();
+
6942 if (final)
+
6943 WriteLineIndent("// Fast Binary Encoding " + domain + *p->name + " final proxy");
+
6944 else
+
6945 WriteLineIndent("// Fast Binary Encoding " + domain + *p->name + " proxy");
+
6946 WriteLineIndent("public class " + proxy + " extends " + domain + "fbe.Receiver");
+
6947 WriteLineIndent("{");
+
6948 Indent(1);
+
6949
+
6950 // Generate imported proxy accessors
+
6951 if (p->import)
+
6952 {
+
6953 WriteLineIndent("// Imported proxy");
+
6954 for (const auto& import : p->import->imports)
+
6955 WriteLineIndent("public " + domain + *import + ".fbe." + proxy + " " + *import + "Proxy;");
+
6956 WriteLine();
+
6957 }
+
6958
+
6959 // Generate proxy models accessors
+
6960 if (p->body)
+
6961 {
+
6962 WriteLineIndent("// Proxy models accessors");
+
6963 for (const auto& s : p->body->structs)
+
6964 if (s->message)
+
6965 WriteLineIndent("private final " + *s->name + model + " " + *s->name + "Model;");
+
6966 WriteLine();
+
6967 }
+
6968
+
6969 // Generate proxy constructors
+
6970 WriteLineIndent("public " + proxy + "()");
+
6971 WriteLineIndent("{");
+
6972 Indent(1);
+
6973 WriteLineIndent("super(" + std::string(final ? "true" : "false") + ");");
+
6974 if (p->import)
+
6975 {
+
6976 for (const auto& import : p->import->imports)
+
6977 WriteLineIndent(*import + "Proxy = new " + domain + *import + ".fbe." + proxy + "(getBuffer());");
+
6978 }
+
6979 if (p->body)
+
6980 {
+
6981 for (const auto& s : p->body->structs)
+
6982 if (s->message)
+
6983 WriteLineIndent(*s->name + "Model = new " + *s->name + model + "();");
+
6984 }
+
6985 Indent(-1);
+
6986 WriteLineIndent("}");
+
6987 WriteLineIndent("public " + proxy + "(" + domain + "fbe.Buffer buffer)");
+
6988 WriteLineIndent("{");
+
6989 Indent(1);
+
6990 WriteLineIndent("super(buffer, " + std::string(final ? "true" : "false") + ");");
+
6991 if (p->import)
+
6992 {
+
6993 for (const auto& import : p->import->imports)
+
6994 WriteLineIndent(*import + "Proxy = new " + domain + *import + ".fbe." + proxy + "(getBuffer());");
+
6995 }
+
6996 if (p->body)
+
6997 {
+
6998 for (const auto& s : p->body->structs)
+
6999 if (s->message)
+
7000 WriteLineIndent(*s->name + "Model = new " + *s->name + model + "();");
+
7001 }
+
7002 Indent(-1);
+
7003 WriteLineIndent("}");
+
7004 WriteLine();
+
7005
+
7006 // Generate proxy handlers
+
7007 if (p->body)
+
7008 {
+
7009 WriteLineIndent("// Proxy handlers");
+
7010 for (const auto& s : p->body->structs)
+
7011 {
+
7012 if (s->message)
+
7013 {
+
7014 std::string struct_model = *s->name + model;
+
7015 WriteLineIndent("protected void onProxy(" + struct_model + " model, long type, byte[] buffer, long offset, long size) {}");
+
7016 }
+
7017 }
+
7018 WriteLine();
+
7019 }
+
7020
+
7021 // Generate proxy message handler
+
7022 WriteLineIndent("@Override");
+
7023 WriteLineIndent("public boolean onReceive(long type, byte[] buffer, long offset, long size)");
+
7024 WriteLineIndent("{");
+
7025 Indent(1);
+
7026 if (p->body)
+
7027 {
+
7028 WriteLineIndent("switch ((int)type)");
+
7029 WriteLineIndent("{");
+
7030 Indent(1);
+
7031 for (const auto& s : p->body->structs)
+
7032 {
+
7033 if (s->message)
+
7034 {
+
7035 WriteLineIndent("case (int)" + domain + package + ".fbe." + *s->name + model + ".fbeTypeConst:");
+
7036 WriteLineIndent("{");
+
7037 Indent(1);
+
7038 WriteLineIndent("// Attach the FBE stream to the proxy model");
+
7039 WriteLineIndent(*s->name + "Model.attach(buffer, offset);");
+
7040 WriteLineIndent("assert " + *s->name + "Model.verify() : \"" + *p->name + "." + *s->name + " validation failed!\";");
+
7041 WriteLine();
+
7042 WriteLineIndent("long fbeBegin = " + *s->name + "Model.model.getBegin();");
+
7043 WriteLineIndent("if (fbeBegin == 0)");
+
7044 Indent(1);
+
7045 WriteLineIndent("return false;");
+
7046 Indent(-1);
+
7047 WriteLineIndent("// Call proxy handler");
+
7048 WriteLineIndent("onProxy(" + *s->name + "Model, type, buffer, offset, size);");
+
7049 WriteLineIndent(*s->name + "Model.model.getEnd(fbeBegin);");
+
7050 WriteLineIndent("return true;");
+
7051 Indent(-1);
+
7052 WriteLineIndent("}");
+
7053 }
+
7054 }
+
7055 WriteLineIndent("default: break;");
+
7056 Indent(-1);
+
7057 WriteLineIndent("}");
+
7058 }
+
7059 if (p->import)
+
7060 {
+
7061 WriteLine();
+
7062 for (const auto& import : p->import->imports)
+
7063 {
+
7064 WriteLineIndent("if ((" + *import + "Proxy != null) && " + *import + "Proxy.onReceive(type, buffer, offset, size))");
+
7065 Indent(1);
+
7066 WriteLineIndent("return true;");
+
7067 Indent(-1);
+
7068 }
+
7069 }
+
7070 WriteLine();
+
7071 WriteLineIndent("return false;");
+
7072 Indent(-1);
+
7073 WriteLineIndent("}");
+
7074
+
7075 // Generate proxy end
+
7076 Indent(-1);
+
7077 WriteLineIndent("}");
+
7078
+
7079 // Generate footer
+
7080 GenerateFooter();
+
7081
+
7082 // Store the file
+
7083 WriteEnd();
+
7084 Store(file);
+
7085}
+
7086
+
7087void GeneratorJava::GenerateJson(const std::shared_ptr<Package>& p)
+
7088{
+
7089 std::string domain = (p->domain && !p->domain->empty()) ? (*p->domain + ".") : "";
+
7090 std::string package = *p->name;
+
7091
+
7092 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "fbe";
+
7093
+
7094 // Create package path
+
7095 CppCommon::Directory::CreateTree(path);
+
7096
+
7097 // Generate the file
+
7098 CppCommon::Path file = path / "Json.java";
+
7099 WriteBegin();
+
7100
+
7101 // Generate headers
+
7102 GenerateHeader(CppCommon::Path(_input).filename().string());
+
7103 GenerateImports(domain, package + ".fbe");
+
7104
+
7105 // Generate JSON engine begin
+
7106 WriteLine();
+
7107 WriteLineIndent("// Fast Binary Encoding " + *p->name + " JSON engine");
+
7108 WriteLineIndent("public final class Json");
+
7109 WriteLineIndent("{");
+
7110 Indent(1);
+
7111
+
7112 WriteLineIndent("private static final com.google.gson.Gson _engine;");
+
7113 WriteLine();
+
7114 WriteLineIndent("// Get the JSON engine");
+
7115 WriteLineIndent("public static com.google.gson.Gson getEngine() { return _engine; }");
+
7116 WriteLine();
+
7117
+
7118 // Generate JSON engine static initialization
+
7119 WriteLineIndent("static");
+
7120 WriteLineIndent("{");
+
7121 Indent(1);
+
7122 WriteLineIndent("_engine = register(new com.google.gson.GsonBuilder()).create();");
+
7123 Indent(-1);
+
7124 WriteLineIndent("}");
+
7125 WriteLine();
+
7126
+
7127 // Generate JSON engine private constructor
+
7128 WriteLineIndent("private Json() {}");
+
7129 WriteLine();
+
7130
+
7131 // Generate JSON engine Register() method
+
7132 WriteLineIndent("public static com.google.gson.GsonBuilder register(com.google.gson.GsonBuilder builder)");
+
7133 WriteLineIndent("{");
+
7134 Indent(1);
+
7135 WriteLineIndent(domain + "fbe.Json.register(builder);");
+
7136 if (p->import)
+
7137 {
+
7138 for (const auto& import : p->import->imports)
+
7139 WriteLineIndent(domain + *import + ".fbe.Json.register(builder);");
+
7140 }
+
7141 if (p->body)
+
7142 {
+
7143 for (const auto& e : p->body->enums)
+
7144 WriteLineIndent("builder.registerTypeAdapter(" + domain + package + "." + *e->name + ".class, new " + *e->name + "Json());");
+
7145 for (const auto& f : p->body->flags)
+
7146 WriteLineIndent("builder.registerTypeAdapter(" + domain + package + "." + *f->name + ".class, new " + *f->name + "Json());");
+
7147 }
+
7148 WriteLineIndent("return builder;");
+
7149 Indent(-1);
+
7150 WriteLineIndent("}");
+
7151
+
7152 // Generate JSON engine end
+
7153 Indent(-1);
+
7154 WriteLineIndent("}");
+
7155
+
7156 // Generate footer
+
7157 GenerateFooter();
+
7158
+
7159 // Store the file
+
7160 WriteEnd();
+
7161 Store(file);
+
7162}
+
7163
+
7164bool GeneratorJava::IsKnownType(const std::string& type)
+
7165{
+
7166 return ((type == "bool") ||
+
7167 (type == "byte") || (type == "bytes") ||
+
7168 (type == "char") || (type == "wchar") ||
+
7169 (type == "int8") || (type == "uint8") ||
+
7170 (type == "int16") || (type == "uint16") ||
+
7171 (type == "int32") || (type == "uint32") ||
+
7172 (type == "int64") || (type == "uint64") ||
+
7173 (type == "float") || (type == "double") ||
+
7174 (type == "decimal") || (type == "string") ||
+
7175 (type == "timestamp") || (type == "uuid"));
+
7176}
+
7177
+
7178bool GeneratorJava::IsImportedType(const std::string& type)
+
7179{
+
7180 size_t pos = type.find_last_of('.');
+
7181 return (pos != std::string::npos);
+
7182}
+
7183
+
7184bool GeneratorJava::IsPackageType(const std::string& type)
+
7185{
+
7186 if (IsKnownType(type) || IsImportedType(type))
+
7187 return true;
+
7188
+
7189 return ((type == "Boolean") ||
+
7190 (type == "Byte") || (type == "java.nio.ByteBuffer") ||
+
7191 (type == "Character") ||
+
7192 (type == "Byte") || (type == "UByte") ||
+
7193 (type == "Short") || (type == "UShort") ||
+
7194 (type == "Integer") || (type == "UInteger") ||
+
7195 (type == "Long") || (type == "ULong") ||
+
7196 (type == "Float") || (type == "Double") ||
+
7197 (type == "java.math.BigDecimal") || (type == "java.math.BigInteger") ||
+
7198 (type == "String") || (type == "java.util.Date") || (type == "java.time.Instant") || (type == "java.util.UUID"));
+
7199}
+
7200
+
7201bool GeneratorJava::IsPrimitiveType(const std::string& type, bool optional)
+
7202{
+
7203 if (optional)
+
7204 return false;
+
7205
+
7206 return ((type == "bool") || (type == "byte") ||
+
7207 (type == "char") || (type == "wchar") ||
+
7208 (type == "int8") || (type == "uint8") ||
+
7209 (type == "int16") || (type == "uint16") ||
+
7210 (type == "int32") || (type == "uint32") ||
+
7211 (type == "int64") || (type == "uint64") ||
+
7212 (type == "float") || (type == "double"));
+
7213}
+
7214
+
7215std::string GeneratorJava::CreatePackagePath(const std::string& domain, const std::string& package)
+
7216{
+
7217 std::string result = domain;
+
7218 CppCommon::StringUtils::ReplaceAll(result, ".", std::string(1, CppCommon::Path::separator()));
+
7219 return result + CppCommon::Path::separator() + package;
+
7220}
+
7221
+
7222std::string GeneratorJava::ConvertEnumBase(const std::string& type)
+
7223{
+
7224 if (type == "byte")
+
7225 return "Byte";
+
7226 else if (type == "char")
+
7227 return "Byte";
+
7228 else if (type == "wchar")
+
7229 return "Integer";
+
7230 else if (type == "int8")
+
7231 return "Byte";
+
7232 else if (type == "uint8")
+
7233 return "Byte";
+
7234 else if (type == "int16")
+
7235 return "Short";
+
7236 else if (type == "uint16")
+
7237 return "Short";
+
7238 else if (type == "int32")
+
7239 return "Integer";
+
7240 else if (type == "uint32")
+
7241 return "Integer";
+
7242 else if (type == "int64")
+
7243 return "Long";
+
7244 else if (type == "uint64")
+
7245 return "Long";
+
7246
+
7247 yyerror("Unsupported enum base type - " + type);
+
7248 return "";
+
7249}
+
7250
+
7251std::string GeneratorJava::ConvertEnumType(const std::string& type)
+
7252{
+
7253 if (type == "byte")
+
7254 return "byte";
+
7255 else if (type == "char")
+
7256 return "byte";
+
7257 else if (type == "wchar")
+
7258 return "int";
+
7259 else if (type == "int8")
+
7260 return "byte";
+
7261 else if (type == "uint8")
+
7262 return "byte";
+
7263 else if (type == "int16")
+
7264 return "short";
+
7265 else if (type == "uint16")
+
7266 return "short";
+
7267 else if (type == "int32")
+
7268 return "int";
+
7269 else if (type == "uint32")
+
7270 return "int";
+
7271 else if (type == "int64")
+
7272 return "long";
+
7273 else if (type == "uint64")
+
7274 return "long";
+
7275
+
7276 yyerror("Unsupported enum base type - " + type);
+
7277 return "";
+
7278}
+
7279
+
7280std::string GeneratorJava::ConvertEnumSize(const std::string& type)
+
7281{
+
7282 if (type == "byte")
+
7283 return "1";
+
7284 else if (type == "char")
+
7285 return "1";
+
7286 else if (type == "wchar")
+
7287 return "4";
+
7288 else if (type == "int8")
+
7289 return "1";
+
7290 else if (type == "uint8")
+
7291 return "1";
+
7292 else if (type == "int16")
+
7293 return "2";
+
7294 else if (type == "uint16")
+
7295 return "2";
+
7296 else if (type == "int32")
+
7297 return "4";
+
7298 else if (type == "uint32")
+
7299 return "4";
+
7300 else if (type == "int64")
+
7301 return "8";
+
7302 else if (type == "uint64")
+
7303 return "8";
+
7304
+
7305 yyerror("Unsupported enum base type - " + type);
+
7306 return "";
+
7307}
+
7308
+
7309std::string GeneratorJava::ConvertEnumGet(const std::string& type)
+
7310{
+
7311 if (type == "byte")
+
7312 return "getAsByte";
+
7313 else if (type == "char")
+
7314 return "getAsByte";
+
7315 else if (type == "wchar")
+
7316 return "getAsInt";
+
7317 else if (type == "int8")
+
7318 return "getAsByte";
+
7319 else if (type == "uint8")
+
7320 return "getAsByte";
+
7321 else if (type == "int16")
+
7322 return "getAsShort";
+
7323 else if (type == "uint16")
+
7324 return "getAsShort";
+
7325 else if (type == "int32")
+
7326 return "getAsInt";
+
7327 else if (type == "uint32")
+
7328 return "getAsInt";
+
7329 else if (type == "int64")
+
7330 return "getAsLong";
+
7331 else if (type == "uint64")
+
7332 return "getAsLong";
+
7333
+
7334 yyerror("Unsupported enum base type - " + type);
+
7335 return "";
+
7336}
+
7337
+
7338std::string GeneratorJava::ConvertEnumRead(const std::string& type)
+
7339{
+
7340 if (type == "byte")
+
7341 return "readByte";
+
7342 else if (type == "char")
+
7343 return "readInt8";
+
7344 else if (type == "wchar")
+
7345 return "readInt32";
+
7346 else if (type == "int8")
+
7347 return "readInt8";
+
7348 else if (type == "uint8")
+
7349 return "readInt8";
+
7350 else if (type == "int16")
+
7351 return "readInt16";
+
7352 else if (type == "uint16")
+
7353 return "readInt16";
+
7354 else if (type == "int32")
+
7355 return "readInt32";
+
7356 else if (type == "uint32")
+
7357 return "readInt32";
+
7358 else if (type == "int64")
+
7359 return "readInt64";
+
7360 else if (type == "uint64")
+
7361 return "readInt64";
+
7362
+
7363 yyerror("Unsupported enum base type - " + type);
+
7364 return "";
+
7365}
+
7366
+
7367std::string GeneratorJava::ConvertEnumConstant(const std::string& type, const std::string& value)
+
7368{
+
7369 std::string result = value;
+
7370
+
7371 if (type.empty())
+
7372 {
+
7373 // Fill flags values
+
7374 std::vector<std::string> flags = CppCommon::StringUtils::Split(value, '|', true);
+
7375
+
7376 // Generate flags combination
+
7377 if (!flags.empty())
+
7378 {
+
7379 result = "";
+
7380 bool first = true;
+
7381 for (const auto& it : flags)
+
7382 {
+
7383 result += (first ? "" : "|") + CppCommon::StringUtils::ToTrim(it) + ".getRaw()";
+
7384 first = false;
+
7385 }
+
7386 }
+
7387 }
+
7388
+
7389 return ConvertEnumConstantPrefix(type) + result + ConvertEnumConstantSuffix(type);
+
7390}
+
7391
+
7392std::string GeneratorJava::ConvertEnumConstantPrefix(const std::string& type)
+
7393{
+
7394 if (type == "byte")
+
7395 return "(byte)";
+
7396 else if (type == "char")
+
7397 return "(char)";
+
7398 else if (type == "wchar")
+
7399 return "(char)";
+
7400 else if (type == "int8")
+
7401 return "(byte)";
+
7402 else if (type == "uint8")
+
7403 return "(byte)";
+
7404 else if (type == "int16")
+
7405 return "(short)";
+
7406 else if (type == "uint16")
+
7407 return "(short)";
+
7408 else if (type == "int32")
+
7409 return "(int)";
+
7410 else if (type == "uint32")
+
7411 return "(int)";
+
7412 else if (type == "int64")
+
7413 return "(long)";
+
7414 else if (type == "uint64")
+
7415 return "(long)";
+
7416
+
7417 return "";
+
7418}
+
7419
+
7420std::string GeneratorJava::ConvertEnumConstantSuffix(const std::string& type)
+
7421{
+
7422 if ((type == "int64") || (type == "uint64"))
+
7423 return "L";
+
7424
+
7425 return "";
+
7426}
+
7427
+
7428std::string GeneratorJava::ConvertPrimitiveTypeName(const std::string& type)
+
7429{
+
7430 if (type == "bool")
+
7431 return "Boolean";
+
7432 else if (type == "byte")
+
7433 return "Byte";
+
7434 else if (type == "char")
+
7435 return "Character";
+
7436 else if (type == "wchar")
+
7437 return "Character";
+
7438 else if (type == "int8")
+
7439 return "Byte";
+
7440 else if (type == "uint8")
+
7441 return "Byte";
+
7442 else if (type == "int16")
+
7443 return "Short";
+
7444 else if (type == "uint16")
+
7445 return "Short";
+
7446 else if (type == "int32")
+
7447 return "Integer";
+
7448 else if (type == "uint32")
+
7449 return "Integer";
+
7450 else if (type == "int64")
+
7451 return "Long";
+
7452 else if (type == "uint64")
+
7453 return "Long";
+
7454 else if (type == "float")
+
7455 return "Float";
+
7456 else if (type == "double")
+
7457 return "Double";
+
7458
+
7459 return "";
+
7460}
+
7461
+
7462std::string GeneratorJava::ConvertTypeName(const std::string& domain, const std::string& package, const std::string& type, bool optional)
+
7463{
+
7464 if (optional)
+
7465 {
+
7466 if (type == "bool")
+
7467 return "Boolean";
+
7468 else if (type == "byte")
+
7469 return "Byte";
+
7470 else if (type == "char")
+
7471 return "Character";
+
7472 else if (type == "wchar")
+
7473 return "Character";
+
7474 else if (type == "int8")
+
7475 return "Byte";
+
7476 else if (type == "uint8")
+
7477 return "Byte";
+
7478 else if (type == "int16")
+
7479 return "Short";
+
7480 else if (type == "uint16")
+
7481 return "Short";
+
7482 else if (type == "int32")
+
7483 return "Integer";
+
7484 else if (type == "uint32")
+
7485 return "Integer";
+
7486 else if (type == "int64")
+
7487 return "Long";
+
7488 else if (type == "uint64")
+
7489 return "Long";
+
7490 else if (type == "float")
+
7491 return "Float";
+
7492 else if (type == "double")
+
7493 return "Double";
+
7494 }
+
7495
+
7496 if (type == "bool")
+
7497 return "boolean";
+
7498 else if (type == "byte")
+
7499 return "byte";
+
7500 else if (type == "bytes")
+
7501 return "java.nio.ByteBuffer";
+
7502 else if (type == "char")
+
7503 return "char";
+
7504 else if (type == "wchar")
+
7505 return "char";
+
7506 else if (type == "int8")
+
7507 return "byte";
+
7508 else if (type == "uint8")
+
7509 return "byte";
+
7510 else if (type == "int16")
+
7511 return "short";
+
7512 else if (type == "uint16")
+
7513 return "short";
+
7514 else if (type == "int32")
+
7515 return "int";
+
7516 else if (type == "uint32")
+
7517 return "int";
+
7518 else if (type == "int64")
+
7519 return "long";
+
7520 else if (type == "uint64")
+
7521 return "long";
+
7522 else if (type == "float")
+
7523 return "float";
+
7524 else if (type == "double")
+
7525 return "double";
+
7526 else if (type == "decimal")
+
7527 return "java.math.BigDecimal";
+
7528 else if (type == "string")
+
7529 return "String";
+
7530 else if (type == "timestamp")
+
7531 return ((Version() < 8) ? "java.util.Date" : "java.time.Instant");
+
7532 else if (type == "uuid")
+
7533 return "java.util.UUID";
+
7534
+
7535 std::string ns = "";
+
7536 std::string t = type;
+
7537
+
7538 size_t pos = type.find_last_of('.');
+
7539 if (pos != std::string::npos)
+
7540 {
+
7541 ns.assign(type, 0, pos + 1);
+
7542 ns = domain + ns;
+
7543 t.assign(type, pos + 1, type.size() - pos);
+
7544 }
+
7545 else if (!package.empty())
+
7546 ns = domain + package + ".";
+
7547
+
7548 return ns + t;
+
7549}
+
7550
+
7551std::string GeneratorJava::ConvertTypeName(const std::string& domain, const std::string& package, const StructField& field)
+
7552{
+
7553 if (field.array)
+
7554 return ConvertTypeName(domain, package, *field.type, field.optional) + "[]";
+
7555 else if (field.vector)
+
7556 return "java.util.ArrayList<" + ConvertTypeName(domain, package, *field.type, true) + ">";
+
7557 else if (field.list)
+
7558 return "java.util.LinkedList<" + ConvertTypeName(domain, package, *field.type, true) + ">";
+
7559 else if (field.set)
+
7560 return "java.util.HashSet<" + ConvertTypeName(domain, package, *field.key, true) + ">";
+
7561 else if (field.map)
+
7562 return "java.util.TreeMap<" + ConvertTypeName(domain, package, *field.key, true) + ", " + ConvertTypeName(domain, package, *field.type, true) +">";
+
7563 else if (field.hash)
+
7564 return "java.util.HashMap<" + ConvertTypeName(domain, package, *field.key, true) + ", " + ConvertTypeName(domain, package, *field.type, true) +">";
+
7565
+
7566 return ConvertTypeName(domain, package, *field.type, field.optional);
+
7567}
+
7568
+
7569std::string GeneratorJava::ConvertBaseFieldName(const std::string& domain, const std::string& type, bool final)
+
7570{
+
7571 std::string modelType = final ? "Final" : "Field";
+
7572
+
7573 std::string ns = "";
+
7574 std::string t = type;
+
7575
+
7576 size_t pos = type.find_last_of('.');
+
7577 if (pos != std::string::npos)
+
7578 {
+
7579 ns.assign(type, 0, pos + 1);
+
7580 ns.append("fbe.");
+
7581 ns = domain + ns;
+
7582 t.assign(type, pos + 1, type.size() - pos);
+
7583 }
+
7584
+
7585 return ns + modelType + "Model" + ConvertTypeFieldName(t);
+
7586}
+
7587
+
7588std::string GeneratorJava::ConvertTypeFieldName(const std::string& type)
+
7589{
+
7590 if (type == "bool")
+
7591 return "Boolean";
+
7592 else if (type == "byte")
+
7593 return "Byte";
+
7594 else if (type == "bytes")
+
7595 return "Bytes";
+
7596 else if (type == "char")
+
7597 return "Char";
+
7598 else if (type == "wchar")
+
7599 return "WChar";
+
7600 else if (type == "int8")
+
7601 return "Int8";
+
7602 else if (type == "uint8")
+
7603 return "Int8";
+
7604 else if (type == "int16")
+
7605 return "Int16";
+
7606 else if (type == "uint16")
+
7607 return "Int16";
+
7608 else if (type == "int32")
+
7609 return "Int32";
+
7610 else if (type == "uint32")
+
7611 return "Int32";
+
7612 else if (type == "int64")
+
7613 return "Int64";
+
7614 else if (type == "uint64")
+
7615 return "Int64";
+
7616 else if (type == "float")
+
7617 return "Float";
+
7618 else if (type == "double")
+
7619 return "Double";
+
7620 else if (type == "decimal")
+
7621 return "Decimal";
+
7622 else if (type == "string")
+
7623 return "String";
+
7624 else if (type == "timestamp")
+
7625 return ((Version() < 8) ? "Date" : "Timestamp");
+
7626 else if (type == "uuid")
+
7627 return "UUID";
+
7628
+
7629 std::string result = type;
+
7630 CppCommon::StringUtils::ReplaceAll(result, ".", "");
+
7631 return result;
+
7632}
+
7633
+
7634std::string GeneratorJava::ConvertTypeFieldType(const std::string& domain, const std::string& type, bool optional)
+
7635{
+
7636 if (type == "bool")
+
7637 return "Boolean";
+
7638 else if (type == "byte")
+
7639 return "Byte";
+
7640 else if (type == "bytes")
+
7641 return "java.nio.ByteBuffer";
+
7642 else if (type == "char")
+
7643 return "Character";
+
7644 else if (type == "wchar")
+
7645 return "Character";
+
7646 else if (type == "int8")
+
7647 return "Byte";
+
7648 else if (type == "uint8")
+
7649 return "Byte";
+
7650 else if (type == "int16")
+
7651 return "Short";
+
7652 else if (type == "uint16")
+
7653 return "Short";
+
7654 else if (type == "int32")
+
7655 return "Integer";
+
7656 else if (type == "uint32")
+
7657 return "Integer";
+
7658 else if (type == "int64")
+
7659 return "Long";
+
7660 else if (type == "uint64")
+
7661 return "Long";
+
7662 else if (type == "float")
+
7663 return "Float";
+
7664 else if (type == "double")
+
7665 return "Double";
+
7666 else if (type == "decimal")
+
7667 return "java.math.BigDecimal";
+
7668 else if (type == "string")
+
7669 return "String";
+
7670 else if (type == "timestamp")
+
7671 return ((Version() < 8) ? "java.util.Date" : "java.time.Instant");
+
7672 else if (type == "uuid")
+
7673 return "java.util.UUID";
+
7674
+
7675 std::string ns = "";
+
7676 std::string t = type;
+
7677
+
7678 size_t pos = type.find_last_of('.');
+
7679 if (pos != std::string::npos)
+
7680 {
+
7681 ns.assign(type, 0, pos + 1);
+
7682 ns = domain + ns;
+
7683 t.assign(type, pos + 1, type.size() - pos);
+
7684 }
+
7685
+
7686 return ns + t;
+
7687}
+
7688
+
7689std::string GeneratorJava::ConvertTypeFieldDeclaration(const std::string& domain, const std::string& type, bool optional, bool final)
+
7690{
+
7691 std::string modelType = final ? "Final" : "Field";
+
7692
+
7693 std::string ns = "";
+
7694 std::string opt = optional ? "Optional" : "";
+
7695 std::string t = type;
+
7696
+
7697 size_t pos = type.find_last_of('.');
+
7698 if (pos != std::string::npos)
+
7699 {
+
7700 ns.assign(type, 0, pos + 1);
+
7701 ns.append("fbe.");
+
7702 ns = domain + ns;
+
7703 t.assign(type, pos + 1, type.size() - pos);
+
7704 }
+
7705 else
+
7706 ns = (IsKnownType(type) && !optional) ? (domain + "fbe.") : "";
+
7707
+
7708 return ns + modelType + "Model" + opt + ConvertTypeFieldName(t);
+
7709}
+
7710
+
7711std::string GeneratorJava::ConvertTypeFieldDeclaration(const std::string& domain, const StructField& field, bool final)
+
7712{
+
7713 std::string modelType = final ? "Final" : "Field";
+
7714
+
7715 if (field.array)
+
7716 return modelType + "ModelArray" + std::string(field.optional ? "Optional" : "") + ConvertTypeFieldName(*field.type);
+
7717 else if (field.vector || field.list || field.set)
+
7718 return modelType + "ModelVector" + std::string(field.optional ? "Optional" : "") + ConvertTypeFieldName(*field.type);
+
7719 else if (field.map || field.hash)
+
7720 return modelType + "ModelMap" + ConvertTypeFieldName(*field.key) + std::string(field.optional ? "Optional" : "") + ConvertTypeFieldName(*field.type);
+
7721 else if (field.optional)
+
7722 return modelType + "ModelOptional" + ConvertTypeFieldName(*field.type);
+
7723
+
7724 return ConvertTypeFieldDeclaration(domain, *field.type, field.optional, final);
+
7725}
+
7726
+
7727std::string GeneratorJava::ConvertTypeFieldInitialization(const std::string& domain, const StructField& field, const std::string& offset, bool final)
+
7728{
+
7729 std::string modelType = final ? "Final" : "Field";
+
7730
+
7731 if (field.array)
+
7732 return "new " + modelType + "ModelArray" + std::string(field.optional ? "Optional" : "") + ConvertTypeFieldName(*field.type) + "(buffer, " + offset + ", " + std::to_string(field.N) + ")";
+
7733 else if (field.vector || field.list || field.set)
+
7734 return "new " + modelType + "ModelVector" + std::string(field.optional ? "Optional" : "") + ConvertTypeFieldName(*field.type) + "(buffer, " + offset + ")";
+
7735 else if (field.map || field.hash)
+
7736 return "new " + modelType + "ModelMap" + ConvertTypeFieldName(*field.key) + std::string(field.optional ? "Optional" : "") + ConvertTypeFieldName(*field.type) + "(buffer, " + offset + ")";
+
7737 else if (field.optional)
+
7738 return "new " + modelType + "ModelOptional" + ConvertTypeFieldName(*field.type) + "(buffer, " + offset + ")";
+
7739
+
7740 std::string ns = "";
+
7741 std::string t = *field.type;
+
7742 std::string type = *field.type;
+
7743
+
7744 size_t pos = type.find_last_of('.');
+
7745 if (pos != std::string::npos)
+
7746 {
+
7747 ns.assign(type, 0, pos + 1);
+
7748 ns.append("fbe.");
+
7749 ns = domain + ns;
+
7750 t.assign(type, pos + 1, type.size() - pos);
+
7751 }
+
7752 else
+
7753 ns = IsKnownType(type) ? (domain + "fbe.") : "";
+
7754
+
7755 return "new " + ns + modelType + "Model" + ConvertTypeFieldName(t) + "(buffer, " + offset + ")";
+
7756}
+
7757
+
7758std::string GeneratorJava::ConvertConstant(const std::string& domain, const std::string& package, const std::string& type, const std::string& value, bool optional)
+
7759{
+
7760 if (value == "true")
+
7761 return "true";
+
7762 else if (value == "false")
+
7763 return "false";
+
7764 else if (value == "null")
+
7765 return "null";
+
7766 else if (value == "min")
+
7767 {
+
7768 if ((type == "byte") || (type == "uint8") || (type == "uint16") || (type == "uint32") || (type == "uint64"))
+
7769 return ConvertConstantPrefix(type) + "0" + ConvertConstantSuffix(type);
+
7770 else if (type == "int8")
+
7771 return ConvertConstantPrefix(type) + "-128" + ConvertConstantSuffix(type);
+
7772 else if (type == "int16")
+
7773 return ConvertConstantPrefix(type) + "-32768" + ConvertConstantSuffix(type);
+
7774 else if (type == "int32")
+
7775 return ConvertConstantPrefix(type) + "-2147483648" + ConvertConstantSuffix(type);
+
7776 else if (type == "int64")
+
7777 return ConvertConstantPrefix(type) + "-9223372036854775808" + ConvertConstantSuffix(type);
+
7778
+
7779 yyerror("Unsupported type " + type + " for 'min' constant");
+
7780 return "";
+
7781 }
+
7782 else if (value == "max")
+
7783 {
+
7784 if (type == "byte")
+
7785 return ConvertConstantPrefix(type) + "0xFF" + ConvertConstantSuffix(type);
+
7786 else if (type == "int8")
+
7787 return ConvertConstantPrefix(type) + "127" + ConvertConstantSuffix(type);
+
7788 else if (type == "uint8")
+
7789 return ConvertConstantPrefix(type) + "0xFF" + ConvertConstantSuffix(type);
+
7790 else if (type == "int16")
+
7791 return ConvertConstantPrefix(type) + "32767" + ConvertConstantSuffix(type);
+
7792 else if (type == "uint16")
+
7793 return ConvertConstantPrefix(type) + "0xFFFF" + ConvertConstantSuffix(type);
+
7794 else if (type == "int32")
+
7795 return ConvertConstantPrefix(type) + "2147483647" + ConvertConstantSuffix(type);
+
7796 else if (type == "uint32")
+
7797 return ConvertConstantPrefix(type) + "0xFFFFFFFF" + ConvertConstantSuffix(type);
+
7798 else if (type == "int64")
+
7799 return ConvertConstantPrefix(type) + "9223372036854775807" + ConvertConstantSuffix(type);
+
7800 else if (type == "uint64")
+
7801 return ConvertConstantPrefix(type) + "0xFFFFFFFFFFFFFFFF" + ConvertConstantSuffix(type);
+
7802
+
7803 yyerror("Unsupported type " + type + " for 'max' constant");
+
7804 return "";
+
7805 }
+
7806 else if (value == "epoch")
+
7807 return ((Version() < 8) ? "new java.util.Date(0)" : "java.time.Instant.EPOCH");
+
7808 else if (value == "utc")
+
7809 return ((Version() < 8) ? "new java.util.Date(System.currentTimeMillis())" : "java.time.Instant.now()");
+
7810 else if (value == "uuid0")
+
7811 return domain + "fbe.UUIDGenerator.nil()";
+
7812 else if (value == "uuid1")
+
7813 return domain + "fbe.UUIDGenerator.sequential()";
+
7814 else if (value == "uuid4")
+
7815 return domain + "fbe.UUIDGenerator.random()";
+
7816
+
7817 std::string result = value;
+
7818
+
7819 if (!IsKnownType(type))
+
7820 {
+
7821 // Fill flags values
+
7822 std::vector<std::string> flags = CppCommon::StringUtils::Split(value, '|', true);
+
7823
+
7824 // Generate flags combination
+
7825 if (flags.size() > 1)
+
7826 {
+
7827 result = "";
+
7828 bool first = true;
+
7829 for (const auto& it : flags)
+
7830 {
+
7831 std::string flag = CppCommon::StringUtils::ToTrim(it);
+
7832 size_t pos = flag.find_last_of('.');
+
7833 if (pos != std::string::npos)
+
7834 {
+
7835 if (CppCommon::StringUtils::CountAll(flag, ".") > 1)
+
7836 flag = domain + flag;
+
7837 else
+
7838 flag = (package.empty() ? "" : (domain + package + ".")) + flag;
+
7839 }
+
7840 result += (first ? "" : ", ") + flag + ".getEnum()";
+
7841 first = false;
+
7842 }
+
7843 result = (package.empty() ? "" : (domain + package + ".")) + type + ".fromSet(java.util.EnumSet.of(" + result + "))";
+
7844 }
+
7845 else
+
7846 {
+
7847 size_t pos = result.find_last_of('.');
+
7848 if (pos != std::string::npos)
+
7849 {
+
7850 if (CppCommon::StringUtils::CountAll(result, ".") > 1)
+
7851 result = domain + result;
+
7852 else
+
7853 result = (package.empty() ? "" : (domain + package + ".")) + result;
+
7854 }
+
7855 }
+
7856 }
+
7857
+
7858 return ConvertConstantPrefix(type) + result + ConvertConstantSuffix(type);
+
7859}
+
7860
+
7861std::string GeneratorJava::ConvertConstantPrefix(const std::string& type)
+
7862{
+
7863 if (type == "boolean")
+
7864 return "(boolean)";
+
7865 else if (type == "byte")
+
7866 return "(byte)";
+
7867 else if (type == "char")
+
7868 return "(char)";
+
7869 else if (type == "wchar")
+
7870 return "(char)";
+
7871 else if (type == "int8")
+
7872 return "(byte)";
+
7873 else if (type == "uint8")
+
7874 return "(byte)";
+
7875 else if (type == "int16")
+
7876 return "(short)";
+
7877 else if (type == "uint16")
+
7878 return "(short)";
+
7879 else if (type == "int32")
+
7880 return "(int)";
+
7881 else if (type == "uint32")
+
7882 return "(int)";
+
7883 else if (type == "int64")
+
7884 return "(long)";
+
7885 else if (type == "uint64")
+
7886 return "(long)";
+
7887 else if (type == "float")
+
7888 return "(float)";
+
7889 else if (type == "double")
+
7890 return "(double)";
+
7891 else if (type == "decimal")
+
7892 return "java.math.BigDecimal.valueOf(";
+
7893 else if (type == "uuid")
+
7894 return "java.util.UUID.fromString(";
+
7895
+
7896 return "";
+
7897}
+
7898
+
7899std::string GeneratorJava::ConvertConstantSuffix(const std::string& type)
+
7900{
+
7901 if ((type == "int64") || (type == "uint64"))
+
7902 return "L";
+
7903 else if (type == "float")
+
7904 return "f";
+
7905 else if (type == "double")
+
7906 return "d";
+
7907 else if (type == "decimal")
+
7908 return "d)";
+
7909 else if (type == "uuid")
+
7910 return ")";
+
7911
+
7912 return "";
+
7913}
+
7914
+
7915std::string GeneratorJava::ConvertDefault(const std::string& domain, const std::string& package, const std::string& type)
+
7916{
+
7917 if (type == "bool")
+
7918 return "false";
+
7919 else if (type == "byte")
+
7920 return "(byte)0";
+
7921 else if (type == "bytes")
+
7922 return "java.nio.ByteBuffer.allocate(0)";
+
7923 else if ((type == "char") || (type == "wchar"))
+
7924 return "'\\0'";
+
7925 else if ((type == "int8") || (type == "uint8"))
+
7926 return "(byte)0";
+
7927 else if ((type == "int16") || (type == "uint16"))
+
7928 return "(short)0";
+
7929 else if ((type == "int32") || (type == "uint32"))
+
7930 return "0";
+
7931 else if ((type == "int64") || (type == "uint64"))
+
7932 return "0L";
+
7933 else if (type == "float")
+
7934 return "0.0f";
+
7935 else if (type == "double")
+
7936 return "0.0d";
+
7937 else if (type == "decimal")
+
7938 return "java.math.BigDecimal.valueOf(0L)";
+
7939 else if (type == "string")
+
7940 return "\"\"";
+
7941 else if (type == "timestamp")
+
7942 return ((Version() < 8) ? "new java.util.Date(0)" : "java.time.Instant.EPOCH");
+
7943 else if (type == "uuid")
+
7944 return domain + "fbe.UUIDGenerator.nil()";
+
7945
+
7946 std::string ns = "";
+
7947 std::string t = type;
+
7948
+
7949 size_t pos = type.find_last_of('.');
+
7950 if (pos != std::string::npos)
+
7951 {
+
7952 ns.assign(type, 0, pos + 1);
+
7953 ns = domain + ns;
+
7954 t.assign(type, pos + 1, type.size() - pos);
+
7955 }
+
7956 else if (!package.empty())
+
7957 ns = domain + package + ".";
+
7958
+
7959 return "new " + ns + t + "()";
+
7960}
+
7961
+
7962std::string GeneratorJava::ConvertDefault(const std::string& domain, const std::string& package, const StructField& field)
+
7963{
+
7964 if (field.value)
+
7965 return ConvertConstant(domain, package, *field.type, *field.value, field.optional);
+
7966
+
7967 if (field.array)
+
7968 return "new " + ConvertTypeName(domain, package, *field.type, field.optional) + "[" + std::to_string(field.N) + "]";
+
7969 else if (field.vector || field.list || field.set || field.map || field.hash)
+
7970 return "new " + ConvertTypeName(domain, package, field) + "()";
+
7971 else if (field.optional)
+
7972 return "null";
+
7973 else if (!IsPackageType(*field.type))
+
7974 return "new " + ConvertTypeName(domain, package, field) + "()";
+
7975
+
7976 return ConvertDefault(domain, package, *field.type);
+
7977}
+
7978
+
7979std::string GeneratorJava::ConvertOutputStreamType(const std::string& type, const std::string& name, bool optional)
+
7980{
+
7981 if (type == "bool")
+
7982 return ".append(" + name + " ? \"true\" : \"false\")";
+
7983 else if (type == "bytes")
+
7984 return ".append(\"bytes[\").append(" + name + ".array().length).append(\"]\")";
+
7985 else if ((type == "char") || (type == "wchar"))
+
7986 return ".append(\"'\").append(" + name + ").append(\"'\")";
+
7987 else if ((type == "string") || (type == "uuid"))
+
7988 return ".append(\"\\\"\").append(" + name + ").append(\"\\\"\")";
+
7989 else if (type == "timestamp")
+
7990 return ((Version() < 8) ? ".append(" + name + ".getTime() * 1000)" : ".append(" + name + ".getEpochSecond() * 1000000000 + " + name + ".getNano())");
+
7991 else
+
7992 return ".append(" + name + ")";
+
7993}
+
7994
+
7995std::string GeneratorJava::ConvertOutputStreamValue(const std::string& type, const std::string& name, bool optional, bool separate)
+
7996{
+
7997 std::string comma = separate ? ".append(first ? \"\" : \",\")" : "";
+
7998
+
7999 if (optional || (type == "bytes") || (type == "decimal") || (type == "string") || (type == "timestamp") || (type == "uuid"))
+
8000 return "if (" + name + " != null) sb" + comma + ConvertOutputStreamType(type, name, true) + "; else sb" + comma + ".append(\"null\");";
+
8001 else
+
8002 return "sb" + comma + ConvertOutputStreamType(type, name, false) + ";";
+
8003}
+
8004
+
8005} // namespace FBE
+
void WriteBegin()
Definition generator.inl:24
+
void Store(const CppCommon::Path &filename)
Definition generator.cpp:17
+
static std::string EndLine()
Definition generator.inl:68
+
std::string _input
Definition generator.h:25
+ +
std::string _output
Definition generator.h:26
+
void WriteLineIndent(const std::string &str)
Definition generator.inl:58
+
void Write(const std::string &str)
Definition generator.inl:29
+ +
bool Final() const noexcept
+
bool JSON() const noexcept
+
bool Proto() const noexcept
+
void Generate(const std::shared_ptr< Package > &package) override
+
int yyerror(const char *msg)
Definition fbe.l:163
+
Fast binary encoding Java generator definition.
+
Definition fbe.h:33
+
const char version[]
Definition version.h:15
+
+ + +
+ + diff --git a/documents/html/generator__java_8h.html b/documents/html/generator__java_8h.html new file mode 100644 index 000000000..c91482429 --- /dev/null +++ b/documents/html/generator__java_8h.html @@ -0,0 +1,114 @@ + + + + + + + +FastBinaryEncoding: include/generator_java.h File Reference + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+ +
generator_java.h File Reference
+
+
+ +

Fast binary encoding Java generator definition. +More...

+
#include "generator.h"
+
+

Go to the source code of this file.

+ + + +

+Classes

class  FBE::GeneratorJava
+ + +

+Namespaces

namespace  FBE
+

Detailed Description

+

Fast binary encoding Java generator definition.

+
Author
Ivan Shynkarenka
+
Date
20.04.2018
+ + +

Definition in file generator_java.h.

+
+ + +
+ + diff --git a/documents/html/generator__java_8h_source.html b/documents/html/generator__java_8h_source.html new file mode 100644 index 000000000..ad89b7cc6 --- /dev/null +++ b/documents/html/generator__java_8h_source.html @@ -0,0 +1,238 @@ + + + + + + + +FastBinaryEncoding: include/generator_java.h Source File + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+
generator_java.h
+
+
+Go to the documentation of this file.
1
+
8
+
9#ifndef GENERATOR_JAVA_H
+
10#define GENERATOR_JAVA_H
+
11
+
12#include "generator.h"
+
13
+
14namespace FBE {
+
15
+
+ +
17{
+
18public:
+ +
20
+
21 // Final protocol code generation
+
22 bool Final() const noexcept { return _final; }
+
23 GeneratorJava& Final(bool final) noexcept { _final = final; return *this; }
+
24
+
25 // JSON protocol code generation
+
26 bool JSON() const noexcept { return _json; }
+
27 GeneratorJava& JSON(bool json) noexcept { _json = json; return *this; }
+
28
+
29 // Sender/Receiver protocol code generation
+
30 bool Proto() const noexcept { return _proto; }
+
31 GeneratorJava& Proto(bool proto) noexcept { _proto = proto; return *this; }
+
32
+
33 // Java version
+
34 int Version() const noexcept { return _version; }
+
35 GeneratorJava& Version(int v) noexcept { _version = v; return *this; }
+
36
+
37 void Generate(const std::shared_ptr<Package>& package) override;
+
38
+
39private:
+
40 bool _final{false};
+
41 bool _json{false};
+
42 bool _proto{false};
+
43 int _version{8};
+
44
+
45 void GenerateHeader(const std::string& source);
+
46 void GenerateFooter();
+
47 void GenerateImports(const std::string& domain, const std::string& package);
+
48 void GenerateImports(const std::shared_ptr<Package>& p);
+
49
+
50 void GenerateFBEPackage(const std::string& domain, const std::string& package);
+
51 void GenerateFBEUUIDGenerator(const std::string& domain, const std::string& package);
+
52 void GenerateFBEBuffer(const std::string& domain, const std::string& package);
+
53 void GenerateFBEModel(const std::string& domain, const std::string& package);
+
54 void GenerateFBEPair(const std::string& domain, const std::string& package);
+
55 void GenerateFBESize(const std::string& domain, const std::string& package);
+
56 void GenerateFBEFieldModel(const std::string& domain, const std::string& package);
+
57 void GenerateFBEFieldModel(const std::string& domain, const std::string& package, const std::string& name, const std::string& type, const std::string& base, const std::string& size, const std::string& defaults);
+
58 void GenerateFBEFieldModelDecimal(const std::string& domain, const std::string& package);
+
59 void GenerateFBEFieldModelDate(const std::string& domain, const std::string& package);
+
60 void GenerateFBEFieldModelTimestamp(const std::string& domain, const std::string& package);
+
61 void GenerateFBEFieldModelBytes(const std::string& domain, const std::string& package);
+
62 void GenerateFBEFieldModelString(const std::string& domain, const std::string& package);
+
63 void GenerateFBEFieldModelOptional(const std::string& domain, const std::string& package, const std::string& name, const std::string& type, const std::string& model);
+
64 void GenerateFBEFieldModelArray(const std::string& domain, const std::string& package, const std::string& name, const std::string& type, const std::string& model, bool bytes);
+
65 void GenerateFBEFieldModelVector(const std::string& domain, const std::string& package, const std::string& name, const std::string& type, const std::string& model);
+
66 void GenerateFBEFieldModelMap(const std::string& domain, const std::string& package, const std::string& key_name, const std::string& key_type, const std::string& key_model, const std::string& value_name, const std::string& value_type, const std::string& value_model);
+
67 void GenerateFBEFieldModelEnumFlags(const std::string& domain, const std::string& package, const std::string& name, const std::string& type);
+
68 void GenerateFBEFinalModel(const std::string& domain, const std::string& package);
+
69 void GenerateFBEFinalModel(const std::string& domain, const std::string& package, const std::string& name, const std::string& type, const std::string& base, const std::string& size, const std::string& defaults);
+
70 void GenerateFBEFinalModelDecimal(const std::string& domain, const std::string& package);
+
71 void GenerateFBEFinalModelDate(const std::string& domain, const std::string& package);
+
72 void GenerateFBEFinalModelTimestamp(const std::string& domain, const std::string& package);
+
73 void GenerateFBEFinalModelBytes(const std::string& domain, const std::string& package);
+
74 void GenerateFBEFinalModelString(const std::string& domain, const std::string& package);
+
75 void GenerateFBEFinalModelOptional(const std::string& domain, const std::string& package, const std::string& name, const std::string& type, const std::string& model);
+
76 void GenerateFBEFinalModelArray(const std::string& domain, const std::string& package, const std::string& name, const std::string& type, const std::string& model, bool bytes);
+
77 void GenerateFBEFinalModelVector(const std::string& domain, const std::string& package, const std::string& name, const std::string& type, const std::string& model);
+
78 void GenerateFBEFinalModelMap(const std::string& domain, const std::string& package, const std::string& key_name, const std::string& key_type, const std::string& key_model, const std::string& value_name, const std::string& value_type, const std::string& value_model);
+
79 void GenerateFBEFinalModelEnumFlags(const std::string& domain, const std::string& package, const std::string& name, const std::string& type);
+
80 void GenerateFBESender(const std::string& domain, const std::string& package);
+
81 void GenerateFBEReceiver(const std::string& domain, const std::string& package);
+
82 void GenerateFBEJson(const std::string& domain, const std::string& package);
+
83
+
84 void GenerateContainers(const std::shared_ptr<Package>& p, bool final);
+
85 void GeneratePackage(const std::shared_ptr<Package>& p);
+
86 void GenerateEnum(const std::shared_ptr<Package>& p, const std::shared_ptr<EnumType>& e, const CppCommon::Path& path);
+
87 void GenerateEnumClass(const std::shared_ptr<Package>& p, const std::shared_ptr<EnumType>& e, const CppCommon::Path& path);
+
88 void GenerateEnumJson(const std::shared_ptr<Package>& p, const std::shared_ptr<EnumType>& e);
+
89 void GenerateFlags(const std::shared_ptr<Package>& p, const std::shared_ptr<FlagsType>& e, const CppCommon::Path& path);
+
90 void GenerateFlagsClass(const std::shared_ptr<Package>& p, const std::shared_ptr<FlagsType>& e, const CppCommon::Path& path);
+
91 void GenerateFlagsJson(const std::shared_ptr<Package>& p, const std::shared_ptr<FlagsType>& e);
+
92 void GenerateStruct(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s, const CppCommon::Path& path);
+
93 void GenerateStructFieldModel(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s);
+
94 void GenerateStructModel(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s);
+
95 void GenerateStructFinalModel(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s);
+
96 void GenerateStructModelFinal(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s);
+
97 void GenerateProtocolVersion(const std::shared_ptr<Package>& p);
+
98 void GenerateSender(const std::shared_ptr<Package>& p, bool final);
+
99 void GenerateReceiver(const std::shared_ptr<Package>& p, bool final);
+
100 void GenerateProxy(const std::shared_ptr<Package>& p, bool final);
+
101 void GenerateJson(const std::shared_ptr<Package>& p);
+
102
+
103 bool IsKnownType(const std::string& type);
+
104 bool IsImportedType(const std::string& type);
+
105 bool IsPackageType(const std::string& type);
+
106 bool IsPrimitiveType(const std::string& type, bool optional);
+
107
+
108 std::string CreatePackagePath(const std::string& domain, const std::string& package);
+
109
+
110 std::string ConvertEnumBase(const std::string& type);
+
111 std::string ConvertEnumType(const std::string& type);
+
112 std::string ConvertEnumSize(const std::string& type);
+
113 std::string ConvertEnumGet(const std::string& type);
+
114 std::string ConvertEnumRead(const std::string& type);
+
115 std::string ConvertEnumConstant(const std::string& type, const std::string& value);
+
116 std::string ConvertEnumConstantPrefix(const std::string& type);
+
117 std::string ConvertEnumConstantSuffix(const std::string& type);
+
118 std::string ConvertPrimitiveTypeName(const std::string& type);
+
119 std::string ConvertTypeName(const std::string& domain, const std::string& package, const std::string& type, bool optional);
+
120 std::string ConvertTypeName(const std::string& domain, const std::string& package, const StructField& field);
+
121 std::string ConvertBaseFieldName(const std::string& domain, const std::string& type, bool final);
+
122 std::string ConvertTypeFieldName(const std::string& type);
+
123 std::string ConvertTypeFieldType(const std::string& domain, const std::string& type, bool optional);
+
124 std::string ConvertTypeFieldDeclaration(const std::string& domain, const std::string& type, bool optional, bool final);
+
125 std::string ConvertTypeFieldDeclaration(const std::string& domain, const StructField& field, bool final);
+
126 std::string ConvertTypeFieldInitialization(const std::string& domain, const StructField& field, const std::string& offset, bool final);
+
127 std::string ConvertConstant(const std::string& domain, const std::string& package, const std::string& type, const std::string& value, bool optional);
+
128 std::string ConvertConstantPrefix(const std::string& type);
+
129 std::string ConvertConstantSuffix(const std::string& type);
+
130 std::string ConvertDefault(const std::string& domain, const std::string& package, const std::string& type);
+
131 std::string ConvertDefault(const std::string& domain, const std::string& package, const StructField& field);
+
132
+
133 std::string ConvertOutputStreamType(const std::string& type, const std::string& name, bool optional);
+
134 std::string ConvertOutputStreamValue(const std::string& type, const std::string& name, bool optional, bool separate);
+
135};
+
+
136
+
137} // namespace FBE
+
138
+
139#endif // GENERATOR_JAVA_H
+
Generator(const std::string &input, const std::string &output, int indent, char space)
Definition generator.inl:11
+ +
GeneratorJava & Proto(bool proto) noexcept
+
bool Final() const noexcept
+
GeneratorJava & JSON(bool json) noexcept
+
int Version() const noexcept
+
bool JSON() const noexcept
+
bool Proto() const noexcept
+
GeneratorJava & Final(bool final) noexcept
+
GeneratorJava & Version(int v) noexcept
+
Generator(const std::string &input, const std::string &output, int indent, char space)
Definition generator.inl:11
+
void Generate(const std::shared_ptr< Package > &package) override
+
Fast binary encoding generator definition.
+
Definition fbe.h:33
+
+ + +
+ + diff --git a/documents/html/generator__javascript_8cpp.html b/documents/html/generator__javascript_8cpp.html new file mode 100644 index 000000000..c18be4b3e --- /dev/null +++ b/documents/html/generator__javascript_8cpp.html @@ -0,0 +1,109 @@ + + + + + + + +FastBinaryEncoding: source/generator_javascript.cpp File Reference + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+ +
generator_javascript.cpp File Reference
+
+
+ +

Fast binary encoding JavaScript generator implementation. +More...

+ +

Go to the source code of this file.

+ + + +

+Namespaces

namespace  FBE
+

Detailed Description

+

Fast binary encoding JavaScript generator implementation.

+
Author
Ivan Shynkarenka
+
Date
28.06.2018
+ + +

Definition in file generator_javascript.cpp.

+
+ + +
+ + diff --git a/documents/html/generator__javascript_8cpp_source.html b/documents/html/generator__javascript_8cpp_source.html new file mode 100644 index 000000000..d564ed0a4 --- /dev/null +++ b/documents/html/generator__javascript_8cpp_source.html @@ -0,0 +1,10626 @@ + + + + + + + +FastBinaryEncoding: source/generator_javascript.cpp Source File + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+
generator_javascript.cpp
+
+
+Go to the documentation of this file.
1
+
8
+ +
10
+
11namespace FBE {
+
12
+
+
13void GeneratorJavaScript::Generate(const std::shared_ptr<Package>& package)
+
14{
+
15 GeneratePackage(package);
+
16}
+
+
17
+
18void GeneratorJavaScript::GenerateHeader(const std::string& source)
+
19{
+
20 std::string code = R"CODE(//------------------------------------------------------------------------------
+
21// Automatically generated by the Fast Binary Encoding compiler, do not modify!
+
22// https://github.com/chronoxor/FastBinaryEncoding
+
23// Source: _INPUT_
+
24// FBE version: _VERSION_
+
25//------------------------------------------------------------------------------
+
26)CODE";
+
27
+
28 // Prepare code template
+
29 code = std::regex_replace(code, std::regex("_INPUT_"), source);
+
30 code = std::regex_replace(code, std::regex("_VERSION_"), version);
+
31 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
32
+
33 Write(code);
+
34}
+
35
+
36void GeneratorJavaScript::GenerateFooter()
+
37{
+
38
+
39}
+
40
+
41void GeneratorJavaScript::GenerateBig(const CppCommon::Path& path)
+
42{
+
43 // Generate the common file
+
44 CppCommon::Path common = path / "big.js";
+
45 WriteBegin();
+
46
+
47 // Generate common header
+
48 GenerateHeader("FBE");
+
49
+
50 std::string code = R"CODE(
+
51/* eslint-disable */
+
52
+
53/*
+
54 * big.js v5.1.2
+
55 * A small, fast, easy-to-use library for arbitrary-precision decimal arithmetic.
+
56 * Copyright (c) 2017 Michael Mclaughlin <M8ch88l@gmail.com>
+
57 * https://github.com/MikeMcl/big.js/LICENCE
+
58 */
+
59;(function (GLOBAL) {
+
60 'use strict';
+
61 var Big,
+
62
+
63
+
64/************************************** EDITABLE DEFAULTS *****************************************/
+
65
+
66
+
67 // The default values below must be integers within the stated ranges.
+
68
+
69 /*
+
70 * The maximum number of decimal places (DP) of the results of operations involving division:
+
71 * div and sqrt, and pow with negative exponents.
+
72 */
+
73 DP = 20, // 0 to MAX_DP
+
74
+
75 /*
+
76 * The rounding mode (RM) used when rounding to the above decimal places.
+
77 *
+
78 * 0 Towards zero (i.e. truncate, no rounding). (ROUND_DOWN)
+
79 * 1 To nearest neighbour. If equidistant, round up. (ROUND_HALF_UP)
+
80 * 2 To nearest neighbour. If equidistant, to even. (ROUND_HALF_EVEN)
+
81 * 3 Away from zero. (ROUND_UP)
+
82 */
+
83 RM = 1, // 0, 1, 2 or 3
+
84
+
85 // The maximum value of DP and Big.DP.
+
86 MAX_DP = 1E6, // 0 to 1000000
+
87
+
88 // The maximum magnitude of the exponent argument to the pow method.
+
89 MAX_POWER = 1E6, // 1 to 1000000
+
90
+
91 /*
+
92 * The negative exponent (NE) at and beneath which toString returns exponential notation.
+
93 * (JavaScript numbers: -7)
+
94 * -1000000 is the minimum recommended exponent value of a Big.
+
95 */
+
96 NE = -7, // 0 to -1000000
+
97
+
98 /*
+
99 * The positive exponent (PE) at and above which toString returns exponential notation.
+
100 * (JavaScript numbers: 21)
+
101 * 1000000 is the maximum recommended exponent value of a Big.
+
102 * (This limit is not enforced or checked.)
+
103 */
+
104 PE = 21, // 0 to 1000000
+
105
+
106
+
107/**************************************************************************************************/
+
108)CODE";
+
109
+
110 // Prepare code template
+
111 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
112
+
113 Write(code);
+
114
+
115 code = R"CODE(
+
116
+
117 // Error messages.
+
118 NAME = '[big.js] ',
+
119 INVALID = NAME + 'Invalid ',
+
120 INVALID_DP = INVALID + 'decimal places',
+
121 INVALID_RM = INVALID + 'rounding mode',
+
122 DIV_BY_ZERO = NAME + 'Division by zero',
+
123
+
124 // The shared prototype object.
+
125 P = {},
+
126 UNDEFINED = void 0,
+
127 NUMERIC = /^-?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?$/i;
+
128
+
129
+
130 /*
+
131 * Create and return a Big constructor.
+
132 *
+
133 */
+
134 function _Big_() {
+
135
+
136 /*
+
137 * The Big constructor and exported function.
+
138 * Create and return a new instance of a Big number object.
+
139 *
+
140 * n {number|string|Big} A numeric value.
+
141 */
+
142 function Big(n) {
+
143 var x = this;
+
144
+
145 // Enable constructor usage without new.
+
146 if (!(x instanceof Big)) return n === UNDEFINED ? _Big_() : new Big(n);
+
147
+
148 // Duplicate.
+
149 if (n instanceof Big) {
+
150 x.s = n.s;
+
151 x.e = n.e;
+
152 x.c = n.c.slice();
+
153 } else {
+
154 parse(x, n);
+
155 }
+
156
+
157 /*
+
158 * Retain a reference to this Big constructor, and shadow Big.prototype.constructor which
+
159 * points to Object.
+
160 */
+
161 x.constructor = Big;
+
162 }
+
163
+
164 Big.prototype = P;
+
165 Big.DP = DP;
+
166 Big.RM = RM;
+
167 Big.NE = NE;
+
168 Big.PE = PE;
+
169 Big.version = '5.0.2';
+
170
+
171 return Big;
+
172 }
+
173
+
174
+
175 /*
+
176 * Parse the number or string value passed to a Big constructor.
+
177 *
+
178 * x {Big} A Big number instance.
+
179 * n {number|string} A numeric value.
+
180 */
+
181 function parse(x, n) {
+
182 var e, i, nl;
+
183
+
184 // Minus zero?
+
185 if (n === 0 && 1 / n < 0) n = '-0';
+
186 else if (!NUMERIC.test(n += '')) throw Error(INVALID + 'number');
+
187
+
188 // Determine sign.
+
189 x.s = n.charAt(0) == '-' ? (n = n.slice(1), -1) : 1;
+
190
+
191 // Decimal point?
+
192 if ((e = n.indexOf('.')) > -1) n = n.replace('.', '');
+
193
+
194 // Exponential form?
+
195 if ((i = n.search(/e/i)) > 0) {
+
196
+
197 // Determine exponent.
+
198 if (e < 0) e = i;
+
199 e += +n.slice(i + 1);
+
200 n = n.substring(0, i);
+
201 } else if (e < 0) {
+
202
+
203 // Integer.
+
204 e = n.length;
+
205 }
+
206
+
207 nl = n.length;
+
208
+
209 // Determine leading zeros.
+
210 for (i = 0; i < nl && n.charAt(i) == '0';) ++i;
+
211
+
212 if (i == nl) {
+
213
+
214 // Zero.
+
215 x.c = [x.e = 0];
+
216 } else {
+
217
+
218 // Determine trailing zeros.
+
219 for (; nl > 0 && n.charAt(--nl) == '0';);
+
220 x.e = e - i - 1;
+
221 x.c = [];
+
222
+
223 // Convert string to array of digits without leading/trailing zeros.
+
224 for (e = 0; i <= nl;) x.c[e++] = +n.charAt(i++);
+
225 }
+
226
+
227 return x;
+
228 }
+
229
+
230
+
231 /*
+
232 * Round Big x to a maximum of dp decimal places using rounding mode rm.
+
233 * Called by stringify, P.div, P.round and P.sqrt.
+
234 *
+
235 * x {Big} The Big to round.
+
236 * dp {number} Integer, 0 to MAX_DP inclusive.
+
237 * rm {number} 0, 1, 2 or 3 (DOWN, HALF_UP, HALF_EVEN, UP)
+
238 * [more] {boolean} Whether the result of division was truncated.
+
239 */
+
240 function round(x, dp, rm, more) {
+
241 var xc = x.c,
+
242 i = x.e + dp + 1;
+
243
+
244 if (i < xc.length) {
+
245 if (rm === 1) {
+
246
+
247 // xc[i] is the digit after the digit that may be rounded up.
+
248 more = xc[i] >= 5;
+
249 } else if (rm === 2) {
+
250 more = xc[i] > 5 || xc[i] == 5 &&
+
251 (more || i < 0 || xc[i + 1] !== UNDEFINED || xc[i - 1] & 1);
+
252 } else if (rm === 3) {
+
253 more = more || xc[i] !== UNDEFINED || i < 0;
+
254 } else {
+
255 more = false;
+
256 if (rm !== 0) throw Error(INVALID_RM);
+
257 }
+
258
+
259 if (i < 1) {
+
260 xc.length = 1;
+
261
+
262 if (more) {
+
263
+
264 // 1, 0.1, 0.01, 0.001, 0.0001 etc.
+
265 x.e = -dp;
+
266 xc[0] = 1;
+
267 } else {
+
268
+
269 // Zero.
+
270 xc[0] = x.e = 0;
+
271 }
+
272 } else {
+
273
+
274 // Remove any digits after the required decimal places.
+
275 xc.length = i--;
+
276
+
277 // Round up?
+
278 if (more) {
+
279
+
280 // Rounding up may mean the previous digit has to be rounded up.
+
281 for (; ++xc[i] > 9;) {
+
282 xc[i] = 0;
+
283 if (!i--) {
+
284 ++x.e;
+
285 xc.unshift(1);
+
286 }
+
287 }
+
288 }
+
289
+
290 // Remove trailing zeros.
+
291 for (i = xc.length; !xc[--i];) xc.pop();
+
292 }
+
293 } else if (rm < 0 || rm > 3 || rm !== ~~rm) {
+
294 throw Error(INVALID_RM);
+
295 }
+
296
+
297 return x;
+
298 }
+
299
+
300
+
301 /*
+
302 * Return a string representing the value of Big x in normal or exponential notation.
+
303 * Handles P.toExponential, P.toFixed, P.toJSON, P.toPrecision, P.toString and P.valueOf.
+
304 *
+
305 * x {Big}
+
306 * id? {number} Caller id.
+
307 * 1 toExponential
+
308 * 2 toFixed
+
309 * 3 toPrecision
+
310 * 4 valueOf
+
311 * n? {number|undefined} Caller's argument.
+
312 * k? {number|undefined}
+
313 */
+
314 function stringify(x, id, n, k) {
+
315 var e, s,
+
316 Big = x.constructor,
+
317 z = !x.c[0];
+
318
+
319 if (n !== UNDEFINED) {
+
320 if (n !== ~~n || n < (id == 3) || n > MAX_DP) {
+
321 throw Error(id == 3 ? INVALID + 'precision' : INVALID_DP);
+
322 }
+
323
+
324 x = new Big(x);
+
325
+
326 // The index of the digit that may be rounded up.
+
327 n = k - x.e;
+
328
+
329 // Round?
+
330 if (x.c.length > ++k) round(x, n, Big.RM);
+
331
+
332 // toFixed: recalculate k as x.e may have changed if value rounded up.
+
333 if (id == 2) k = x.e + n + 1;
+
334
+
335 // Append zeros?
+
336 for (; x.c.length < k;) x.c.push(0);
+
337 }
+
338
+
339 e = x.e;
+
340 s = x.c.join('');
+
341 n = s.length;
+
342
+
343 // Exponential notation?
+
344 if (id != 2 && (id == 1 || id == 3 && k <= e || e <= Big.NE || e >= Big.PE)) {
+
345 s = s.charAt(0) + (n > 1 ? '.' + s.slice(1) : '') + (e < 0 ? 'e' : 'e+') + e;
+
346
+
347 // Normal notation.
+
348 } else if (e < 0) {
+
349 for (; ++e;) s = '0' + s;
+
350 s = '0.' + s;
+
351 } else if (e > 0) {
+
352 if (++e > n) for (e -= n; e--;) s += '0';
+
353 else if (e < n) s = s.slice(0, e) + '.' + s.slice(e);
+
354 } else if (n > 1) {
+
355 s = s.charAt(0) + '.' + s.slice(1);
+
356 }
+
357
+
358 return x.s < 0 && (!z || id == 4) ? '-' + s : s;
+
359 }
+
360)CODE";
+
361
+
362 // Prepare code template
+
363 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
364
+
365 Write(code);
+
366
+
367 code = R"CODE(
+
368
+
369 // Prototype/instance methods
+
370
+
371
+
372 /*
+
373 * Return a new Big whose value is the absolute value of this Big.
+
374 */
+
375 P.abs = function () {
+
376 var x = new this.constructor(this);
+
377 x.s = 1;
+
378 return x;
+
379 };
+
380
+
381
+
382 /*
+
383 * Return 1 if the value of this Big is greater than the value of Big y,
+
384 * -1 if the value of this Big is less than the value of Big y, or
+
385 * 0 if they have the same value.
+
386 */
+
387 P.cmp = function (y) {
+
388 var isneg,
+
389 x = this,
+
390 xc = x.c,
+
391 yc = (y = new x.constructor(y)).c,
+
392 i = x.s,
+
393 j = y.s,
+
394 k = x.e,
+
395 l = y.e;
+
396
+
397 // Either zero?
+
398 if (!xc[0] || !yc[0]) return !xc[0] ? !yc[0] ? 0 : -j : i;
+
399
+
400 // Signs differ?
+
401 if (i != j) return i;
+
402
+
403 isneg = i < 0;
+
404
+
405 // Compare exponents.
+
406 if (k != l) return k > l ^ isneg ? 1 : -1;
+
407
+
408 j = (k = xc.length) < (l = yc.length) ? k : l;
+
409
+
410 // Compare digit by digit.
+
411 for (i = -1; ++i < j;) {
+
412 if (xc[i] != yc[i]) return xc[i] > yc[i] ^ isneg ? 1 : -1;
+
413 }
+
414
+
415 // Compare lengths.
+
416 return k == l ? 0 : k > l ^ isneg ? 1 : -1;
+
417 };
+
418
+
419
+
420 /*
+
421 * Return a new Big whose value is the value of this Big divided by the value of Big y, rounded,
+
422 * if necessary, to a maximum of Big.DP decimal places using rounding mode Big.RM.
+
423 */
+
424 P.div = function (y) {
+
425 var x = this,
+
426 Big = x.constructor,
+
427 a = x.c, // dividend
+
428 b = (y = new Big(y)).c, // divisor
+
429 k = x.s == y.s ? 1 : -1,
+
430 dp = Big.DP;
+
431
+
432 if (dp !== ~~dp || dp < 0 || dp > MAX_DP) throw Error(INVALID_DP);
+
433
+
434 // Divisor is zero?
+
435 if (!b[0]) throw Error(DIV_BY_ZERO);
+
436
+
437 // Dividend is 0? Return +-0.
+
438 if (!a[0]) return new Big(k * 0);
+
439
+
440 var bl, bt, n, cmp, ri,
+
441 bz = b.slice(),
+
442 ai = bl = b.length,
+
443 al = a.length,
+
444 r = a.slice(0, bl), // remainder
+
445 rl = r.length,
+
446 q = y, // quotient
+
447 qc = q.c = [],
+
448 qi = 0,
+
449 d = dp + (q.e = x.e - y.e) + 1; // number of digits of the result
+
450
+
451 q.s = k;
+
452 k = d < 0 ? 0 : d;
+
453
+
454 // Create version of divisor with leading zero.
+
455 bz.unshift(0);
+
456
+
457 // Add zeros to make remainder as long as divisor.
+
458 for (; rl++ < bl;) r.push(0);
+
459
+
460 do {
+
461
+
462 // n is how many times the divisor goes into current remainder.
+
463 for (n = 0; n < 10; n++) {
+
464
+
465 // Compare divisor and remainder.
+
466 if (bl != (rl = r.length)) {
+
467 cmp = bl > rl ? 1 : -1;
+
468 } else {
+
469 for (ri = -1, cmp = 0; ++ri < bl;) {
+
470 if (b[ri] != r[ri]) {
+
471 cmp = b[ri] > r[ri] ? 1 : -1;
+
472 break;
+
473 }
+
474 }
+
475 }
+
476
+
477 // If divisor < remainder, subtract divisor from remainder.
+
478 if (cmp < 0) {
+
479
+
480 // Remainder can't be more than 1 digit longer than divisor.
+
481 // Equalise lengths using divisor with extra leading zero?
+
482 for (bt = rl == bl ? b : bz; rl;) {
+
483 if (r[--rl] < bt[rl]) {
+
484 ri = rl;
+
485 for (; ri && !r[--ri];) r[ri] = 9;
+
486 --r[ri];
+
487 r[rl] += 10;
+
488 }
+
489 r[rl] -= bt[rl];
+
490 }
+
491
+
492 for (; !r[0];) r.shift();
+
493 } else {
+
494 break;
+
495 }
+
496 }
+
497
+
498 // Add the digit n to the result array.
+
499 qc[qi++] = cmp ? n : ++n;
+
500
+
501 // Update the remainder.
+
502 if (r[0] && cmp) r[rl] = a[ai] || 0;
+
503 else r = [a[ai]];
+
504
+
505 } while ((ai++ < al || r[0] !== UNDEFINED) && k--);
+
506
+
507 // Leading zero? Do not remove if result is simply zero (qi == 1).
+
508 if (!qc[0] && qi != 1) {
+
509
+
510 // There can't be more than one zero.
+
511 qc.shift();
+
512 q.e--;
+
513 }
+
514
+
515 // Round?
+
516 if (qi > d) round(q, dp, Big.RM, r[0] !== UNDEFINED);
+
517
+
518 return q;
+
519 };
+
520
+
521
+
522 /*
+
523 * Return true if the value of this Big is equal to the value of Big y, otherwise return false.
+
524 */
+
525 P.eq = function (y) {
+
526 return !this.cmp(y);
+
527 };
+
528
+
529
+
530 /*
+
531 * Return true if the value of this Big is greater than the value of Big y, otherwise return
+
532 * false.
+
533 */
+
534 P.gt = function (y) {
+
535 return this.cmp(y) > 0;
+
536 };
+
537
+
538
+
539 /*
+
540 * Return true if the value of this Big is greater than or equal to the value of Big y, otherwise
+
541 * return false.
+
542 */
+
543 P.gte = function (y) {
+
544 return this.cmp(y) > -1;
+
545 };
+
546
+
547
+
548 /*
+
549 * Return true if the value of this Big is less than the value of Big y, otherwise return false.
+
550 */
+
551 P.lt = function (y) {
+
552 return this.cmp(y) < 0;
+
553 };
+
554
+
555
+
556 /*
+
557 * Return true if the value of this Big is less than or equal to the value of Big y, otherwise
+
558 * return false.
+
559 */
+
560 P.lte = function (y) {
+
561 return this.cmp(y) < 1;
+
562 };
+
563
+
564
+
565 /*
+
566 * Return a new Big whose value is the value of this Big minus the value of Big y.
+
567 */
+
568 P.minus = P.sub = function (y) {
+
569 var i, j, t, xlty,
+
570 x = this,
+
571 Big = x.constructor,
+
572 a = x.s,
+
573 b = (y = new Big(y)).s;
+
574
+
575 // Signs differ?
+
576 if (a != b) {
+
577 y.s = -b;
+
578 return x.plus(y);
+
579 }
+
580
+
581 var xc = x.c.slice(),
+
582 xe = x.e,
+
583 yc = y.c,
+
584 ye = y.e;
+
585
+
586 // Either zero?
+
587 if (!xc[0] || !yc[0]) {
+
588
+
589 // y is non-zero? x is non-zero? Or both are zero.
+
590 return yc[0] ? (y.s = -b, y) : new Big(xc[0] ? x : 0);
+
591 }
+
592
+
593 // Determine which is the bigger number. Prepend zeros to equalise exponents.
+
594 if (a = xe - ye) {
+
595
+
596 if (xlty = a < 0) {
+
597 a = -a;
+
598 t = xc;
+
599 } else {
+
600 ye = xe;
+
601 t = yc;
+
602 }
+
603
+
604 t.reverse();
+
605 for (b = a; b--;) t.push(0);
+
606 t.reverse();
+
607 } else {
+
608
+
609 // Exponents equal. Check digit by digit.
+
610 j = ((xlty = xc.length < yc.length) ? xc : yc).length;
+
611
+
612 for (a = b = 0; b < j; b++) {
+
613 if (xc[b] != yc[b]) {
+
614 xlty = xc[b] < yc[b];
+
615 break;
+
616 }
+
617 }
+
618 }
+
619
+
620 // x < y? Point xc to the array of the bigger number.
+
621 if (xlty) {
+
622 t = xc;
+
623 xc = yc;
+
624 yc = t;
+
625 y.s = -y.s;
+
626 }
+
627
+
628 /*
+
629 * Append zeros to xc if shorter. No need to add zeros to yc if shorter as subtraction only
+
630 * needs to start at yc.length.
+
631 */
+
632 if ((b = (j = yc.length) - (i = xc.length)) > 0) for (; b--;) xc[i++] = 0;
+
633
+
634 // Subtract yc from xc.
+
635 for (b = i; j > a;) {
+
636 if (xc[--j] < yc[j]) {
+
637 for (i = j; i && !xc[--i];) xc[i] = 9;
+
638 --xc[i];
+
639 xc[j] += 10;
+
640 }
+
641
+
642 xc[j] -= yc[j];
+
643 }
+
644
+
645 // Remove trailing zeros.
+
646 for (; xc[--b] === 0;) xc.pop();
+
647
+
648 // Remove leading zeros and adjust exponent accordingly.
+
649 for (; xc[0] === 0;) {
+
650 xc.shift();
+
651 --ye;
+
652 }
+
653
+
654 if (!xc[0]) {
+
655
+
656 // n - n = +0
+
657 y.s = 1;
+
658
+
659 // Result must be zero.
+
660 xc = [ye = 0];
+
661 }
+
662
+
663 y.c = xc;
+
664 y.e = ye;
+
665
+
666 return y;
+
667 };
+
668
+
669
+
670 /*
+
671 * Return a new Big whose value is the value of this Big modulo the value of Big y.
+
672 */
+
673 P.mod = function (y) {
+
674 var ygtx,
+
675 x = this,
+
676 Big = x.constructor,
+
677 a = x.s,
+
678 b = (y = new Big(y)).s;
+
679
+
680 if (!y.c[0]) throw Error(DIV_BY_ZERO);
+
681
+
682 x.s = y.s = 1;
+
683 ygtx = y.cmp(x) == 1;
+
684 x.s = a;
+
685 y.s = b;
+
686
+
687 if (ygtx) return new Big(x);
+
688
+
689 a = Big.DP;
+
690 b = Big.RM;
+
691 Big.DP = Big.RM = 0;
+
692 x = x.div(y);
+
693 Big.DP = a;
+
694 Big.RM = b;
+
695
+
696 return this.minus(x.times(y));
+
697 };
+
698
+
699
+
700 /*
+
701 * Return a new Big whose value is the value of this Big plus the value of Big y.
+
702 */
+
703 P.plus = P.add = function (y) {
+
704 var t,
+
705 x = this,
+
706 Big = x.constructor,
+
707 a = x.s,
+
708 b = (y = new Big(y)).s;
+
709
+
710 // Signs differ?
+
711 if (a != b) {
+
712 y.s = -b;
+
713 return x.minus(y);
+
714 }
+
715
+
716 var xe = x.e,
+
717 xc = x.c,
+
718 ye = y.e,
+
719 yc = y.c;
+
720
+
721 // Either zero? y is non-zero? x is non-zero? Or both are zero.
+
722 if (!xc[0] || !yc[0]) return yc[0] ? y : new Big(xc[0] ? x : a * 0);
+
723
+
724 xc = xc.slice();
+
725
+
726 // Prepend zeros to equalise exponents.
+
727 // Note: Faster to use reverse than do unshifts.
+
728 if (a = xe - ye) {
+
729 if (a > 0) {
+
730 ye = xe;
+
731 t = yc;
+
732 } else {
+
733 a = -a;
+
734 t = xc;
+
735 }
+
736
+
737 t.reverse();
+
738 for (; a--;) t.push(0);
+
739 t.reverse();
+
740 }
+
741
+
742 // Point xc to the longer array.
+
743 if (xc.length - yc.length < 0) {
+
744 t = yc;
+
745 yc = xc;
+
746 xc = t;
+
747 }
+
748
+
749 a = yc.length;
+
750
+
751 // Only start adding at yc.length - 1 as the further digits of xc can be left as they are.
+
752 for (b = 0; a; xc[a] %= 10) b = (xc[--a] = xc[a] + yc[a] + b) / 10 | 0;
+
753
+
754 // No need to check for zero, as +x + +y != 0 && -x + -y != 0
+
755
+
756 if (b) {
+
757 xc.unshift(b);
+
758 ++ye;
+
759 }
+
760
+
761 // Remove trailing zeros.
+
762 for (a = xc.length; xc[--a] === 0;) xc.pop();
+
763
+
764 y.c = xc;
+
765 y.e = ye;
+
766
+
767 return y;
+
768 };
+
769
+
770
+
771 /*
+
772 * Return a Big whose value is the value of this Big raised to the power n.
+
773 * If n is negative, round to a maximum of Big.DP decimal places using rounding
+
774 * mode Big.RM.
+
775 *
+
776 * n {number} Integer, -MAX_POWER to MAX_POWER inclusive.
+
777 */
+
778 P.pow = function (n) {
+
779 var x = this,
+
780 one = new x.constructor(1),
+
781 y = one,
+
782 isneg = n < 0;
+
783
+
784 if (n !== ~~n || n < -MAX_POWER || n > MAX_POWER) throw Error(INVALID + 'exponent');
+
785 if (isneg) n = -n;
+
786
+
787 for (;;) {
+
788 if (n & 1) y = y.times(x);
+
789 n >>= 1;
+
790 if (!n) break;
+
791 x = x.times(x);
+
792 }
+
793
+
794 return isneg ? one.div(y) : y;
+
795 };
+
796
+
797
+
798 /*
+
799 * Return a new Big whose value is the value of this Big rounded to a maximum of dp decimal
+
800 * places using rounding mode rm.
+
801 * If dp is not specified, round to 0 decimal places.
+
802 * If rm is not specified, use Big.RM.
+
803 *
+
804 * dp? {number} Integer, 0 to MAX_DP inclusive.
+
805 * rm? 0, 1, 2 or 3 (ROUND_DOWN, ROUND_HALF_UP, ROUND_HALF_EVEN, ROUND_UP)
+
806 */
+
807 P.round = function (dp, rm) {
+
808 var Big = this.constructor;
+
809 if (dp === UNDEFINED) dp = 0;
+
810 else if (dp !== ~~dp || dp < 0 || dp > MAX_DP) throw Error(INVALID_DP);
+
811 return round(new Big(this), dp, rm === UNDEFINED ? Big.RM : rm);
+
812 };
+
813
+
814
+
815 /*
+
816 * Return a new Big whose value is the square root of the value of this Big, rounded, if
+
817 * necessary, to a maximum of Big.DP decimal places using rounding mode Big.RM.
+
818 */
+
819 P.sqrt = function () {
+
820 var r, c, t,
+
821 x = this,
+
822 Big = x.constructor,
+
823 s = x.s,
+
824 e = x.e,
+
825 half = new Big(0.5);
+
826
+
827 // Zero?
+
828 if (!x.c[0]) return new Big(x);
+
829
+
830 // Negative?
+
831 if (s < 0) throw Error(NAME + 'No square root');
+
832
+
833 // Estimate.
+
834 s = Math.sqrt(x.toString());
+
835
+
836 // Math.sqrt underflow/overflow?
+
837 // Re-estimate: pass x to Math.sqrt as integer, then adjust the result exponent.
+
838 if (s === 0 || s === 1 / 0) {
+
839 c = x.c.join('');
+
840 if (!(c.length + e & 1)) c += '0';
+
841 r = new Big(Math.sqrt(c).toString());
+
842 r.e = ((e + 1) / 2 | 0) - (e < 0 || e & 1);
+
843 } else {
+
844 r = new Big(s.toString());
+
845 }
+
846
+
847 e = r.e + (Big.DP += 4);
+
848
+
849 // Newton-Raphson iteration.
+
850 do {
+
851 t = r;
+
852 r = half.times(t.plus(x.div(t)));
+
853 } while (t.c.slice(0, e).join('') !== r.c.slice(0, e).join(''));
+
854
+
855 return round(r, Big.DP -= 4, Big.RM);
+
856 };
+
857
+
858
+
859 /*
+
860 * Return a new Big whose value is the value of this Big times the value of Big y.
+
861 */
+
862 P.times = P.mul = function (y) {
+
863 var c,
+
864 x = this,
+
865 Big = x.constructor,
+
866 xc = x.c,
+
867 yc = (y = new Big(y)).c,
+
868 a = xc.length,
+
869 b = yc.length,
+
870 i = x.e,
+
871 j = y.e;
+
872
+
873 // Determine sign of result.
+
874 y.s = x.s == y.s ? 1 : -1;
+
875
+
876 // Return signed 0 if either 0.
+
877 if (!xc[0] || !yc[0]) return new Big(y.s * 0);
+
878
+
879 // Initialise exponent of result as x.e + y.e.
+
880 y.e = i + j;
+
881
+
882 // If array xc has fewer digits than yc, swap xc and yc, and lengths.
+
883 if (a < b) {
+
884 c = xc;
+
885 xc = yc;
+
886 yc = c;
+
887 j = a;
+
888 a = b;
+
889 b = j;
+
890 }
+
891
+
892 // Initialise coefficient array of result with zeros.
+
893 for (c = new Array(j = a + b); j--;) c[j] = 0;
+
894
+
895 // Multiply.
+
896
+
897 // i is initially xc.length.
+
898 for (i = b; i--;) {
+
899 b = 0;
+
900
+
901 // a is yc.length.
+
902 for (j = a + i; j > i;) {
+
903
+
904 // Current sum of products at this digit position, plus carry.
+
905 b = c[j] + yc[i] * xc[j - i - 1] + b;
+
906 c[j--] = b % 10;
+
907
+
908 // carry
+
909 b = b / 10 | 0;
+
910 }
+
911
+
912 c[j] = (c[j] + b) % 10;
+
913 }
+
914
+
915 // Increment result exponent if there is a final carry, otherwise remove leading zero.
+
916 if (b) ++y.e;
+
917 else c.shift();
+
918
+
919 // Remove trailing zeros.
+
920 for (i = c.length; !c[--i];) c.pop();
+
921 y.c = c;
+
922
+
923 return y;
+
924 };
+
925
+
926
+
927 /*
+
928 * Return a string representing the value of this Big in exponential notation to dp fixed decimal
+
929 * places and rounded using Big.RM.
+
930 *
+
931 * dp? {number} Integer, 0 to MAX_DP inclusive.
+
932 */
+
933 P.toExponential = function (dp) {
+
934 return stringify(this, 1, dp, dp);
+
935 };
+
936
+
937
+
938 /*
+
939 * Return a string representing the value of this Big in normal notation to dp fixed decimal
+
940 * places and rounded using Big.RM.
+
941 *
+
942 * dp? {number} Integer, 0 to MAX_DP inclusive.
+
943 *
+
944 * (-0).toFixed(0) is '0', but (-0.1).toFixed(0) is '-0'.
+
945 * (-0).toFixed(1) is '0.0', but (-0.01).toFixed(1) is '-0.0'.
+
946 */
+
947 P.toFixed = function (dp) {
+
948 return stringify(this, 2, dp, this.e + dp);
+
949 };
+
950
+
951
+
952 /*
+
953 * Return a string representing the value of this Big rounded to sd significant digits using
+
954 * Big.RM. Use exponential notation if sd is less than the number of digits necessary to represent
+
955 * the integer part of the value in normal notation.
+
956 *
+
957 * sd {number} Integer, 1 to MAX_DP inclusive.
+
958 */
+
959 P.toPrecision = function (sd) {
+
960 return stringify(this, 3, sd, sd - 1);
+
961 };
+
962
+
963
+
964 /*
+
965 * Return a string representing the value of this Big.
+
966 * Return exponential notation if this Big has a positive exponent equal to or greater than
+
967 * Big.PE, or a negative exponent equal to or less than Big.NE.
+
968 * Omit the sign for negative zero.
+
969 */
+
970 P.toString = function () {
+
971 return stringify(this);
+
972 };
+
973
+
974
+
975 /*
+
976 * Return a string representing the value of this Big.
+
977 * Return exponential notation if this Big has a positive exponent equal to or greater than
+
978 * Big.PE, or a negative exponent equal to or less than Big.NE.
+
979 * Include the sign for negative zero.
+
980 */
+
981 P.valueOf = P.toJSON = function () {
+
982 return stringify(this, 4);
+
983 };
+
984
+
985
+
986 // Export
+
987
+
988
+
989 Big = _Big_();
+
990
+
991 Big['default'] = Big.Big = Big;
+
992
+
993 //AMD.
+
994 if (typeof define === 'function' && define.amd) {
+
995 define(function () { return Big; });
+
996
+
997 // Node and other CommonJS-like environments that support module.exports.
+
998 } else if (typeof module !== 'undefined' && module.exports) {
+
999 module.exports = Big;
+
1000
+
1001 //Browser.
+
1002 } else {
+
1003 GLOBAL.Big = Big;
+
1004 }
+
1005})(this);
+
1006)CODE";
+
1007
+
1008 // Prepare code template
+
1009 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
1010
+
1011 Write(code);
+
1012
+
1013 // Generate common footer
+
1014 GenerateFooter();
+
1015
+
1016 // Close the common file
+
1017 WriteEnd();
+
1018 Store(common);
+
1019}
+
1020
+
1021void GeneratorJavaScript::GenerateInt64(const CppCommon::Path& path)
+
1022{
+
1023 // Generate the common file
+
1024 CppCommon::Path common = path / "int64.js";
+
1025 WriteBegin();
+
1026
+
1027 // Generate common header
+
1028 GenerateHeader("FBE");
+
1029
+
1030 std::string code = R"CODE(
+
1031/* eslint-disable prefer-const,no-loss-of-precision */
+
1032'use strict'
+
1033
+
1037class Int64 {
+
1044 constructor (low, high) {
+
1045 this.low = low | 0
+
1046 this.high = high | 0
+
1047 }
+
1048
+
1053 static get ZERO () { return INT64_ZERO }
+
1054
+
1059 static get MIN () { return INT64_MIN }
+
1060
+
1065 static get MAX () { return INT64_MAX }
+
1066
+
1072 static isInt64 (obj) {
+
1073 return (obj && obj.__isInt64__) === true
+
1074 }
+
1075
+
1082 static fromBits (lowBits, highBits) {
+
1083 return new Int64(lowBits, highBits)
+
1084 }
+
1085
+
1092 static fromBytes (bytes, le = true) {
+
1093 return le ? Int64.fromBytesLE(bytes) : Int64.fromBytesBE(bytes)
+
1094 }
+
1095
+
1101 static fromBytesBE (bytes) {
+
1102 return new Int64(
+
1103 bytes[4] << 24 |
+
1104 bytes[5] << 16 |
+
1105 bytes[6] << 8 |
+
1106 bytes[7] << 0,
+
1107 bytes[0] << 24 |
+
1108 bytes[1] << 16 |
+
1109 bytes[2] << 8 |
+
1110 bytes[3] << 0
+
1111 )
+
1112 }
+
1113
+
1119 static fromBytesLE (bytes) {
+
1120 return new Int64(
+
1121 bytes[0] << 0 |
+
1122 bytes[1] << 8 |
+
1123 bytes[2] << 16 |
+
1124 bytes[3] << 24,
+
1125 bytes[4] << 0 |
+
1126 bytes[5] << 8 |
+
1127 bytes[6] << 16 |
+
1128 bytes[7] << 24
+
1129 )
+
1130 }
+
1131
+
1137 static fromInt32 (value) {
+
1138 value |= 0
+
1139
+
1140 let cache = ((value >= -128) && (value < 128))
+
1141 if (cache) {
+
1142 let cached = Int64Cache[value]
+
1143 if (cached) {
+
1144 return cached
+
1145 }
+
1146 }
+
1147
+
1148 let result = Int64.fromBits(value, (value < 0) ? -1 : 0)
+
1149
+
1150 if (cache) {
+
1151 Int64Cache[value] = result
+
1152 }
+
1153
+
1154 return result
+
1155 }
+
1156
+
1162 static fromNumber (value) {
+
1163 if (isNaN(value)) {
+
1164 return INT64_ZERO
+
1165 }
+
1166 if (value <= -INT64_TWO_PWR_63_DBL) {
+
1167 return INT64_MIN
+
1168 }
+
1169 if (value + 1 >= INT64_TWO_PWR_63_DBL) {
+
1170 return INT64_MAX
+
1171 }
+
1172 if (value < 0) {
+
1173 return Int64.fromNumber(-value).neg()
+
1174 }
+
1175 return Int64.fromBits((value % INT64_TWO_PWR_32_DBL) | 0, (value / INT64_TWO_PWR_32_DBL) | 0)
+
1176 }
+
1177
+
1184 static fromString (str, radix = 10) {
+
1185 if (str.length === 0) {
+
1186 throw new Error('Empty string!')
+
1187 }
+
1188 if ((str === 'NaN') || (str === 'Infinity') || (str === '+Infinity') || (str === '-Infinity')) {
+
1189 return INT64_ZERO
+
1190 }
+
1191 radix = radix || 10
+
1192 if ((radix < 2) || (radix > 36)) {
+
1193 throw new RangeError('radix')
+
1194 }
+
1195
+
1196 let p = str.indexOf('-')
+
1197 if (p > 0) {
+
1198 throw new Error('Interior hyphen!')
+
1199 } else if (p === 0) {
+
1200 return Int64.fromString(str.substring(1), radix).neg()
+
1201 }
+
1202
+
1203 // Do several (8) digits each time through the loop, so as to
+
1204 // minimize the calls to the very expensive emulated div.
+
1205 let radixToPower = Int64.fromNumber(Math.pow(radix, 8))
+
1206
+
1207 let result = INT64_ZERO
+
1208 for (let i = 0; i < str.length; i += 8) {
+
1209 let size = Math.min(8, str.length - i)
+
1210 let value = parseInt(str.substring(i, i + size), radix)
+
1211 if (size < 8) {
+
1212 let power = Int64.fromNumber(Math.pow(radix, size))
+
1213 result = result.mul(power).add(Int64.fromNumber(value))
+
1214 } else {
+
1215 result = result.mul(radixToPower)
+
1216 result = result.add(Int64.fromNumber(value))
+
1217 }
+
1218 }
+
1219 return result
+
1220 }
+
1221
+
1227 static fromValue (value) {
+
1228 if (typeof value === 'number') {
+
1229 return Int64.fromNumber(value)
+
1230 }
+
1231 if (typeof value === 'string') {
+
1232 return Int64.fromString(value, 10)
+
1233 }
+
1234 return Int64.fromBits(value.low, value.high)
+
1235 }
+
1236
+
1243 toBytes (le = true) {
+
1244 return le ? this.toBytesLE() : this.toBytesBE()
+
1245 }
+
1246
+
1252 toBytesBE () {
+
1253 let hi = this.high
+
1254 let lo = this.low
+
1255 return [
+
1256 hi >>> 24 & 0xFF,
+
1257 hi >>> 16 & 0xFF,
+
1258 hi >>> 8 & 0xFF,
+
1259 hi >>> 0 & 0xFF,
+
1260 lo >>> 24 & 0xFF,
+
1261 lo >>> 16 & 0xFF,
+
1262 lo >>> 8 & 0xFF,
+
1263 lo >>> 0 & 0xFF
+
1264 ]
+
1265 }
+
1266
+
1272 toBytesLE () {
+
1273 let hi = this.high
+
1274 let lo = this.low
+
1275 return [
+
1276 lo >>> 0 & 0xFF,
+
1277 lo >>> 8 & 0xFF,
+
1278 lo >>> 16 & 0xFF,
+
1279 lo >>> 24 & 0xFF,
+
1280 hi >>> 0 & 0xFF,
+
1281 hi >>> 8 & 0xFF,
+
1282 hi >>> 16 & 0xFF,
+
1283 hi >>> 24 & 0xFF
+
1284 ]
+
1285 }
+
1286
+
1292 toInt32 () {
+
1293 return this.low
+
1294 }
+
1295
+
1301 toNumber () {
+
1302 return this.high * INT64_TWO_PWR_32_DBL + (this.low >>> 0)
+
1303 }
+
1304
+
1311 toString (radix = 10) {
+
1312 radix = radix || 10
+
1313 if ((radix < 2) || (radix > 36)) {
+
1314 throw new RangeError('Radix must be in range [2, 36]')
+
1315 }
+
1316 if (this.isZero) {
+
1317 return '0'
+
1318 }
+
1319 if (this.isNegative) {
+
1320 if (this.eq(INT64_MIN)) {
+
1321 // We need to change the Long value before it can be negated, so we remove
+
1322 // the bottom-most digit in this base and then recurse to do the rest.
+
1323 let radixLong = Int64.fromNumber(radix)
+
1324 let div = this.div(radixLong)
+
1325 let rem1 = div.mul(radixLong).sub(this)
+
1326 return div.toString(radix) + rem1.toInt32().toString(radix)
+
1327 } else {
+
1328 return '-' + this.neg().toString(radix)
+
1329 }
+
1330 }
+
1331
+
1332 // Do several (6) digits each time through the loop, so as to
+
1333 // minimize the calls to the very expensive emulated div.
+
1334 let radixToPower = Int64.fromNumber(Math.pow(radix, 6))
+
1335 let rem = this
+
1336 let result = ''
+
1337 while (true) {
+
1338 let remDiv = rem.div(radixToPower)
+
1339 let intval = rem.sub(remDiv.mul(radixToPower)).toInt32() >>> 0
+
1340 let digits = intval.toString(radix)
+
1341 rem = remDiv
+
1342 if (rem.isZero) {
+
1343 return digits + result
+
1344 } else {
+
1345 while (digits.length < 6) {
+
1346 digits = '0' + digits
+
1347 }
+
1348 result = '' + digits + result
+
1349 }
+
1350 }
+
1351 }
+
1352
+
1358 toSigned () {
+
1359 return this
+
1360 }
+
1361
+
1367 toUnsigned () {
+
1368 return UInt64.fromBits(this.low, this.high)
+
1369 }
+
1370
+
1376 get HighBits () {
+
1377 return this.high
+
1378 }
+
1379
+
1385 get HighBitsUnsigned () {
+
1386 return this.high >>> 0
+
1387 }
+
1388
+
1394 get LowBits () {
+
1395 return this.low
+
1396 }
+
1397
+
1403 get LowBitsUnsigned () {
+
1404 return this.low >>> 0
+
1405 }
+
1406
+
1412 get NumBits () {
+
1413 if (this.isNegative) {
+
1414 return this.eq(INT64_MIN) ? 64 : this.neg().NumBits
+
1415 }
+
1416
+
1417 let val = (this.high !== 0) ? this.high : this.low
+
1418
+
1419 let bit
+
1420 for (bit = 31; bit > 0; bit--) {
+
1421 if ((val & (1 << bit)) !== 0) {
+
1422 break
+
1423 }
+
1424 }
+
1425
+
1426 return (this.high !== 0) ? (bit + 33) : (bit + 1)
+
1427 }
+
1428
+
1434 get isZero () {
+
1435 return (this.high === 0) && (this.low === 0)
+
1436 }
+
1437
+
1443 get isPositive () {
+
1444 return this.high >= 0
+
1445 }
+
1446
+
1452 get isNegative () {
+
1453 return this.high < 0
+
1454 }
+
1455
+
1461 get isOdd () {
+
1462 return (this.low & 1) === 1
+
1463 }
+
1464
+
1470 get isEven () {
+
1471 return (this.low & 1) === 0
+
1472 }
+
1473
+
1480 eq (other) {
+
1481 if (UInt64.isUInt64(other)) {
+
1482 if (((this.high >>> 31) === 1) && ((other.high >>> 31) === 1)) {
+
1483 return false
+
1484 }
+
1485 } else if (!Int64.isInt64(other)) {
+
1486 other = Int64.fromValue(other)
+
1487 }
+
1488 return (this.high === other.high) && (this.low === other.low)
+
1489 }
+
1490
+
1497 ne (other) {
+
1498 return !this.eq(other)
+
1499 }
+
1500
+
1507 lt (other) {
+
1508 return this.cmp(other) < 0
+
1509 }
+
1510
+
1517 lte (other) {
+
1518 return this.cmp(other) <= 0
+
1519 }
+
1520
+
1527 gt (other) {
+
1528 return this.cmp(other) > 0
+
1529 }
+
1530
+
1537 gte (other) {
+
1538 return this.cmp(other) >= 0
+
1539 }
+
1540
+
1547 cmp (other) {
+
1548 if (!Int64.isInt64(other) && !UInt64.isUInt64(other)) {
+
1549 other = Int64.fromValue(other)
+
1550 }
+
1551 if (this.eq(other)) {
+
1552 return 0
+
1553 }
+
1554 let thisNeg = this.isNegative
+
1555 let otherNeg = other.isNegative
+
1556 if (thisNeg && !otherNeg) {
+
1557 return -1
+
1558 }
+
1559 if (!thisNeg && otherNeg) {
+
1560 return 1
+
1561 }
+
1562 // At this point the sign bits are the same
+
1563 return this.sub(other).isNegative ? -1 : 1
+
1564 }
+
1565)CODE";
+
1566
+
1567 // Prepare code template
+
1568 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
1569
+
1570 Write(code);
+
1571
+
1572 code = R"CODE(
+
1578 neg () {
+
1579 if (this.eq(INT64_MIN)) {
+
1580 return INT64_MIN
+
1581 }
+
1582 return this.not().add(INT64_ONE)
+
1583 }
+
1584
+
1591 add (other) {
+
1592 if (!Int64.isInt64(other) && !UInt64.isUInt64(other)) {
+
1593 other = Int64.fromValue(other)
+
1594 }
+
1595
+
1596 // Divide each number into 4 chunks of 16 bits, and then sum the chunks
+
1597
+
1598 let a48 = this.high >>> 16
+
1599 let a32 = this.high & 0xFFFF
+
1600 let a16 = this.low >>> 16
+
1601 let a00 = this.low & 0xFFFF
+
1602
+
1603 let b48 = other.high >>> 16
+
1604 let b32 = other.high & 0xFFFF
+
1605 let b16 = other.low >>> 16
+
1606 let b00 = other.low & 0xFFFF
+
1607
+
1608 let c48 = 0
+
1609 let c32 = 0
+
1610 let c16 = 0
+
1611 let c00 = 0
+
1612 c00 += a00 + b00
+
1613 c16 += c00 >>> 16
+
1614 c00 &= 0xFFFF
+
1615 c16 += a16 + b16
+
1616 c32 += c16 >>> 16
+
1617 c16 &= 0xFFFF
+
1618 c32 += a32 + b32
+
1619 c48 += c32 >>> 16
+
1620 c32 &= 0xFFFF
+
1621 c48 += a48 + b48
+
1622 c48 &= 0xFFFF
+
1623 return Int64.fromBits((c16 << 16) | c00, (c48 << 16) | c32)
+
1624 }
+
1625
+
1632 sub (other) {
+
1633 if (!Int64.isInt64(other) && !UInt64.isUInt64(other)) {
+
1634 other = Int64.fromValue(other)
+
1635 }
+
1636 return this.add(other.neg())
+
1637 }
+
1638
+
1645 mul (other) {
+
1646 if (this.isZero) {
+
1647 return INT64_ZERO
+
1648 }
+
1649 if (!Int64.isInt64(other) && !UInt64.isUInt64(other)) {
+
1650 other = Int64.fromValue(other)
+
1651 }
+
1652
+
1653 if (other.isZero) {
+
1654 return INT64_ZERO
+
1655 }
+
1656 if (this.eq(INT64_MIN)) {
+
1657 return other.isOdd ? INT64_MIN : INT64_ZERO
+
1658 }
+
1659 if (other.eq(INT64_MIN)) {
+
1660 return this.isOdd ? INT64_MIN : INT64_ZERO
+
1661 }
+
1662
+
1663 if (this.isNegative) {
+
1664 if (other.isNegative) {
+
1665 return this.neg().mul(other.neg())
+
1666 } else {
+
1667 return this.neg().mul(other).neg()
+
1668 }
+
1669 } else if (other.isNegative) {
+
1670 return this.mul(other.neg()).neg()
+
1671 }
+
1672
+
1673 // If both longs are small, use float multiplication
+
1674 if (this.lt(INT64_TWO_PWR_24) && other.lt(INT64_TWO_PWR_24)) {
+
1675 return Int64.fromNumber(this.toNumber() * other.toNumber())
+
1676 }
+
1677
+
1678 // Divide each long into 4 chunks of 16 bits, and then add up 4x4 products.
+
1679 // We can skip products that would overflow.
+
1680
+
1681 let a48 = this.high >>> 16
+
1682 let a32 = this.high & 0xFFFF
+
1683 let a16 = this.low >>> 16
+
1684 let a00 = this.low & 0xFFFF
+
1685
+
1686 let b48 = other.high >>> 16
+
1687 let b32 = other.high & 0xFFFF
+
1688 let b16 = other.low >>> 16
+
1689 let b00 = other.low & 0xFFFF
+
1690
+
1691 let c48 = 0
+
1692 let c32 = 0
+
1693 let c16 = 0
+
1694 let c00 = 0
+
1695 c00 += a00 * b00
+
1696 c16 += c00 >>> 16
+
1697 c00 &= 0xFFFF
+
1698 c16 += a16 * b00
+
1699 c32 += c16 >>> 16
+
1700 c16 &= 0xFFFF
+
1701 c16 += a00 * b16
+
1702 c32 += c16 >>> 16
+
1703 c16 &= 0xFFFF
+
1704 c32 += a32 * b00
+
1705 c48 += c32 >>> 16
+
1706 c32 &= 0xFFFF
+
1707 c32 += a16 * b16
+
1708 c48 += c32 >>> 16
+
1709 c32 &= 0xFFFF
+
1710 c32 += a00 * b32
+
1711 c48 += c32 >>> 16
+
1712 c32 &= 0xFFFF
+
1713 c48 += a48 * b00 + a32 * b16 + a16 * b32 + a00 * b48
+
1714 c48 &= 0xFFFF
+
1715 return Int64.fromBits((c16 << 16) | c00, (c48 << 16) | c32)
+
1716 }
+
1717
+
1724 div (other) {
+
1725 if (!Int64.isInt64(other) && !UInt64.isUInt64(other)) {
+
1726 other = Int64.fromValue(other)
+
1727 }
+
1728 if (other.isZero) {
+
1729 throw new Error('Division by zero!')
+
1730 }
+
1731
+
1732 if (this.isZero) {
+
1733 return INT64_ZERO
+
1734 }
+
1735
+
1736 let approx, rem, res
+
1737
+
1738 // This section is only relevant for signed longs and is derived from the closure library as a whole
+
1739 if (this.eq(INT64_MIN)) {
+
1740 // Recall that -MIN_VALUE == MIN_VALUE
+
1741 if (other.eq(INT64_ONE) || other.eq(INT64_NEG_ONE)) {
+
1742 return INT64_MIN
+
1743 } else if (other.eq(INT64_MIN)) {
+
1744 return INT64_ONE
+
1745 } else {
+
1746 // At this point, we have |other| >= 2, so |this/other| < |MIN_VALUE|
+
1747 let halfThis = this.shr(1)
+
1748 approx = halfThis.div(other).shl(1)
+
1749 if (approx.eq(INT64_ZERO)) {
+
1750 return other.isNegative ? INT64_ONE : INT64_NEG_ONE
+
1751 } else {
+
1752 rem = this.sub(other.mul(approx))
+
1753 res = approx.add(rem.div(other))
+
1754 return res
+
1755 }
+
1756 }
+
1757 } else if (other.eq(INT64_MIN)) {
+
1758 return INT64_ZERO
+
1759 }
+
1760
+
1761 if (this.isNegative) {
+
1762 if (other.isNegative) {
+
1763 return this.neg().div(other.neg())
+
1764 }
+
1765 return this.neg().div(other).neg()
+
1766 } else if (other.isNegative) {
+
1767 return this.div(other.neg()).neg()
+
1768 }
+
1769 res = INT64_ZERO
+
1770
+
1771 // Repeat the following until the remainder is less than other: find a floating-point that approximates
+
1772 // remainder / other *from below*, add this into the result, and subtract it from the remainder.
+
1773 // It is critical that the approximate value is less than or equal to the real value so that the
+
1774 // remainder never becomes negative.
+
1775 rem = this
+
1776 while (rem.gte(other)) {
+
1777 // Approximate the result of division. This may be a little greater or smaller than the actual value
+
1778 approx = Math.max(1, Math.floor(rem.toNumber() / other.toNumber()))
+
1779
+
1780 // We will tweak the approximate result by changing it in the 48-th digit or the smallest non-fractional
+
1781 // digit, whichever is larger.
+
1782 let log2 = Math.ceil(Math.log(approx) / Math.LN2)
+
1783 let delta = (log2 <= 48) ? 1 : Math.pow(2, log2 - 48)
+
1784
+
1785 // Decrease the approximation until it is smaller than the remainder.
+
1786 // Note that if it is too large, the product overflows and is negative.
+
1787 let approxRes = Int64.fromNumber(approx)
+
1788 let approxRem = approxRes.mul(other)
+
1789 while (approxRem.isNegative || approxRem.gt(rem)) {
+
1790 approx -= delta
+
1791 approxRes = Int64.fromNumber(approx)
+
1792 approxRem = approxRes.mul(other)
+
1793 }
+
1794
+
1795 // We know the answer can't be zero... and actually, zero would cause infinite recursion since
+
1796 // we would make no progress.
+
1797 if (approxRes.isZero) {
+
1798 approxRes = INT64_ONE
+
1799 }
+
1800
+
1801 res = res.add(approxRes)
+
1802 rem = rem.sub(approxRem)
+
1803 }
+
1804 return res
+
1805 }
+
1806
+
1813 mod (other) {
+
1814 if (!Int64.isInt64(other) && !UInt64.isUInt64(other)) {
+
1815 other = Int64.fromValue(other)
+
1816 }
+
1817 return this.sub(this.div(other).mul(other))
+
1818 }
+
1819
+
1825 not () {
+
1826 return Int64.fromBits(~this.low, ~this.high)
+
1827 }
+
1828
+
1835 and (other) {
+
1836 if (!Int64.isInt64(other) && !UInt64.isUInt64(other)) {
+
1837 other = Int64.fromValue(other)
+
1838 }
+
1839 return Int64.fromBits(this.low & other.low, this.high & other.high)
+
1840 }
+
1841
+
1848 or (other) {
+
1849 if (!Int64.isInt64(other) && !UInt64.isUInt64(other)) {
+
1850 other = Int64.fromValue(other)
+
1851 }
+
1852 return Int64.fromBits(this.low | other.low, this.high | other.high)
+
1853 }
+
1854
+
1861 xor (other) {
+
1862 if (!Int64.isInt64(other) && !UInt64.isUInt64(other)) {
+
1863 other = Int64.fromValue(other)
+
1864 }
+
1865 return Int64.fromBits(this.low ^ other.low, this.high ^ other.high)
+
1866 }
+
1867
+
1874 shl (numBits) {
+
1875 if (Int64.isInt64(numBits) || UInt64.isUInt64(numBits)) {
+
1876 numBits = numBits.toInt32()
+
1877 }
+
1878 if ((numBits &= 63) === 0) {
+
1879 return this
+
1880 } else if (numBits < 32) {
+
1881 return Int64.fromBits(this.low << numBits, (this.high << numBits) | (this.low >>> (32 - numBits)))
+
1882 } else {
+
1883 return Int64.fromBits(0, this.low << (numBits - 32))
+
1884 }
+
1885 }
+
1886
+
1893 shr (numBits) {
+
1894 if (Int64.isInt64(numBits) || UInt64.isUInt64(numBits)) {
+
1895 numBits = numBits.toInt32()
+
1896 }
+
1897 if ((numBits &= 63) === 0) {
+
1898 return this
+
1899 } else if (numBits < 32) {
+
1900 return Int64.fromBits((this.low >>> numBits) | (this.high << (32 - numBits)), this.high >> numBits)
+
1901 } else {
+
1902 return Int64.fromBits(this.high >> (numBits - 32), (this.high >= 0) ? 0 : -1)
+
1903 }
+
1904 }
+
1905
+
1912 shru (numBits) {
+
1913 if (Int64.isInt64(numBits) || UInt64.isUInt64(numBits)) {
+
1914 numBits = numBits.toInt32()
+
1915 }
+
1916 numBits &= 63
+
1917 if (numBits === 0) {
+
1918 return this
+
1919 } else {
+
1920 let high = this.high
+
1921 if (numBits < 32) {
+
1922 let low = this.low
+
1923 return Int64.fromBits((low >>> numBits) | (high << (32 - numBits)), high >>> numBits)
+
1924 } else if (numBits === 32) {
+
1925 return Int64.fromBits(high, 0)
+
1926 } else {
+
1927 return Int64.fromBits(high >>> (numBits - 32), 0)
+
1928 }
+
1929 }
+
1930 }
+
1931}
+
1932
+
1933Object.defineProperty(Int64.prototype, '__isInt64__', { value: true })
+
1934
+
1935// Useful constants
+
1936const INT64_TWO_PWR_16_DBL = 1 << 16
+
1937const INT64_TWO_PWR_24_DBL = 1 << 24
+
1938const INT64_TWO_PWR_32_DBL = INT64_TWO_PWR_16_DBL * INT64_TWO_PWR_16_DBL
+
1939const INT64_TWO_PWR_64_DBL = INT64_TWO_PWR_32_DBL * INT64_TWO_PWR_32_DBL
+
1940const INT64_TWO_PWR_63_DBL = INT64_TWO_PWR_64_DBL / 2
+
1941
+
1942// Int64 values cache
+
1943const Int64Cache = {}
+
1944
+
1945// Int64 values constants
+
1946const INT64_ZERO = Int64.fromInt32(0)
+
1947const INT64_ONE = Int64.fromInt32(1)
+
1948const INT64_NEG_ONE = Int64.fromInt32(-1)
+
1949const INT64_MIN = Int64.fromBits(0, 0x80000000 | 0)
+
1950const INT64_MAX = Int64.fromBits(0xFFFFFFFF | 0, 0x7FFFFFFF | 0)
+
1951const INT64_TWO_PWR_24 = Int64.fromInt32(INT64_TWO_PWR_24_DBL)
+
1952
+
1953exports.Int64 = Int64
+
1954)CODE";
+
1955
+
1956 // Prepare code template
+
1957 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
1958
+
1959 Write(code);
+
1960
+
1961 code = R"CODE(
+
1965class UInt64 {
+
1972 constructor (low, high) {
+
1973 this.low = low | 0
+
1974 this.high = high | 0
+
1975 }
+
1976
+
1981 static get ZERO () { return UINT64_ZERO }
+
1982
+
1987 static get MIN () { return UINT64_MIN }
+
1988
+
1993 static get MAX () { return UINT64_MAX }
+
1994
+
2000 static isUInt64 (obj) {
+
2001 return (obj && obj.__isUInt64__) === true
+
2002 }
+
2003
+
2010 static fromBits (lowBits, highBits) {
+
2011 return new UInt64(lowBits, highBits)
+
2012 }
+
2013
+
2020 static fromBytes (bytes, le = true) {
+
2021 return le ? UInt64.fromBytesLE(bytes) : UInt64.fromBytesBE(bytes)
+
2022 }
+
2023
+
2029 static fromBytesBE (bytes) {
+
2030 return new UInt64(
+
2031 bytes[4] << 24 |
+
2032 bytes[5] << 16 |
+
2033 bytes[6] << 8 |
+
2034 bytes[7] << 0,
+
2035 bytes[0] << 24 |
+
2036 bytes[1] << 16 |
+
2037 bytes[2] << 8 |
+
2038 bytes[3] << 0
+
2039 )
+
2040 }
+
2041
+
2047 static fromBytesLE (bytes) {
+
2048 return new UInt64(
+
2049 bytes[0] << 0 |
+
2050 bytes[1] << 8 |
+
2051 bytes[2] << 16 |
+
2052 bytes[3] << 24,
+
2053 bytes[4] << 0 |
+
2054 bytes[5] << 8 |
+
2055 bytes[6] << 16 |
+
2056 bytes[7] << 24
+
2057 )
+
2058 }
+
2059
+
2065 static fromInt32 (value) {
+
2066 value >>>= 0
+
2067
+
2068 let cache = ((value >= 0) && (value < 256))
+
2069 if (cache) {
+
2070 let cached = UInt64Cache[value]
+
2071 if (cached) {
+
2072 return cached
+
2073 }
+
2074 }
+
2075
+
2076 let result = UInt64.fromBits(value, ((value | 0) < 0) ? -1 : 0)
+
2077
+
2078 if (cache) {
+
2079 UInt64Cache[value] = result
+
2080 }
+
2081
+
2082 return result
+
2083 }
+
2084
+
2090 static fromNumber (value) {
+
2091 if (isNaN(value)) {
+
2092 return UINT64_ZERO
+
2093 }
+
2094 if (value < 0) {
+
2095 return UINT64_ZERO
+
2096 }
+
2097 if (value >= UINT64_TWO_PWR_64_DBL) {
+
2098 return UINT64_MAX
+
2099 }
+
2100 if (value < 0) {
+
2101 return UInt64.fromNumber(-value).neg()
+
2102 }
+
2103 return UInt64.fromBits((value % UINT64_TWO_PWR_32_DBL) | 0, (value / UINT64_TWO_PWR_32_DBL) | 0)
+
2104 }
+
2105
+
2112 static fromString (str, radix = 10) {
+
2113 if (str.length === 0) {
+
2114 throw new Error('Empty string!')
+
2115 }
+
2116 if ((str === 'NaN') || (str === 'Infinity') || (str === '+Infinity') || (str === '-Infinity')) {
+
2117 return UINT64_ZERO
+
2118 }
+
2119 radix = radix || 10
+
2120 if ((radix < 2) || (radix > 36)) {
+
2121 throw new RangeError('radix')
+
2122 }
+
2123
+
2124 let p = str.indexOf('-')
+
2125 if (p > 0) {
+
2126 throw new Error('Interior hyphen!')
+
2127 } else if (p === 0) {
+
2128 return UInt64.fromString(str.substring(1), radix).neg()
+
2129 }
+
2130
+
2131 // Do several (8) digits each time through the loop, so as to
+
2132 // minimize the calls to the very expensive emulated div.
+
2133 let radixToPower = UInt64.fromNumber(Math.pow(radix, 8))
+
2134
+
2135 let result = UINT64_ZERO
+
2136 for (let i = 0; i < str.length; i += 8) {
+
2137 let size = Math.min(8, str.length - i)
+
2138 let value = parseInt(str.substring(i, i + size), radix)
+
2139 if (size < 8) {
+
2140 let power = UInt64.fromNumber(Math.pow(radix, size))
+
2141 result = result.mul(power).add(UInt64.fromNumber(value))
+
2142 } else {
+
2143 result = result.mul(radixToPower)
+
2144 result = result.add(UInt64.fromNumber(value))
+
2145 }
+
2146 }
+
2147 return result
+
2148 }
+
2149
+
2155 static fromValue (value) {
+
2156 if (typeof value === 'number') {
+
2157 return UInt64.fromNumber(value)
+
2158 }
+
2159 if (typeof value === 'string') {
+
2160 return UInt64.fromString(value, 10)
+
2161 }
+
2162 return UInt64.fromBits(value.low, value.high)
+
2163 }
+
2164
+
2171 toBytes (le = true) {
+
2172 return le ? this.toBytesLE() : this.toBytesBE()
+
2173 }
+
2174
+
2180 toBytesBE () {
+
2181 let hi = this.high
+
2182 let lo = this.low
+
2183 return [
+
2184 hi >>> 24 & 0xff,
+
2185 hi >>> 16 & 0xff,
+
2186 hi >>> 8 & 0xff,
+
2187 hi >>> 0 & 0xff,
+
2188 lo >>> 24 & 0xff,
+
2189 lo >>> 16 & 0xff,
+
2190 lo >>> 8 & 0xff,
+
2191 lo >>> 0 & 0xff
+
2192 ]
+
2193 }
+
2194
+
2200 toBytesLE () {
+
2201 let hi = this.high
+
2202 let lo = this.low
+
2203 return [
+
2204 lo >>> 0 & 0xff,
+
2205 lo >>> 8 & 0xff,
+
2206 lo >>> 16 & 0xff,
+
2207 lo >>> 24 & 0xff,
+
2208 hi >>> 0 & 0xff,
+
2209 hi >>> 8 & 0xff,
+
2210 hi >>> 16 & 0xff,
+
2211 hi >>> 24 & 0xff
+
2212 ]
+
2213 }
+
2214
+
2220 toInt32 () {
+
2221 return this.low >>> 0
+
2222 }
+
2223
+
2229 toNumber () {
+
2230 return ((this.high >>> 0) * UINT64_TWO_PWR_32_DBL) + (this.low >>> 0)
+
2231 }
+
2232
+
2239 toString (radix = 10) {
+
2240 radix = radix || 10
+
2241 if ((radix < 2) || (radix > 36)) {
+
2242 throw new RangeError('Radix must be in range [2, 36]')
+
2243 }
+
2244 if (this.isZero) {
+
2245 return '0'
+
2246 }
+
2247 if (this.isNegative) {
+
2248 if (this.eq(UINT64_MIN)) {
+
2249 // We need to change the Long value before it can be negated, so we remove
+
2250 // the bottom-most digit in this base and then recurse to do the rest.
+
2251 let radixLong = UInt64.fromNumber(radix)
+
2252 let div = this.div(radixLong)
+
2253 let rem1 = div.mul(radixLong).sub(this)
+
2254 return div.toString(radix) + rem1.toInt32().toString(radix)
+
2255 } else {
+
2256 return '-' + this.neg().toString(radix)
+
2257 }
+
2258 }
+
2259
+
2260 // Do several (6) digits each time through the loop, so as to
+
2261 // minimize the calls to the very expensive emulated div.
+
2262 let radixToPower = UInt64.fromNumber(Math.pow(radix, 6))
+
2263 let rem = this
+
2264 let result = ''
+
2265 while (true) {
+
2266 let remDiv = rem.div(radixToPower)
+
2267 let intval = rem.sub(remDiv.mul(radixToPower)).toInt32() >>> 0
+
2268 let digits = intval.toString(radix)
+
2269 rem = remDiv
+
2270 if (rem.isZero) {
+
2271 return digits + result
+
2272 } else {
+
2273 while (digits.length < 6) {
+
2274 digits = '0' + digits
+
2275 }
+
2276 result = '' + digits + result
+
2277 }
+
2278 }
+
2279 }
+
2280
+
2286 toSigned () {
+
2287 return Int64.fromBits(this.low, this.high)
+
2288 }
+
2289
+
2295 toUnsigned () {
+
2296 return this
+
2297 }
+
2298
+
2304 get HighBits () {
+
2305 return this.high
+
2306 }
+
2307
+
2313 get HighBitsUnsigned () {
+
2314 return this.high >>> 0
+
2315 }
+
2316
+
2322 get LowBits () {
+
2323 return this.low
+
2324 }
+
2325
+
2331 get LowBitsUnsigned () {
+
2332 return this.low >>> 0
+
2333 }
+
2334
+
2340 get NumBits () {
+
2341 if (this.isNegative) {
+
2342 return this.eq(UINT64_MIN) ? 64 : this.neg().NumBits
+
2343 }
+
2344
+
2345 let val = (this.high !== 0) ? this.high : this.low
+
2346
+
2347 let bit
+
2348 for (bit = 31; bit > 0; bit--) {
+
2349 if ((val & (1 << bit)) !== 0) {
+
2350 break
+
2351 }
+
2352 }
+
2353
+
2354 return (this.high !== 0) ? (bit + 33) : (bit + 1)
+
2355 }
+
2356
+
2362 get isZero () {
+
2363 return (this.high === 0) && (this.low === 0)
+
2364 }
+
2365
+
2371 get isPositive () {
+
2372 return true
+
2373 }
+
2374
+
2380 get isNegative () {
+
2381 return false
+
2382 }
+
2383
+
2389 get isOdd () {
+
2390 return (this.low & 1) === 1
+
2391 }
+
2392
+
2398 get isEven () {
+
2399 return (this.low & 1) === 0
+
2400 }
+
2401
+
2408 eq (other) {
+
2409 if (Int64.isInt64(other)) {
+
2410 if (((this.high >>> 31) === 1) && ((other.high >>> 31) === 1)) {
+
2411 return false
+
2412 }
+
2413 } else if (!UInt64.isUInt64(other)) {
+
2414 other = UInt64.fromValue(other)
+
2415 }
+
2416 return (this.high === other.high) && (this.low === other.low)
+
2417 }
+
2418
+
2425 ne (other) {
+
2426 return !this.eq(other)
+
2427 }
+
2428
+
2435 lt (other) {
+
2436 return this.cmp(other) < 0
+
2437 }
+
2438
+
2445 lte (other) {
+
2446 return this.cmp(other) <= 0
+
2447 }
+
2448
+
2455 gt (other) {
+
2456 return this.cmp(other) > 0
+
2457 }
+
2458
+
2465 gte (other) {
+
2466 return this.cmp(other) >= 0
+
2467 }
+
2468
+
2475 cmp (other) {
+
2476 if (!Int64.isInt64(other) && !UInt64.isUInt64(other)) {
+
2477 other = UInt64.fromValue(other)
+
2478 }
+
2479 if (this.eq(other)) {
+
2480 return 0
+
2481 }
+
2482 let thisNeg = this.isNegative
+
2483 let otherNeg = other.isNegative
+
2484 if (thisNeg && !otherNeg) {
+
2485 return -1
+
2486 }
+
2487 if (!thisNeg && otherNeg) {
+
2488 return 1
+
2489 }
+
2490 // Both are positive if at least one is unsigned
+
2491 return (((other.high >>> 0) > (this.high >>> 0)) || ((other.high === this.high) && (other.low >>> 0) > (this.low >>> 0))) ? -1 : 1
+
2492 }
+
2493)CODE";
+
2494
+
2495 // Prepare code template
+
2496 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2497
+
2498 Write(code);
+
2499
+
2500 code = R"CODE(
+
2506 neg () {
+
2507 return this.not().add(UINT64_ONE)
+
2508 }
+
2509
+
2516 add (other) {
+
2517 if (!Int64.isInt64(other) && !UInt64.isUInt64(other)) {
+
2518 other = UInt64.fromValue(other)
+
2519 }
+
2520
+
2521 // Divide each number into 4 chunks of 16 bits, and then sum the chunks
+
2522
+
2523 let a48 = this.high >>> 16
+
2524 let a32 = this.high & 0xFFFF
+
2525 let a16 = this.low >>> 16
+
2526 let a00 = this.low & 0xFFFF
+
2527
+
2528 let b48 = other.high >>> 16
+
2529 let b32 = other.high & 0xFFFF
+
2530 let b16 = other.low >>> 16
+
2531 let b00 = other.low & 0xFFFF
+
2532
+
2533 let c48 = 0
+
2534 let c32 = 0
+
2535 let c16 = 0
+
2536 let c00 = 0
+
2537 c00 += a00 + b00
+
2538 c16 += c00 >>> 16
+
2539 c00 &= 0xFFFF
+
2540 c16 += a16 + b16
+
2541 c32 += c16 >>> 16
+
2542 c16 &= 0xFFFF
+
2543 c32 += a32 + b32
+
2544 c48 += c32 >>> 16
+
2545 c32 &= 0xFFFF
+
2546 c48 += a48 + b48
+
2547 c48 &= 0xFFFF
+
2548 return UInt64.fromBits((c16 << 16) | c00, (c48 << 16) | c32)
+
2549 }
+
2550
+
2557 sub (other) {
+
2558 if (!Int64.isInt64(other) && !UInt64.isUInt64(other)) {
+
2559 other = UInt64.fromValue(other)
+
2560 }
+
2561 return this.add(other.neg())
+
2562 }
+
2563
+
2570 mul (other) {
+
2571 if (this.isZero) {
+
2572 return UINT64_ZERO
+
2573 }
+
2574 if (!Int64.isInt64(other) && !UInt64.isUInt64(other)) {
+
2575 other = UInt64.fromValue(other)
+
2576 }
+
2577
+
2578 if (other.isZero) {
+
2579 return UINT64_ZERO
+
2580 }
+
2581 if (this.eq(UINT64_MIN)) {
+
2582 return other.isOdd ? UINT64_MIN : UINT64_ZERO
+
2583 }
+
2584 if (other.eq(UINT64_MIN)) {
+
2585 return this.isOdd ? UINT64_MIN : UINT64_ZERO
+
2586 }
+
2587
+
2588 if (this.isNegative) {
+
2589 if (other.isNegative) {
+
2590 return this.neg().mul(other.neg())
+
2591 } else {
+
2592 return this.neg().mul(other).neg()
+
2593 }
+
2594 } else if (other.isNegative) {
+
2595 return this.mul(other.neg()).neg()
+
2596 }
+
2597
+
2598 // If both longs are small, use float multiplication
+
2599 if (this.lt(UINT64_TWO_PWR_24) && other.lt(UINT64_TWO_PWR_24)) {
+
2600 return UInt64.fromNumber(this.toNumber() * other.toNumber())
+
2601 }
+
2602
+
2603 // Divide each long into 4 chunks of 16 bits, and then add up 4x4 products.
+
2604 // We can skip products that would overflow.
+
2605
+
2606 let a48 = this.high >>> 16
+
2607 let a32 = this.high & 0xFFFF
+
2608 let a16 = this.low >>> 16
+
2609 let a00 = this.low & 0xFFFF
+
2610
+
2611 let b48 = other.high >>> 16
+
2612 let b32 = other.high & 0xFFFF
+
2613 let b16 = other.low >>> 16
+
2614 let b00 = other.low & 0xFFFF
+
2615
+
2616 let c48 = 0
+
2617 let c32 = 0
+
2618 let c16 = 0
+
2619 let c00 = 0
+
2620 c00 += a00 * b00
+
2621 c16 += c00 >>> 16
+
2622 c00 &= 0xFFFF
+
2623 c16 += a16 * b00
+
2624 c32 += c16 >>> 16
+
2625 c16 &= 0xFFFF
+
2626 c16 += a00 * b16
+
2627 c32 += c16 >>> 16
+
2628 c16 &= 0xFFFF
+
2629 c32 += a32 * b00
+
2630 c48 += c32 >>> 16
+
2631 c32 &= 0xFFFF
+
2632 c32 += a16 * b16
+
2633 c48 += c32 >>> 16
+
2634 c32 &= 0xFFFF
+
2635 c32 += a00 * b32
+
2636 c48 += c32 >>> 16
+
2637 c32 &= 0xFFFF
+
2638 c48 += a48 * b00 + a32 * b16 + a16 * b32 + a00 * b48
+
2639 c48 &= 0xFFFF
+
2640 return UInt64.fromBits((c16 << 16) | c00, (c48 << 16) | c32)
+
2641 }
+
2642
+
2649 div (other) {
+
2650 if (!Int64.isInt64(other) && !UInt64.isUInt64(other)) {
+
2651 other = UInt64.fromValue(other)
+
2652 }
+
2653 if (other.isZero) {
+
2654 throw new Error('Division by zero!')
+
2655 }
+
2656
+
2657 if (this.isZero) {
+
2658 return UINT64_ZERO
+
2659 }
+
2660
+
2661 let approx, rem, res
+
2662
+
2663 // The algorithm below has not been made for unsigned longs. It's therefore required to take special care of
+
2664 // the MSB prior to running it.
+
2665 if (Int64.isInt64(other)) {
+
2666 other = other.toUnsigned()
+
2667 }
+
2668 if (other.gt(this)) {
+
2669 return UINT64_ZERO
+
2670 }
+
2671 // 15 >>> 1 = 7 ; with divisor = 8 ; true
+
2672 if (other.gt(this.shru(1))) {
+
2673 return UINT64_ONE
+
2674 }
+
2675 res = UINT64_ZERO
+
2676
+
2677 // Repeat the following until the remainder is less than other: find a floating-point that approximates
+
2678 // remainder / other *from below*, add this into the result, and subtract it from the remainder.
+
2679 // It is critical that the approximate value is less than or equal to the real value so that the
+
2680 // remainder never becomes negative.
+
2681 rem = this
+
2682 while (rem.gte(other)) {
+
2683 // Approximate the result of division. This may be a little greater or smaller than the actual value
+
2684 approx = Math.max(1, Math.floor(rem.toNumber() / other.toNumber()))
+
2685
+
2686 // We will tweak the approximate result by changing it in the 48-th digit or the smallest non-fractional
+
2687 // digit, whichever is larger.
+
2688 let log2 = Math.ceil(Math.log(approx) / Math.LN2)
+
2689 let delta = (log2 <= 48) ? 1 : Math.pow(2, log2 - 48)
+
2690
+
2691 // Decrease the approximation until it is smaller than the remainder.
+
2692 // Note that if it is too large, the product overflows and is negative.
+
2693 let approxRes = Int64.fromNumber(approx)
+
2694 let approxRem = approxRes.mul(other)
+
2695 while (approxRem.isNegative || approxRem.gt(rem)) {
+
2696 approx -= delta
+
2697 approxRes = UInt64.fromNumber(approx)
+
2698 approxRem = approxRes.mul(other)
+
2699 }
+
2700
+
2701 // We know the answer can't be zero... and actually, zero would cause infinite recursion since
+
2702 // we would make no progress.
+
2703 if (approxRes.isZero) {
+
2704 approxRes = UINT64_ONE
+
2705 }
+
2706
+
2707 res = res.add(approxRes)
+
2708 rem = rem.sub(approxRem)
+
2709 }
+
2710 return res
+
2711 }
+
2712
+
2719 mod (other) {
+
2720 if (!Int64.isInt64(other) && !UInt64.isUInt64(other)) {
+
2721 other = UInt64.fromValue(other)
+
2722 }
+
2723 return this.sub(this.div(other).mul(other))
+
2724 }
+
2725
+
2731 not () {
+
2732 return UInt64.fromBits(~this.low, ~this.high)
+
2733 }
+
2734
+
2741 and (other) {
+
2742 if (!Int64.isInt64(other) && !UInt64.isUInt64(other)) {
+
2743 other = UInt64.fromValue(other)
+
2744 }
+
2745 return UInt64.fromBits(this.low & other.low, this.high & other.high)
+
2746 }
+
2747
+
2754 or (other) {
+
2755 if (!Int64.isInt64(other) && !UInt64.isUInt64(other)) {
+
2756 other = UInt64.fromValue(other)
+
2757 }
+
2758 return UInt64.fromBits(this.low | other.low, this.high | other.high)
+
2759 }
+
2760
+
2767 xor (other) {
+
2768 if (!Int64.isInt64(other) && !UInt64.isUInt64(other)) {
+
2769 other = UInt64.fromValue(other)
+
2770 }
+
2771 return UInt64.fromBits(this.low ^ other.low, this.high ^ other.high)
+
2772 }
+
2773
+
2780 shl (numBits) {
+
2781 if (Int64.isInt64(numBits) || UInt64.isUInt64(numBits)) {
+
2782 numBits = numBits.toInt32()
+
2783 }
+
2784 if ((numBits &= 63) === 0) {
+
2785 return this
+
2786 } else if (numBits < 32) {
+
2787 return UInt64.fromBits(this.low << numBits, (this.high << numBits) | (this.low >>> (32 - numBits)))
+
2788 } else {
+
2789 return UInt64.fromBits(0, this.low << (numBits - 32))
+
2790 }
+
2791 }
+
2792
+
2799 shr (numBits) {
+
2800 if (Int64.isInt64(numBits) || UInt64.isUInt64(numBits)) {
+
2801 numBits = numBits.toInt32()
+
2802 }
+
2803 if ((numBits &= 63) === 0) {
+
2804 return this
+
2805 } else if (numBits < 32) {
+
2806 return UInt64.fromBits((this.low >>> numBits) | (this.high << (32 - numBits)), this.high >> numBits)
+
2807 } else {
+
2808 return UInt64.fromBits(this.high >> (numBits - 32), (this.high >= 0) ? 0 : -1)
+
2809 }
+
2810 }
+
2811
+
2818 shru (numBits) {
+
2819 if (Int64.isInt64(numBits) || UInt64.isUInt64(numBits)) {
+
2820 numBits = numBits.toInt32()
+
2821 }
+
2822 numBits &= 63
+
2823 if (numBits === 0) {
+
2824 return this
+
2825 } else {
+
2826 let high = this.high
+
2827 if (numBits < 32) {
+
2828 let low = this.low
+
2829 return UInt64.fromBits((low >>> numBits) | (high << (32 - numBits)), high >>> numBits)
+
2830 } else if (numBits === 32) {
+
2831 return UInt64.fromBits(high, 0)
+
2832 } else {
+
2833 return UInt64.fromBits(high >>> (numBits - 32), 0)
+
2834 }
+
2835 }
+
2836 }
+
2837}
+
2838
+
2839Object.defineProperty(UInt64.prototype, '__isUInt64__', { value: true })
+
2840
+
2841// Useful constants
+
2842const UINT64_TWO_PWR_16_DBL = 1 << 16
+
2843const UINT64_TWO_PWR_24_DBL = 1 << 24
+
2844const UINT64_TWO_PWR_32_DBL = UINT64_TWO_PWR_16_DBL * UINT64_TWO_PWR_16_DBL
+
2845const UINT64_TWO_PWR_64_DBL = UINT64_TWO_PWR_32_DBL * UINT64_TWO_PWR_32_DBL
+
2846
+
2847// UInt64 values cache
+
2848const UInt64Cache = {}
+
2849
+
2850// Int64 values constants
+
2851const UINT64_ZERO = UInt64.fromInt32(0)
+
2852const UINT64_ONE = UInt64.fromInt32(1)
+
2853const UINT64_MIN = UInt64.fromInt32(0)
+
2854const UINT64_MAX = UInt64.fromBits(0xFFFFFFFF | 0, 0xFFFFFFFF | 0)
+
2855const UINT64_TWO_PWR_24 = UInt64.fromInt32(UINT64_TWO_PWR_24_DBL)
+
2856
+
2857exports.UInt64 = UInt64
+
2858)CODE";
+
2859
+
2860 // Prepare code template
+
2861 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2862
+
2863 Write(code);
+
2864
+
2865 // Generate common footer
+
2866 GenerateFooter();
+
2867
+
2868 // Close the common file
+
2869 WriteEnd();
+
2870 Store(common);
+
2871}
+
2872
+
2873void GeneratorJavaScript::GenerateUUID(const CppCommon::Path& path)
+
2874{
+
2875 // Generate the common file
+
2876 CppCommon::Path common = path / "uuid.js";
+
2877 WriteBegin();
+
2878
+
2879 // Generate common header
+
2880 GenerateHeader("FBE");
+
2881
+
2882 std::string code = R"CODE(
+
2883/* eslint-disable prefer-const,no-loss-of-precision */
+
2884'use strict'
+
2885
+
2900class UUID {
+
2906 constructor (value = undefined) {
+
2907 if (value == null) {
+
2908 this.data = new Uint8Array(16)
+
2909 } else if ((value instanceof Array) || (value instanceof Uint8Array)) {
+
2910 this.data = UUID.fromBytes(value).data.slice()
+
2911 } else if ((typeof value === 'string') || (value instanceof String)) {
+
2912 this.data = UUID.fromString(value).data.slice()
+
2913 } else if (value instanceof UUID) {
+
2914 this.data = value.data.slice()
+
2915 } else {
+
2916 throw new Error('Unsupported UUID base type ' + (typeof value))
+
2917 }
+
2918 }
+
2919
+
2925 static isUUID (obj) {
+
2926 return (obj && obj.__isUUID__) === true
+
2927 }
+
2928
+
2934 static fromBytes (bytes) {
+
2935 let result = new UUID()
+
2936 for (let i = 0; i < bytes.length; i++) {
+
2937 result.data[i] = bytes[i] & 0xFF
+
2938 }
+
2939 return result
+
2940 }
+
2941
+
2954 static fromParts (timeLow, timeMid, timeHiAndVersion, clockSeqHiAndReserved, clockSeqLow, nodeLow, nodeMid, nodeHi) {
+
2955 let result = new UUID()
+
2956 result.data[0] = (timeLow >>> 24)
+
2957 result.data[1] = (timeLow >>> 16)
+
2958 result.data[2] = (timeLow >>> 8)
+
2959 result.data[3] = (timeLow & 0xFF)
+
2960 result.data[4] = (timeMid >>> 8)
+
2961 result.data[5] = (timeMid & 0xFF)
+
2962 result.data[6] = (timeHiAndVersion >>> 8)
+
2963 result.data[7] = (timeHiAndVersion & 0xFF)
+
2964 result.data[8] = (clockSeqHiAndReserved & 0xFF)
+
2965 result.data[9] = (clockSeqLow & 0xFF)
+
2966 result.data[10] = (nodeLow >>> 24)
+
2967 result.data[11] = (nodeLow >>> 16)
+
2968 result.data[12] = (nodeLow >>> 8)
+
2969 result.data[13] = (nodeLow & 0xFF)
+
2970 result.data[14] = (nodeMid & 0xFF)
+
2971 result.data[15] = (nodeHi & 0xFF)
+
2972 return result
+
2973 }
+
2974
+
2980 static fromString (str) {
+
2981 if (str.length === 0) {
+
2982 throw new Error('Empty string!')
+
2983 }
+
2984 let result = new UUID()
+
2985 str = str.replace(/[{}-]/g, '')
+
2986 for (let i = 0; i < str.length; i++) {
+
2987 result.data[i] = parseInt(str.substr(i * 2, 2), 16)
+
2988 }
+
2989 return result
+
2990 }
+
2991
+
2996 static nil () {
+
2997 return new UUID()
+
2998 }
+
2999
+
3004 static sequential () {
+
3005 let now = new Date().getTime()
+
3006 let sequence = Math.floor(Math.random() * TWO_POW_14)
+
3007 let nodeHi = Math.floor(Math.random() * TWO_POW_8)
+
3008 let nodeMid = Math.floor(Math.random() * TWO_POW_8)
+
3009 let nodeLow = Math.floor(Math.random() * TWO_POW_32)
+
3010 let tick = Math.floor(Math.random() * TWO_POW_4)
+
3011 let timestamp = 0
+
3012 let timestampRatio = 1 / 4
+
3013
+
3014 if (now !== timestamp) {
+
3015 if (now < timestamp) {
+
3016 sequence++
+
3017 }
+
3018 timestamp = now
+
3019 tick = Math.floor(Math.random() * TWO_POW_4)
+
3020 } else if ((Math.random() < timestampRatio) && (tick < 9984)) {
+
3021 tick += 1 + Math.floor(Math.random() * TWO_POW_4)
+
3022 } else {
+
3023 sequence++
+
3024 }
+
3025
+
3026 let ts = timestamp - Date.UTC(1582, 9, 15)
+
3027 let hm = ((ts / 0x100000000) * 10000) & 0xFFFFFFF
+
3028 let tl = ((ts & 0xFFFFFFF) * 10000) % 0x100000000 + tick
+
3029 let thav = (hm >>> 16 & 0xFFF) | 0x1000
+
3030
+
3031 sequence &= 0x3FFF
+
3032 let cshar = (sequence >>> 8) | 0x80
+
3033 let csl = sequence & 0xFF
+
3034
+
3035 return UUID.fromParts(tl, hm & 0xFFFF, thav, cshar, csl, nodeLow, nodeMid, nodeHi)
+
3036 }
+
3037
+
3042 static random () {
+
3043 return UUID.fromParts(
+
3044 Math.floor(Math.random() * TWO_POW_32),
+
3045 Math.floor(Math.random() * TWO_POW_16),
+
3046 0x4000 | Math.floor(Math.random() * TWO_POW_12),
+
3047 0x80 | Math.floor(Math.random() * TWO_POW_6),
+
3048 Math.floor(Math.random() * TWO_POW_8),
+
3049 Math.floor(Math.random() * TWO_POW_32),
+
3050 Math.floor(Math.random() * TWO_POW_8),
+
3051 Math.floor(Math.random() * TWO_POW_8)
+
3052 )
+
3053 }
+
3054
+
3060 toBytes () {
+
3061 let result = []
+
3062 for (let i = 0; i < this.data.length; i++) {
+
3063 result.push(this.data[i])
+
3064 }
+
3065 return result
+
3066 }
+
3067
+
3073 toString () {
+
3074 let result = ''
+
3075 for (let i = 0; i < this.data.length; i++) {
+
3076 result += (this.data[i] >>> 4).toString(16)
+
3077 result += (this.data[i] & 0xF).toString(16)
+
3078 if ((i === 3) || (i === 5) || (i === 7) || (i === 9)) {
+
3079 result += '-'
+
3080 }
+
3081 }
+
3082 return result
+
3083 }
+
3084
+
3091 eq (other) {
+
3092 if (!UUID.isUUID(other)) {
+
3093 return false
+
3094 }
+
3095 for (let i = 0; i < this.data.length; i++) {
+
3096 if (this.data[i] !== other.data[i]) {
+
3097 return false
+
3098 }
+
3099 }
+
3100 return true
+
3101 }
+
3102
+
3109 ne (other) {
+
3110 return !this.eq(other)
+
3111 }
+
3112
+
3119 lt (other) {
+
3120 return this.cmp(other) < 0
+
3121 }
+
3122
+
3129 lte (other) {
+
3130 return this.cmp(other) <= 0
+
3131 }
+
3132
+
3139 gt (other) {
+
3140 return this.cmp(other) > 0
+
3141 }
+
3142
+
3149 gte (other) {
+
3150 return this.cmp(other) >= 0
+
3151 }
+
3152
+
3159 cmp (other) {
+
3160 if (!UUID.isUUID(other)) {
+
3161 return 1
+
3162 }
+
3163 for (let i = 0; i < this.data.length; i++) {
+
3164 let diff = this.data[i] - other.data[i]
+
3165 if (diff !== 0) {
+
3166 return diff
+
3167 }
+
3168 }
+
3169 return 0
+
3170 }
+
3171}
+
3172
+
3173Object.defineProperty(UUID.prototype, '__isUUID__', { value: true })
+
3174
+
3175// UUID internal constants
+
3176const TWO_POW_32 = 4294967296
+
3177const TWO_POW_16 = 65536
+
3178const TWO_POW_14 = 16384
+
3179const TWO_POW_12 = 4096
+
3180const TWO_POW_8 = 256
+
3181const TWO_POW_6 = 64
+
3182const TWO_POW_4 = 16
+
3183
+
3184exports.UUID = UUID
+
3185)CODE";
+
3186
+
3187 // Prepare code template
+
3188 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
3189
+
3190 Write(code);
+
3191
+
3192 // Generate common footer
+
3193 GenerateFooter();
+
3194
+
3195 // Close the common file
+
3196 WriteEnd();
+
3197 Store(common);
+
3198}
+
3199
+
3200void GeneratorJavaScript::GenerateIEEE754(const CppCommon::Path& path)
+
3201{
+
3202 // Generate the common file
+
3203 CppCommon::Path common = path / "ieee754.js";
+
3204 WriteBegin();
+
3205
+
3206 // Generate common header
+
3207 GenerateHeader("FBE");
+
3208
+
3209 std::string code = R"CODE(
+
3210/* eslint-disable prefer-const,no-loss-of-precision */
+
3211'use strict'
+
3212
+
3222let ieee754read = function (buffer, offset, isLE, mLen, nBytes) {
+
3223 let e, m
+
3224 let eLen = (nBytes * 8) - mLen - 1
+
3225 let eMax = (1 << eLen) - 1
+
3226 let eBias = eMax >> 1
+
3227 let nBits = -7
+
3228 let i = isLE ? (nBytes - 1) : 0
+
3229 let d = isLE ? -1 : 1
+
3230 let s = buffer[offset + i]
+
3231
+
3232 i += d
+
3233
+
3234 e = s & ((1 << (-nBits)) - 1)
+
3235 s >>= (-nBits)
+
3236 nBits += eLen
+
3237 for (; nBits > 0; e = (e * 256) + buffer[offset + i], i += d, nBits -= 8);
+
3238
+
3239 m = e & ((1 << (-nBits)) - 1)
+
3240 e >>= (-nBits)
+
3241 nBits += mLen
+
3242 for (; nBits > 0; m = (m * 256) + buffer[offset + i], i += d, nBits -= 8);
+
3243
+
3244 if (e === 0) {
+
3245 e = 1 - eBias
+
3246 } else if (e === eMax) {
+
3247 return m ? NaN : ((s ? -1 : 1) * Infinity)
+
3248 } else {
+
3249 m = m + Math.pow(2, mLen)
+
3250 e = e - eBias
+
3251 }
+
3252 return (s ? -1 : 1) * m * Math.pow(2, e - mLen)
+
3253}
+
3254
+
3255exports.ieee754read = ieee754read
+
3256
+
3266let ieee754write = function (buffer, offset, value, isLE, mLen, nBytes) {
+
3267 let e, m, c
+
3268 let eLen = (nBytes * 8) - mLen - 1
+
3269 let eMax = (1 << eLen) - 1
+
3270 let eBias = eMax >> 1
+
3271 let rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0)
+
3272 let i = isLE ? 0 : (nBytes - 1)
+
3273 let d = isLE ? 1 : -1
+
3274 let s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0
+
3275
+
3276 value = Math.abs(value)
+
3277
+
3278 if (isNaN(value) || value === Infinity) {
+
3279 m = isNaN(value) ? 1 : 0
+
3280 e = eMax
+
3281 } else {
+
3282 e = Math.floor(Math.log(value) / Math.LN2)
+
3283 if (value * (c = Math.pow(2, -e)) < 1) {
+
3284 e--
+
3285 c *= 2
+
3286 }
+
3287 if (e + eBias >= 1) {
+
3288 value += rt / c
+
3289 } else {
+
3290 value += rt * Math.pow(2, 1 - eBias)
+
3291 }
+
3292 if (value * c >= 2) {
+
3293 e++
+
3294 c /= 2
+
3295 }
+
3296
+
3297 if (e + eBias >= eMax) {
+
3298 m = 0
+
3299 e = eMax
+
3300 } else if (e + eBias >= 1) {
+
3301 m = ((value * c) - 1) * Math.pow(2, mLen)
+
3302 e = e + eBias
+
3303 } else {
+
3304 m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen)
+
3305 e = 0
+
3306 }
+
3307 }
+
3308
+
3309 for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8);
+
3310
+
3311 e = (e << mLen) | m
+
3312 eLen += mLen
+
3313 for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8);
+
3314
+
3315 buffer[offset + i - d] |= s * 128
+
3316}
+
3317
+
3318exports.ieee754write = ieee754write
+
3319)CODE";
+
3320
+
3321 // Prepare code template
+
3322 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
3323
+
3324 Write(code);
+
3325
+
3326 // Generate common footer
+
3327 GenerateFooter();
+
3328
+
3329 // Close the common file
+
3330 WriteEnd();
+
3331 Store(common);
+
3332}
+
3333
+
3334void GeneratorJavaScript::GenerateUTF8(const CppCommon::Path& path)
+
3335{
+
3336 // Generate the common file
+
3337 CppCommon::Path common = path / "utf8.js";
+
3338 WriteBegin();
+
3339
+
3340 // Generate common header
+
3341 GenerateHeader("FBE");
+
3342
+
3343 std::string code = R"CODE(
+
3344/* eslint-disable prefer-const,no-loss-of-precision */
+
3345'use strict'
+
3346
+
3352let utf8count = function (str) {
+
3353 let bytes = 0
+
3354 for (let i = 0; i < str.length; i++) {
+
3355 let codePoint = str.charCodeAt(i)
+
3356 if (codePoint < 0x80) {
+
3357 bytes++
+
3358 } else if ((codePoint > 0x7F) && (codePoint < 0x800)) {
+
3359 bytes = bytes + 2
+
3360 } else {
+
3361 bytes = bytes + 3
+
3362 }
+
3363 }
+
3364 return bytes
+
3365}
+
3366
+
3367exports.utf8count = utf8count
+
3368
+
3375let utf8encode = function (buffer, offset, str) {
+
3376 let units = Infinity
+
3377 let codePoint
+
3378 let index = offset
+
3379 let length = str.length
+
3380 let leadSurrogate = null
+
3381
+
3382 for (let i = 0; i < length; ++i) {
+
3383 codePoint = str.charCodeAt(i)
+
3384
+
3385 // Is surrogate component...
+
3386 if ((codePoint > 0xD7FF) && (codePoint < 0xE000)) {
+
3387 // Last char was a lead
+
3388 if (!leadSurrogate) {
+
3389 // No lead yet
+
3390 if (codePoint > 0xDBFF) {
+
3391 // Unexpected trail
+
3392 if ((units -= 3) > -1) {
+
3393 buffer[index++] = 0xEF
+
3394 buffer[index++] = 0xBF
+
3395 buffer[index++] = 0xBD
+
3396 }
+
3397 continue
+
3398 } else if ((i + 1) === length) {
+
3399 // Unpaired lead
+
3400 if ((units -= 3) > -1) {
+
3401 buffer[index++] = 0xEF
+
3402 buffer[index++] = 0xBF
+
3403 buffer[index++] = 0xBD
+
3404 }
+
3405 continue
+
3406 }
+
3407
+
3408 // Valid lead
+
3409 leadSurrogate = codePoint
+
3410
+
3411 continue
+
3412 }
+
3413
+
3414 // 2 leads in a row
+
3415 if (codePoint < 0xDC00) {
+
3416 if ((units -= 3) > -1) {
+
3417 buffer[index++] = 0xEF
+
3418 buffer[index++] = 0xBF
+
3419 buffer[index++] = 0xBD
+
3420 }
+
3421 leadSurrogate = codePoint
+
3422 continue
+
3423 }
+
3424
+
3425 // Valid surrogate pair
+
3426 codePoint = (((leadSurrogate - 0xD800) << 10) | (codePoint - 0xDC00)) + 0x10000
+
3427 } else if (leadSurrogate) {
+
3428 // Valid bmp char, but last char was a lead
+
3429 if ((units -= 3) > -1) {
+
3430 buffer[index++] = 0xEF
+
3431 buffer[index++] = 0xBF
+
3432 buffer[index++] = 0xBD
+
3433 }
+
3434 }
+
3435
+
3436 leadSurrogate = null
+
3437
+
3438 // Encode utf8
+
3439 if (codePoint < 0x80) {
+
3440 if ((units -= 1) < 0) {
+
3441 break
+
3442 }
+
3443 buffer[index++] = codePoint
+
3444 } else if (codePoint < 0x800) {
+
3445 if ((units -= 2) < 0) {
+
3446 break
+
3447 }
+
3448 buffer[index++] = codePoint >> 0x6 | 0xC0
+
3449 buffer[index++] = codePoint & 0x3F | 0x80
+
3450 } else if (codePoint < 0x10000) {
+
3451 if ((units -= 3) < 0) {
+
3452 break
+
3453 }
+
3454 buffer[index++] = codePoint >> 0xC | 0xE0
+
3455 buffer[index++] = codePoint >> 0x6 & 0x3F | 0x80
+
3456 buffer[index++] = codePoint & 0x3F | 0x80
+
3457 } else if (codePoint < 0x110000) {
+
3458 if ((units -= 4) < 0) {
+
3459 break
+
3460 }
+
3461 buffer[index++] = codePoint >> 0x12 | 0xF0
+
3462 buffer[index++] = codePoint >> 0xC & 0x3F | 0x80
+
3463 buffer[index++] = codePoint >> 0x6 & 0x3F | 0x80
+
3464 buffer[index++] = codePoint & 0x3F | 0x80
+
3465 } else {
+
3466 throw new Error('Invalid code point!')
+
3467 }
+
3468 }
+
3469}
+
3470
+
3471exports.utf8encode = utf8encode
+
3472
+
3480let utf8decode = function (buffer, offset, size) {
+
3481 let start = offset
+
3482 let end = offset + size
+
3483 let res = []
+
3484
+
3485 let i = start
+
3486 while (i < end) {
+
3487 let firstByte = buffer[i]
+
3488 let codePoint = null
+
3489 let bytesPerSequence = (firstByte > 0xEF) ? 4 : ((firstByte > 0xDF) ? 3 : ((firstByte > 0xBF) ? 2 : 1))
+
3490
+
3491 if ((i + bytesPerSequence) <= end) {
+
3492 let secondByte
+
3493 let thirdByte
+
3494 let fourthByte
+
3495 let tempCodePoint
+
3496
+
3497 switch (bytesPerSequence) {
+
3498 case 1:
+
3499 if (firstByte < 0x80) {
+
3500 codePoint = firstByte
+
3501 }
+
3502 break
+
3503 case 2:
+
3504 secondByte = buffer[i + 1]
+
3505 if ((secondByte & 0xC0) === 0x80) {
+
3506 tempCodePoint = ((firstByte & 0x1F) << 0x6) | (secondByte & 0x3F)
+
3507 if (tempCodePoint > 0x7F) {
+
3508 codePoint = tempCodePoint
+
3509 }
+
3510 }
+
3511 break
+
3512 case 3:
+
3513 secondByte = buffer[i + 1]
+
3514 thirdByte = buffer[i + 2]
+
3515 if (((secondByte & 0xC0) === 0x80) && ((thirdByte & 0xC0) === 0x80)) {
+
3516 tempCodePoint = ((firstByte & 0xF) << 0xC) | ((secondByte & 0x3F) << 0x6) | (thirdByte & 0x3F)
+
3517 if ((tempCodePoint > 0x7FF) && ((tempCodePoint < 0xD800) || (tempCodePoint > 0xDFFF))) {
+
3518 codePoint = tempCodePoint
+
3519 }
+
3520 }
+
3521 break
+
3522 case 4:
+
3523 secondByte = buffer[i + 1]
+
3524 thirdByte = buffer[i + 2]
+
3525 fourthByte = buffer[i + 3]
+
3526 if (((secondByte & 0xC0) === 0x80) && ((thirdByte & 0xC0) === 0x80) && ((fourthByte & 0xC0) === 0x80)) {
+
3527 tempCodePoint = ((firstByte & 0xF) << 0x12) | ((secondByte & 0x3F) << 0xC) | ((thirdByte & 0x3F) << 0x6) | (fourthByte & 0x3F)
+
3528 if ((tempCodePoint > 0xFFFF) && (tempCodePoint < 0x110000)) {
+
3529 codePoint = tempCodePoint
+
3530 }
+
3531 }
+
3532 }
+
3533 }
+
3534
+
3535 if (codePoint === null) {
+
3536 // We did not generate a valid codePoint so insert a replacement char (U+FFFD) and advance only 1 byte
+
3537 codePoint = 0xFFFD
+
3538 bytesPerSequence = 1
+
3539 } else if (codePoint > 0xFFFF) {
+
3540 // Encode to utf16 (surrogate pair dance)
+
3541 codePoint -= 0x10000
+
3542 res.push((codePoint >>> 10) & 0x3FF | 0xD800)
+
3543 codePoint = 0xDC00 | codePoint & 0x3FF
+
3544 }
+
3545
+
3546 res.push(codePoint)
+
3547 i += bytesPerSequence
+
3548 }
+
3549
+
3550 // Based on http://stackoverflow.com/a/22747272/680742, the browser with the lowest limit is Chrome, with 0x10000 args.
+
3551 // We go 1 magnitude less, for safety
+
3552 const MAX_ARGUMENTS_LENGTH = 0x1000
+
3553
+
3554 if (res.length <= MAX_ARGUMENTS_LENGTH) {
+
3555 // Avoid extra slice()
+
3556 return String.fromCharCode.apply(String, res)
+
3557 }
+
3558
+
3559 let result = ''
+
3560
+
3561 // Decode in chunks to avoid "call stack size exceeded"
+
3562 i = 0
+
3563 while (i < res.length) {
+
3564 result += String.fromCharCode.apply(String, res.slice(i, i += MAX_ARGUMENTS_LENGTH))
+
3565 }
+
3566
+
3567 return result
+
3568}
+
3569
+
3570exports.utf8decode = utf8decode
+
3571)CODE";
+
3572
+
3573 // Prepare code template
+
3574 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
3575
+
3576 Write(code);
+
3577
+
3578 // Generate common footer
+
3579 GenerateFooter();
+
3580
+
3581 // Close the common file
+
3582 WriteEnd();
+
3583 Store(common);
+
3584}
+
3585
+
3586void GeneratorJavaScript::GenerateFBE(const CppCommon::Path& path)
+
3587{
+
3588 // Generate the common file
+
3589 CppCommon::Path common = path / "fbe.js";
+
3590 WriteBegin();
+
3591
+
3592 // Generate common header
+
3593 GenerateHeader("FBE");
+
3594
+
3595 std::string code = R"CODE(
+
3596/* eslint-disable prefer-const,no-loss-of-precision */
+
3597'use strict'
+
3598
+
3599const big = require('./big')
+
3600const int64 = require('./int64')
+
3601const ieee754 = require('./ieee754')
+
3602const utf8 = require('./utf8')
+
3603const uuid = require('./uuid')
+
3604
+
3605const Big = big.Big
+
3606const Int64 = int64.Int64
+
3607const UInt64 = int64.UInt64
+
3608const UUID = uuid.UUID
+
3609const ieee754read = ieee754.ieee754read
+
3610const ieee754write = ieee754.ieee754write
+
3611const utf8count = utf8.utf8count
+
3612const utf8encode = utf8.utf8encode
+
3613const utf8decode = utf8.utf8decode
+
3614)CODE";
+
3615
+
3616 // Prepare code template
+
3617 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
3618
+
3619 Write(code);
+
3620
+
3621 // Generate common models
+
3622 GenerateFBEDeferredPromise();
+
3623 GenerateFBEBaseBuffer();
+
3624 GenerateFBEWriteBuffer();
+
3625 GenerateFBEReadBuffer();
+
3626 GenerateFBEModel();
+
3627 GenerateFBEFieldModelBase();
+
3628 GenerateFBEFieldModel();
+
3629 GenerateFBEFieldModel("Bool", "bool", "boolean", "1", "false");
+
3630 GenerateFBEFieldModel("Byte", "byte", "number", "1", "0");
+
3631 GenerateFBEFieldModel("Char", "char", "string", "1", "'\\0'");
+
3632 GenerateFBEFieldModel("WChar", "wchar", "string", "4", "'\\0'");
+
3633 GenerateFBEFieldModel("Int8", "int8", "number", "1", "0");
+
3634 GenerateFBEFieldModel("UInt8", "uint8", "number", "1", "0");
+
3635 GenerateFBEFieldModel("Int16", "int16", "number", "2", "0");
+
3636 GenerateFBEFieldModel("UInt16", "uint16", "number", "2", "0");
+
3637 GenerateFBEFieldModel("Int32", "int32", "number", "4", "0");
+
3638 GenerateFBEFieldModel("UInt32", "uint32", "number", "4", "0");
+
3639 GenerateFBEFieldModel("Int64", "int64", "Int64", "8", "new Int64(0, 0)");
+
3640 GenerateFBEFieldModel("UInt64", "uint64", "UInt64", "8", "new UInt64(0, 0)");
+
3641 GenerateFBEFieldModel("Float", "float", "number", "4", "0.0");
+
3642 GenerateFBEFieldModel("Double", "double", "number", "8", "0.0");
+
3643 GenerateFBEFieldModelDecimal();
+
3644 GenerateFBEFieldModelTimestamp();
+
3645 GenerateFBEFieldModelUUID();
+
3646 GenerateFBEFieldModelBytes();
+
3647 GenerateFBEFieldModelString();
+
3648 GenerateFBEFieldModelOptional();
+
3649 GenerateFBEFieldModelArray();
+
3650 GenerateFBEFieldModelVector();
+
3651 GenerateFBEFieldModelSet();
+
3652 GenerateFBEFieldModelMap();
+
3653 if (Final())
+
3654 {
+
3655 GenerateFBEFinalModel();
+
3656 GenerateFBEFinalModel("Bool", "bool", "boolean", "1", "false");
+
3657 GenerateFBEFinalModel("Byte", "byte", "number", "1", "0");
+
3658 GenerateFBEFinalModel("Char", "char", "string", "1", "'\\0'");
+
3659 GenerateFBEFinalModel("WChar", "wchar", "string", "4", "'\\0'");
+
3660 GenerateFBEFinalModel("Int8", "int8", "number", "1", "0");
+
3661 GenerateFBEFinalModel("UInt8", "uint8", "number", "1", "0");
+
3662 GenerateFBEFinalModel("Int16", "int16", "number", "2", "0");
+
3663 GenerateFBEFinalModel("UInt16", "uint16", "number", "2", "0");
+
3664 GenerateFBEFinalModel("Int32", "int32", "number", "4", "0");
+
3665 GenerateFBEFinalModel("UInt32", "uint32", "number", "4", "0");
+
3666 GenerateFBEFinalModel("Int64", "int64", "Int64", "8", "new Int64(0, 0)");
+
3667 GenerateFBEFinalModel("UInt64", "uint64", "UInt64", "8", "new UInt64(0, 0)");
+
3668 GenerateFBEFinalModel("Float", "float", "number", "4", "0.0");
+
3669 GenerateFBEFinalModel("Double", "double", "number", "8", "0.0");
+
3670 GenerateFBEFinalModelDecimal();
+
3671 GenerateFBEFinalModelTimestamp();
+
3672 GenerateFBEFinalModelUUID();
+
3673 GenerateFBEFinalModelBytes();
+
3674 GenerateFBEFinalModelString();
+
3675 GenerateFBEFinalModelOptional();
+
3676 GenerateFBEFinalModelArray();
+
3677 GenerateFBEFinalModelVector();
+
3678 GenerateFBEFinalModelSet();
+
3679 GenerateFBEFinalModelMap();
+
3680 }
+
3681 if (Proto())
+
3682 {
+
3683 GenerateFBESender();
+
3684 GenerateFBEReceiver();
+
3685 GenerateFBEClient();
+
3686 }
+
3687 if (JSON())
+
3688 GenerateFBEJson();
+
3689
+
3690 // Generate common footer
+
3691 GenerateFooter();
+
3692
+
3693 // Close the common file
+
3694 WriteEnd();
+
3695 Store(common);
+
3696}
+
3697
+
3698void GeneratorJavaScript::GenerateFBEDeferredPromise()
+
3699{
+
3700 std::string code = R"CODE(
+
3704class DeferredPromise {
+
3709 constructor () {
+
3710 this._promise = new Promise((resolve, reject) => {
+
3711 // Assign the resolve and reject functions to `this` making them usable on the class instance
+
3712 this.resolve = resolve
+
3713 this.reject = reject
+
3714 })
+
3715 // Bind `then` and `catch` to implement the same interface as Promise
+
3716 this.then = this._promise.then.bind(this._promise)
+
3717 this.catch = this._promise.catch.bind(this._promise)
+
3718 this[Symbol.toStringTag] = 'Promise'
+
3719 }
+
3720}
+
3721
+
3722exports.DeferredPromise = DeferredPromise
+
3723)CODE";
+
3724
+
3725 // Prepare code template
+
3726 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
3727
+
3728 Write(code);
+
3729}
+
3730
+
3731void GeneratorJavaScript::GenerateFBEBaseBuffer()
+
3732{
+
3733 std::string code = R"CODE(
+
3737class BaseBuffer {
+
3742 constructor () {
+
3743 this._buffer = null
+
3744 this._size = 0
+
3745 this._offset = 0
+
3746 }
+
3747
+
3753 get isEmpty () {
+
3754 return (this._buffer == null) || (this._size === 0)
+
3755 }
+
3756
+
3762 get buffer () {
+
3763 return this._buffer
+
3764 }
+
3765
+
3771 get capacity () {
+
3772 return this._buffer.length
+
3773 }
+
3774
+
3780 get length () {
+
3781 return this._size
+
3782 }
+
3783
+
3789 get size () {
+
3790 return this._size
+
3791 }
+
3792
+
3798 get offset () {
+
3799 return this._offset
+
3800 }
+
3801
+
3807 shift (offset) {
+
3808 this._offset += offset
+
3809 }
+
3810
+
3816 unshift (offset) {
+
3817 this._offset -= offset
+
3818 }
+
3819
+
3826 checkOffset (offset, size) {
+
3827 if (((offset % 1) !== 0) || (offset < 0)) {
+
3828 throw new RangeError('Invalid offset!')
+
3829 }
+
3830 if ((offset + size) > this.length) {
+
3831 throw new RangeError('Out of bounds!')
+
3832 }
+
3833 }
+
3834
+
3844 checkValue (offset, size, value, min, max) {
+
3845 this.checkOffset(offset, size)
+
3846 if ((value < min) || (value > max)) {
+
3847 throw new RangeError('Value is out of bounds!')
+
3848 }
+
3849 }
+
3850}
+
3851
+
3852exports.BaseBuffer = BaseBuffer
+
3853)CODE";
+
3854
+
3855 // Prepare code template
+
3856 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
3857
+
3858 Write(code);
+
3859}
+
3860
+
3861void GeneratorJavaScript::GenerateFBEWriteBuffer()
+
3862{
+
3863 std::string code = R"CODE(
+
3867class WriteBuffer extends BaseBuffer {
+
3873 constructor (capacity = 0) {
+
3874 super()
+
3875 this._buffer = new Uint8Array(capacity)
+
3876 this._size = 0
+
3877 this._offset = 0
+
3878 }
+
3879
+
3884 attachNew () {
+
3885 this._buffer = new Uint8Array(0)
+
3886 this._size = 0
+
3887 this._offset = 0
+
3888 }
+
3889
+
3895 attachCapacity (capacity = 0) {
+
3896 this._buffer = new Uint8Array(capacity)
+
3897 this._size = 0
+
3898 this._offset = 0
+
3899 }
+
3900
+
3908 attachBuffer (buffer, offset = 0, size = undefined) {
+
3909 if (size == null) {
+
3910 size = buffer.length
+
3911 }
+
3912
+
3913 if (size <= 0) {
+
3914 throw new Error('Invalid size!')
+
3915 }
+
3916 if (offset > size) {
+
3917 throw new Error('Invalid offset!')
+
3918 }
+
3919 if ((buffer instanceof ReadBuffer) || (buffer instanceof WriteBuffer)) {
+
3920 this._buffer = buffer.buffer
+
3921 } else {
+
3922 this._buffer = buffer
+
3923 }
+
3924 this._size = size
+
3925 this._offset = offset
+
3926 }
+
3927
+
3934 allocate (size) {
+
3935 if (size < 0) {
+
3936 throw new Error('Invalid allocation size!')
+
3937 }
+
3938
+
3939 let offset = this._size
+
3940
+
3941 // Calculate a new buffer size
+
3942 let total = this._size + size
+
3943
+
3944 if (total <= this._buffer.length) {
+
3945 this._size = total
+
3946 return offset
+
3947 }
+
3948
+
3949 let data = new Uint8Array(Math.max(total, 2 * this._buffer.length))
+
3950 data.set(this._buffer)
+
3951 this._buffer = data
+
3952 this._size = total
+
3953 return offset
+
3954 }
+
3955
+
3962 remove (offset, size) {
+
3963 if ((offset + size) > this._buffer.length) {
+
3964 throw new Error('Invalid offset & size!')
+
3965 }
+
3966
+
3967 for (let i = 0; i < size; i++) {
+
3968 this._buffer[offset + i] = this._buffer[offset + size + i]
+
3969 }
+
3970 this._size -= size
+
3971 if (this._offset >= (offset + size)) {
+
3972 this._offset -= size
+
3973 } else if (this._offset >= offset) {
+
3974 this._offset -= this._offset - offset
+
3975 if (this._offset > this._size) {
+
3976 this._offset = this._size
+
3977 }
+
3978 }
+
3979 }
+
3980
+
3986 reserve (capacity) {
+
3987 if (capacity < 0) {
+
3988 throw new Error('Invalid reserve capacity!')
+
3989 }
+
3990
+
3991 if (capacity > this._buffer.length) {
+
3992 let data = new Uint8Array(Math.max(capacity, 2 * this._buffer.length))
+
3993 data.set(this._buffer)
+
3994 this._buffer = data
+
3995 }
+
3996 }
+
3997
+
4003 resize (size) {
+
4004 this.reserve(size)
+
4005 this._size = size
+
4006 if (this._offset > this._size) {
+
4007 this._offset = this._size
+
4008 }
+
4009 }
+
4010
+
4015 reset () {
+
4016 this._size = 0
+
4017 this._offset = 0
+
4018 }
+
4019}
+
4020
+
4021exports.WriteBuffer = WriteBuffer
+
4022)CODE";
+
4023
+
4024 // Prepare code template
+
4025 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
4026
+
4027 Write(code);
+
4028}
+
4029
+
4030void GeneratorJavaScript::GenerateFBEReadBuffer()
+
4031{
+
4032 std::string code = R"CODE(
+
4036class ReadBuffer extends BaseBuffer {
+
4044 attachBuffer (buffer, offset = 0, size = undefined) {
+
4045 if (size == null) {
+
4046 size = buffer.length
+
4047 }
+
4048
+
4049 if (size <= 0) {
+
4050 throw new Error('Invalid size!')
+
4051 }
+
4052 if (offset > size) {
+
4053 throw new Error('Invalid offset!')
+
4054 }
+
4055 if ((buffer instanceof ReadBuffer) || (buffer instanceof WriteBuffer)) {
+
4056 this._buffer = buffer.buffer
+
4057 } else {
+
4058 this._buffer = buffer
+
4059 }
+
4060 this._size = size
+
4061 this._offset = offset
+
4062 }
+
4063
+
4068 reset () {
+
4069 this._buffer = null
+
4070 this._size = 0
+
4071 this._offset = 0
+
4072 }
+
4073}
+
4074
+
4075exports.ReadBuffer = ReadBuffer
+
4076)CODE";
+
4077
+
4078 // Prepare code template
+
4079 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
4080
+
4081 Write(code);
+
4082}
+
4083
+
4084void GeneratorJavaScript::GenerateFBEModel()
+
4085{
+
4086 std::string code = R"CODE(
+
4090class Model {
+
4096 constructor (buffer = new WriteBuffer()) {
+
4097 this._buffer = buffer
+
4098 }
+
4099
+
4105 get buffer () {
+
4106 return this._buffer
+
4107 }
+
4108
+
4113 attachNew () {
+
4114 this._buffer.attachNew()
+
4115 }
+
4116
+
4122 attachCapacity (capacity = 0) {
+
4123 this._buffer.attachCapacity(capacity)
+
4124 }
+
4125
+
4133 attachBuffer (buffer, offset = 0, size = undefined) {
+
4134 this._buffer.attachBuffer(buffer, offset, size)
+
4135 }
+
4136
+
4143 allocate (size) {
+
4144 return this._buffer.allocate(size)
+
4145 }
+
4146
+
4153 remove (offset, size) {
+
4154 this._buffer.remove(offset, size)
+
4155 }
+
4156
+
4162 reserve (capacity) {
+
4163 this._buffer.reserve(capacity)
+
4164 }
+
4165
+
4171 resize (size) {
+
4172 this._buffer.resize(size)
+
4173 }
+
4174
+
4179 reset () {
+
4180 this._buffer.reset()
+
4181 }
+
4182
+
4188 shift (offset) {
+
4189 this._buffer.shift(offset)
+
4190 }
+
4191
+
4197 unshift (offset) {
+
4198 this._buffer.unshift(offset)
+
4199 }
+
4200
+
4201 // Buffer I/O methods
+
4202
+
4209 readUInt32 (offset) {
+
4210 offset = offset >>> 0
+
4211 offset += this._buffer.offset
+
4212 this._buffer.checkOffset(offset, 4)
+
4213 return (
+
4214 (this._buffer.buffer[offset + 0] << 0) |
+
4215 (this._buffer.buffer[offset + 1] << 8) |
+
4216 (this._buffer.buffer[offset + 2] << 16)) +
+
4217 (this._buffer.buffer[offset + 3] * 0x1000000)
+
4218 }
+
4219
+
4226 writeUInt32 (offset, value) {
+
4227 value = +value
+
4228 offset = offset >>> 0
+
4229 offset += this._buffer.offset
+
4230 this._buffer.checkValue(offset, 4, value, 0, 0xFFFFFFFF)
+
4231 this._buffer.buffer[offset + 3] = (value >>> 24)
+
4232 this._buffer.buffer[offset + 2] = (value >>> 16)
+
4233 this._buffer.buffer[offset + 1] = (value >>> 8)
+
4234 this._buffer.buffer[offset + 0] = (value & 0xFF)
+
4235 }
+
4236}
+
4237
+
4238exports.Model = Model
+
4239)CODE";
+
4240
+
4241 // Prepare code template
+
4242 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
4243
+
4244 Write(code);
+
4245}
+
4246
+
4247void GeneratorJavaScript::GenerateFBEFieldModelBase()
+
4248{
+
4249 std::string code = R"CODE(
+
4253class FieldModelBase {
+
4260 constructor (buffer, offset) {
+
4261 this._buffer = buffer
+
4262 this._offset = offset
+
4263 }
+
4264
+
4270 get fbeOffset () {
+
4271 return this._offset
+
4272 }
+
4273
+
4279 set fbeOffset (offset) {
+
4280 this._offset = offset
+
4281 }
+
4282
+
4288 get fbeSize () {
+
4289 return 0
+
4290 }
+
4291
+
4297 get fbeExtra () {
+
4298 return 0
+
4299 }
+
4300
+
4306 fbeShift (offset) {
+
4307 this._offset += offset
+
4308 }
+
4309
+
4315 fbeUnshift (offset) {
+
4316 this._offset -= offset
+
4317 }
+
4318
+
4319 // Buffer I/O methods
+
4320
+
4327 readBool (offset) {
+
4328 offset = offset >>> 0
+
4329 offset += this._buffer.offset
+
4330 this._buffer.checkOffset(offset, 1)
+
4331 return this._buffer.buffer[offset] !== 0
+
4332 }
+
4333
+
4340 readByte (offset) {
+
4341 offset = offset >>> 0
+
4342 offset += this._buffer.offset
+
4343 this._buffer.checkOffset(offset, 1)
+
4344 return this._buffer.buffer[offset]
+
4345 }
+
4346
+
4353 readChar (offset) {
+
4354 let code = this.readUInt8(offset)
+
4355 return String.fromCharCode(code)
+
4356 }
+
4357
+
4364 readWChar (offset) {
+
4365 let code = this.readUInt32(offset)
+
4366 return String.fromCharCode(code)
+
4367 }
+
4368
+
4375 readInt8 (offset) {
+
4376 offset = offset >>> 0
+
4377 offset += this._buffer.offset
+
4378 this._buffer.checkOffset(offset, 1)
+
4379 if ((this._buffer.buffer[offset] & 0x80) === 0) {
+
4380 return (this._buffer.buffer[offset])
+
4381 }
+
4382 return ((0xFF - this._buffer.buffer[offset] + 1) * -1)
+
4383 }
+
4384
+
4391 readUInt8 (offset) {
+
4392 offset = offset >>> 0
+
4393 offset += this._buffer.offset
+
4394 this._buffer.checkOffset(offset, 1)
+
4395 return this._buffer.buffer[offset]
+
4396 }
+
4397
+
4404 readInt16 (offset) {
+
4405 offset = offset >>> 0
+
4406 offset += this._buffer.offset
+
4407 this._buffer.checkOffset(offset, 2)
+
4408 let val = this._buffer.buffer[offset] | (this._buffer.buffer[offset + 1] << 8)
+
4409 return (val & 0x8000) ? val | 0xFFFF0000 : val
+
4410 }
+
4411
+
4418 readUInt16 (offset) {
+
4419 offset = offset >>> 0
+
4420 offset += this._buffer.offset
+
4421 this._buffer.checkOffset(offset, 2)
+
4422 return this._buffer.buffer[offset] | (this._buffer.buffer[offset + 1] << 8)
+
4423 }
+
4424
+
4431 readInt32 (offset) {
+
4432 offset = offset >>> 0
+
4433 offset += this._buffer.offset
+
4434 this._buffer.checkOffset(offset, 4)
+
4435 return (
+
4436 (this._buffer.buffer[offset + 0] << 0) |
+
4437 (this._buffer.buffer[offset + 1] << 8) |
+
4438 (this._buffer.buffer[offset + 2] << 16) |
+
4439 (this._buffer.buffer[offset + 3] << 24))
+
4440 }
+
4441
+
4448 readUInt32 (offset) {
+
4449 offset = offset >>> 0
+
4450 offset += this._buffer.offset
+
4451 this._buffer.checkOffset(offset, 4)
+
4452 return (
+
4453 (this._buffer.buffer[offset + 0] << 0) |
+
4454 (this._buffer.buffer[offset + 1] << 8) |
+
4455 (this._buffer.buffer[offset + 2] << 16)) +
+
4456 (this._buffer.buffer[offset + 3] * 0x1000000)
+
4457 }
+
4458
+
4465 readInt64 (offset) {
+
4466 offset = offset >>> 0
+
4467 offset += this._buffer.offset
+
4468 this._buffer.checkOffset(offset, 8)
+
4469 let low = (
+
4470 (this._buffer.buffer[offset + 0] << 0) |
+
4471 (this._buffer.buffer[offset + 1] << 8) |
+
4472 (this._buffer.buffer[offset + 2] << 16) |
+
4473 (this._buffer.buffer[offset + 3] << 24))
+
4474 let high = (
+
4475 (this._buffer.buffer[offset + 4] << 0) |
+
4476 (this._buffer.buffer[offset + 5] << 8) |
+
4477 (this._buffer.buffer[offset + 6] << 16) |
+
4478 (this._buffer.buffer[offset + 7] << 24))
+
4479 return new Int64(low, high)
+
4480 }
+
4481
+
4488 readUInt64 (offset) {
+
4489 offset = offset >>> 0
+
4490 offset += this._buffer.offset
+
4491 this._buffer.checkOffset(offset, 8)
+
4492 let low = (
+
4493 (this._buffer.buffer[offset + 0] << 0) |
+
4494 (this._buffer.buffer[offset + 1] << 8) |
+
4495 (this._buffer.buffer[offset + 2] << 16) |
+
4496 (this._buffer.buffer[offset + 3] << 24))
+
4497 let high = (
+
4498 (this._buffer.buffer[offset + 4] << 0) |
+
4499 (this._buffer.buffer[offset + 5] << 8) |
+
4500 (this._buffer.buffer[offset + 6] << 16) +
+
4501 (this._buffer.buffer[offset + 7] << 24))
+
4502 return new UInt64(low, high)
+
4503 }
+
4504
+
4511 readFloat (offset) {
+
4512 offset = offset >>> 0
+
4513 offset += this._buffer.offset
+
4514 this._buffer.checkOffset(offset, 4)
+
4515 return ieee754read(this._buffer.buffer, offset, true, 23, 4)
+
4516 }
+
4517
+
4524 readDouble (offset) {
+
4525 offset = offset >>> 0
+
4526 offset += this._buffer.offset
+
4527 this._buffer.checkOffset(offset, 4)
+
4528 return ieee754read(this._buffer.buffer, offset, true, 52, 8)
+
4529 }
+
4530
+
4538 readBytes (offset, size) {
+
4539 offset = offset >>> 0
+
4540 offset += this._buffer.offset
+
4541 this._buffer.checkOffset(offset, size)
+
4542 return this._buffer.buffer.slice(offset, offset + size)
+
4543 }
+
4544
+
4552 readString (offset, size) {
+
4553 offset = offset >>> 0
+
4554 offset += this._buffer.offset
+
4555 this._buffer.checkOffset(offset, size)
+
4556 return utf8decode(this._buffer.buffer, offset, size)
+
4557 }
+
4558
+
4565 writeBool (offset, value) {
+
4566 let byte = value ? 1 : 0
+
4567 offset = offset >>> 0
+
4568 offset += this._buffer.offset
+
4569 this._buffer.checkValue(offset, 1, byte, 0, 0xFF)
+
4570 this._buffer.buffer[offset] = (byte & 0xFF)
+
4571 }
+
4572
+
4579 writeByte (offset, value) {
+
4580 offset = offset >>> 0
+
4581 offset += this._buffer.offset
+
4582 this._buffer.checkValue(offset, 1, value, 0, 0xFF)
+
4583 this._buffer.buffer[offset] = (value & 0xFF)
+
4584 }
+
4585
+
4592 writeChar (offset, value) {
+
4593 let code = value.charCodeAt(0)
+
4594 this.writeUInt8(offset, code)
+
4595 }
+
4596
+
4603 writeWChar (offset, value) {
+
4604 let code = value.charCodeAt(0)
+
4605 this.writeUInt32(offset, code)
+
4606 }
+
4607
+
4614 writeInt8 (offset, value) {
+
4615 value = +value
+
4616 offset = offset >>> 0
+
4617 offset += this._buffer.offset
+
4618 this._buffer.checkValue(offset, 1, value, -0x80, 0x7F)
+
4619 if (value < 0) {
+
4620 value = 0xFF + value + 1
+
4621 }
+
4622 this._buffer.buffer[offset] = (value & 0xFF)
+
4623 }
+
4624
+
4631 writeUInt8 (offset, value) {
+
4632 value = +value
+
4633 offset = offset >>> 0
+
4634 offset += this._buffer.offset
+
4635 this._buffer.checkValue(offset, 1, value, 0, 0xFF)
+
4636 this._buffer.buffer[offset] = (value & 0xFF)
+
4637 }
+
4638
+
4645 writeInt16 (offset, value) {
+
4646 value = +value
+
4647 offset = offset >>> 0
+
4648 offset += this._buffer.offset
+
4649 this._buffer.checkValue(offset, 2, value, -0x8000, 0x7FFF)
+
4650 this._buffer.buffer[offset + 0] = (value & 0xFF)
+
4651 this._buffer.buffer[offset + 1] = (value >>> 8)
+
4652 }
+
4653
+
4660 writeUInt16 (offset, value) {
+
4661 value = +value
+
4662 offset = offset >>> 0
+
4663 offset += this._buffer.offset
+
4664 this._buffer.checkValue(offset, 2, value, 0, 0xFFFF)
+
4665 this._buffer.buffer[offset + 0] = (value & 0xFF)
+
4666 this._buffer.buffer[offset + 1] = (value >>> 8)
+
4667 }
+
4668
+
4675 writeInt32 (offset, value) {
+
4676 value = +value
+
4677 offset = offset >>> 0
+
4678 offset += this._buffer.offset
+
4679 this._buffer.checkValue(offset, 4, value, -0x80000000, 0x7FFFFFFF)
+
4680 this._buffer.buffer[offset + 0] = (value & 0xFF)
+
4681 this._buffer.buffer[offset + 1] = (value >>> 8)
+
4682 this._buffer.buffer[offset + 2] = (value >>> 16)
+
4683 this._buffer.buffer[offset + 3] = (value >>> 24)
+
4684 }
+
4685
+
4692 writeUInt32 (offset, value) {
+
4693 value = +value
+
4694 offset = offset >>> 0
+
4695 offset += this._buffer.offset
+
4696 this._buffer.checkValue(offset, 4, value, 0, 0xFFFFFFFF)
+
4697 this._buffer.buffer[offset + 0] = (value & 0xFF)
+
4698 this._buffer.buffer[offset + 1] = (value >>> 8)
+
4699 this._buffer.buffer[offset + 2] = (value >>> 16)
+
4700 this._buffer.buffer[offset + 3] = (value >>> 24)
+
4701 }
+
4702
+
4709 writeInt64 (offset, value) {
+
4710 value = Int64.fromValue(value)
+
4711 offset = offset >>> 0
+
4712 offset += this._buffer.offset
+
4713 this._buffer.checkOffset(offset, 8)
+
4714 this._buffer.buffer[offset + 0] = (value.low & 0xFF)
+
4715 this._buffer.buffer[offset + 1] = (value.low >>> 8)
+
4716 this._buffer.buffer[offset + 2] = (value.low >>> 16)
+
4717 this._buffer.buffer[offset + 3] = (value.low >>> 24)
+
4718 this._buffer.buffer[offset + 4] = (value.high & 0xFF)
+
4719 this._buffer.buffer[offset + 5] = (value.high >>> 8)
+
4720 this._buffer.buffer[offset + 6] = (value.high >>> 16)
+
4721 this._buffer.buffer[offset + 7] = (value.high >>> 24)
+
4722 }
+
4723
+
4730 writeUInt64 (offset, value) {
+
4731 value = UInt64.fromValue(value)
+
4732 offset = offset >>> 0
+
4733 offset += this._buffer.offset
+
4734 this._buffer.checkOffset(offset, 8)
+
4735 this._buffer.buffer[offset + 0] = (value.low & 0xFF)
+
4736 this._buffer.buffer[offset + 1] = (value.low >>> 8)
+
4737 this._buffer.buffer[offset + 2] = (value.low >>> 16)
+
4738 this._buffer.buffer[offset + 3] = (value.low >>> 24)
+
4739 this._buffer.buffer[offset + 4] = (value.high & 0xFF)
+
4740 this._buffer.buffer[offset + 5] = (value.high >>> 8)
+
4741 this._buffer.buffer[offset + 6] = (value.high >>> 16)
+
4742 this._buffer.buffer[offset + 7] = (value.high >>> 24)
+
4743 }
+
4744
+
4751 writeFloat (offset, value) {
+
4752 value = +value
+
4753 offset = offset >>> 0
+
4754 offset += this._buffer.offset
+
4755 this._buffer.checkValue(offset, 4, value, -3.4028234663852886e+38, 3.4028234663852886e+38)
+
4756 ieee754write(this._buffer.buffer, offset, value, true, 23, 4)
+
4757 }
+
4758
+
4765 writeDouble (offset, value) {
+
4766 value = +value
+
4767 offset = offset >>> 0
+
4768 offset += this._buffer.offset
+
4769 this._buffer.checkValue(offset, 8, value, -1.7976931348623157E+308, 1.7976931348623157E+308)
+
4770 ieee754write(this._buffer.buffer, offset, value, true, 52, 8)
+
4771 }
+
4772
+
4781 writeBytes (offset, value, valueOffset = 0, valueSize = undefined) {
+
4782 if (valueSize == null) {
+
4783 valueSize = value.length
+
4784 }
+
4785
+
4786 offset = offset >>> 0
+
4787 offset += this._buffer.offset
+
4788 this._buffer.checkOffset(offset, valueSize)
+
4789 for (let i = 0; i < valueSize; i++) {
+
4790 this._buffer.buffer[offset + i] = value[valueOffset + i]
+
4791 }
+
4792 }
+
4793
+
4801 writeCount (offset, value, valueCount) {
+
4802 offset = offset >>> 0
+
4803 offset += this._buffer.offset
+
4804 this._buffer.checkOffset(offset, valueCount)
+
4805 for (let i = 0; i < valueCount; i++) {
+
4806 this._buffer.buffer[offset + i] = (value & 0xFF)
+
4807 }
+
4808 }
+
4809
+
4817 writeString (offset, value, size) {
+
4818 offset = offset >>> 0
+
4819 offset += this._buffer.offset
+
4820 this._buffer.checkOffset(offset, size)
+
4821 utf8encode(this._buffer.buffer, offset, value)
+
4822 }
+
4823}
+
4824
+
4825exports.FieldModelBase = FieldModelBase
+
4826)CODE";
+
4827
+
4828 // Prepare code template
+
4829 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
4830
+
4831 Write(code);
+
4832}
+
4833
+
4834void GeneratorJavaScript::GenerateFBEFieldModel()
+
4835{
+
4836 std::string code = R"CODE(
+
4840class FieldModel extends FieldModelBase {
+
4846 verify () {
+
4847 return true
+
4848 }
+
4849}
+
4850
+
4851exports.FieldModel = FieldModel
+
4852)CODE";
+
4853
+
4854 // Prepare code template
+
4855 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
4856
+
4857 Write(code);
+
4858}
+
4859
+
4860void GeneratorJavaScript::GenerateFBEFieldModel(const std::string& name, const std::string& type, const std::string& base, const std::string& size, const std::string& defaults)
+
4861{
+
4862 std::string code = R"CODE(
+
4866class FieldModel_NAME_ extends FieldModel {
+
4872 get fbeSize () {
+
4873 return _SIZE_
+
4874 }
+
4875
+
4882 get (defaults = _DEFAULTS_) {
+
4883 if ((this._buffer.offset + this.fbeOffset + this.fbeSize) > this._buffer.size) {
+
4884 return defaults
+
4885 }
+
4886
+
4887 return this.read_NAME_(this.fbeOffset)
+
4888 }
+
4889
+
4895 set (value) {
+
4896 console.assert(((this._buffer.offset + this.fbeOffset + this.fbeSize) <= this._buffer.size), 'Model is broken!')
+
4897 if ((this._buffer.offset + this.fbeOffset + this.fbeSize) > this._buffer.size) {
+
4898 return
+
4899 }
+
4900
+
4901 this.write_NAME_(this.fbeOffset, value)
+
4902 }
+
4903}
+
4904
+
4905exports.FieldModel_NAME_ = FieldModel_NAME_
+
4906)CODE";
+
4907
+
4908 // Prepare code template
+
4909 code = std::regex_replace(code, std::regex("_NAME_"), name);
+
4910 code = std::regex_replace(code, std::regex("_TYPE_"), type);
+
4911 code = std::regex_replace(code, std::regex("_BASE_"), base);
+
4912 code = std::regex_replace(code, std::regex("_SIZE_"), size);
+
4913 code = std::regex_replace(code, std::regex("_DEFAULTS_"), defaults);
+
4914 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
4915
+
4916 Write(code);
+
4917}
+
4918
+
4919void GeneratorJavaScript::GenerateFBEFieldModelDecimal()
+
4920{
+
4921 std::string code = R"CODE(
+
4925class FieldModelDecimal extends FieldModel {
+
4931 get fbeSize () {
+
4932 return 16
+
4933 }
+
4934
+
4941 get (defaults = new Big(0)) {
+
4942 if ((this._buffer.offset + this.fbeOffset + this.fbeSize) > this._buffer.size) {
+
4943 return defaults
+
4944 }
+
4945
+
4946 // Read decimal parts
+
4947 let low = this.readUInt32(this.fbeOffset)
+
4948 let mid = this.readUInt32(this.fbeOffset + 4)
+
4949 let high = this.readUInt32(this.fbeOffset + 8)
+
4950 let flags = this.readUInt32(this.fbeOffset + 12)
+
4951
+
4952 // Calculate decimal value
+
4953 let negative = (flags & 0x80000000) !== 0
+
4954 let scale = (flags & 0x7FFFFFFF) >> 16
+
4955 let result = new Big(0)
+
4956 result = result.add(new Big(high).mul('18446744073709551616'))
+
4957 result = result.add(new Big(mid).mul('4294967296'))
+
4958 result = result.add(new Big(low))
+
4959 result = result.div(Math.pow(10, scale))
+
4960 if (negative) {
+
4961 result.s = -1
+
4962 }
+
4963
+
4964 return result
+
4965 }
+
4966
+
4972 set (value) {
+
4973 console.assert(((this._buffer.offset + this.fbeOffset + this.fbeSize) <= this._buffer.size), 'Model is broken!')
+
4974 if ((this._buffer.offset + this.fbeOffset + this.fbeSize) > this._buffer.size) {
+
4975 return
+
4976 }
+
4977
+
4978 // Extract decimal parts
+
4979 let negative = value.s < 0
+
4980 let scale = Math.max(0, value.c.length - 1 - value.e)
+
4981 let number = value.mul(Math.pow(10, scale)).abs()
+
4982
+
4983 // Check for decimal scale overflow
+
4984 if ((scale < 0) || (scale > 28)) {
+
4985 // Value scale exceeds .NET Decimal limit of [0, 28]
+
4986 this.writeCount(this.fbeOffset, 0, this.fbeSize)
+
4987 return
+
4988 }
+
4989
+
4990 // Write unscaled value to bytes 0-11
+
4991 let index = 0
+
4992 while (number > 0) {
+
4993 // Check for decimal number overflow
+
4994 if (index > 11) {
+
4995 // Value too big for .NET Decimal (bit length is limited to [0, 96])
+
4996 this.writeCount(this.fbeOffset, 0, this.fbeSize)
+
4997 return
+
4998 }
+
4999 let byte = parseInt(number.mod(256))
+
5000 this.writeByte(this.fbeOffset + index, byte)
+
5001 number = number.div(256).round(0, 0)
+
5002 index++
+
5003 }
+
5004
+
5005 // Fill remaining bytes with zeros
+
5006 while (index < 12) {
+
5007 this.writeByte(this.fbeOffset + index, 0)
+
5008 index++
+
5009 }
+
5010
+
5011 // Write scale at byte 14
+
5012 this.writeByte(this.fbeOffset + 14, scale)
+
5013
+
5014 // Write signum at byte 15
+
5015 this.writeByte(this.fbeOffset + 15, (negative ? 0x80 : 0))
+
5016 }
+
5017}
+
5018
+
5019exports.FieldModelDecimal = FieldModelDecimal
+
5020)CODE";
+
5021
+
5022 // Prepare code template
+
5023 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
5024
+
5025 Write(code);
+
5026}
+
5027
+
5028void GeneratorJavaScript::GenerateFBEFieldModelTimestamp()
+
5029{
+
5030 std::string code = R"CODE(
+
5034class FieldModelTimestamp extends FieldModel {
+
5040 get fbeSize () {
+
5041 return 8
+
5042 }
+
5043
+
5050 get (defaults = new Date(0)) {
+
5051 if ((this._buffer.offset + this.fbeOffset + this.fbeSize) > this._buffer.size) {
+
5052 return defaults
+
5053 }
+
5054
+
5055 let nanoseconds = this.readUInt64(this.fbeOffset)
+
5056 return new Date(Math.round(nanoseconds / 1000000))
+
5057 }
+
5058
+
5064 set (value) {
+
5065 console.assert(((this._buffer.offset + this.fbeOffset + this.fbeSize) <= this._buffer.size), 'Model is broken!')
+
5066 if ((this._buffer.offset + this.fbeOffset + this.fbeSize) > this._buffer.size) {
+
5067 return
+
5068 }
+
5069
+
5070 let nanoseconds = UInt64.fromNumber(value.getTime()).mul(1000000)
+
5071 this.writeUInt64(this.fbeOffset, nanoseconds)
+
5072 }
+
5073}
+
5074
+
5075exports.FieldModelTimestamp = FieldModelTimestamp
+
5076)CODE";
+
5077
+
5078 // Prepare code template
+
5079 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
5080
+
5081 Write(code);
+
5082}
+
5083
+
5084void GeneratorJavaScript::GenerateFBEFieldModelUUID()
+
5085{
+
5086 std::string code = R"CODE(
+
5090class FieldModelUUID extends FieldModel {
+
5096 get fbeSize () {
+
5097 return 16
+
5098 }
+
5099
+
5106 get (defaults = UUID.nil()) {
+
5107 if ((this._buffer.offset + this.fbeOffset + this.fbeSize) > this._buffer.size) {
+
5108 return defaults
+
5109 }
+
5110
+
5111 return new UUID(this.readBytes(this.fbeOffset, 16))
+
5112 }
+
5113
+
5119 set (value) {
+
5120 console.assert(((this._buffer.offset + this.fbeOffset + this.fbeSize) <= this._buffer.size), 'Model is broken!')
+
5121 if ((this._buffer.offset + this.fbeOffset + this.fbeSize) > this._buffer.size) {
+
5122 return
+
5123 }
+
5124
+
5125 this.writeBytes(this.fbeOffset, value.data)
+
5126 }
+
5127}
+
5128
+
5129exports.FieldModelUUID = FieldModelUUID
+
5130)CODE";
+
5131
+
5132 // Prepare code template
+
5133 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
5134
+
5135 Write(code);
+
5136}
+
5137
+
5138void GeneratorJavaScript::GenerateFBEFieldModelBytes()
+
5139{
+
5140 std::string code = R"CODE(
+
5144class FieldModelBytes extends FieldModel {
+
5150 get fbeSize () {
+
5151 return 4
+
5152 }
+
5153
+
5159 get fbeExtra () {
+
5160 if ((this._buffer.offset + this.fbeOffset + this.fbeSize) > this._buffer.size) {
+
5161 return 0
+
5162 }
+
5163
+
5164 let fbeBytesOffset = this.readUInt32(this.fbeOffset)
+
5165 if ((fbeBytesOffset === 0) || ((this._buffer.offset + fbeBytesOffset + 4) > this._buffer.size)) {
+
5166 return 0
+
5167 }
+
5168
+
5169 let fbeBytesSize = this.readUInt32(fbeBytesOffset)
+
5170 return 4 + fbeBytesSize
+
5171 }
+
5172
+
5178 verify () {
+
5179 if ((this._buffer.offset + this.fbeOffset + this.fbeSize) > this._buffer.size) {
+
5180 return true
+
5181 }
+
5182
+
5183 let fbeBytesOffset = this.readUInt32(this.fbeOffset)
+
5184 if (fbeBytesOffset === 0) {
+
5185 return true
+
5186 }
+
5187
+
5188 if ((this._buffer.offset + fbeBytesOffset + 4) > this._buffer.size) {
+
5189 return false
+
5190 }
+
5191
+
5192 let fbeBytesSize = this.readUInt32(fbeBytesOffset)
+
5193 return (this._buffer.offset + fbeBytesOffset + 4 + fbeBytesSize) <= this._buffer.size
+
5194 }
+
5195
+
5202 get (defaults = new Uint8Array(0)) {
+
5203 if ((this._buffer.offset + this.fbeOffset + this.fbeSize) > this._buffer.size) {
+
5204 return defaults
+
5205 }
+
5206
+
5207 let fbeBytesOffset = this.readUInt32(this.fbeOffset)
+
5208 if (fbeBytesOffset === 0) {
+
5209 return defaults
+
5210 }
+
5211
+
5212 console.assert(((this._buffer.offset + fbeBytesOffset + 4) <= this._buffer.size), 'Model is broken!')
+
5213 if ((this._buffer.offset + fbeBytesOffset + 4) > this._buffer.size) {
+
5214 return defaults
+
5215 }
+
5216
+
5217 let fbeBytesSize = this.readUInt32(fbeBytesOffset)
+
5218 console.assert(((this._buffer.offset + fbeBytesOffset + 4 + fbeBytesSize) <= this._buffer.size), 'Model is broken!')
+
5219 if ((this._buffer.offset + fbeBytesOffset + 4 + fbeBytesSize) > this._buffer.size) {
+
5220 return defaults
+
5221 }
+
5222
+
5223 return this.readBytes(fbeBytesOffset + 4, fbeBytesSize)
+
5224 }
+
5225
+
5231 set (value) {
+
5232 console.assert(((this._buffer.offset + this.fbeOffset + this.fbeSize) <= this._buffer.size), 'Model is broken!')
+
5233 if ((this._buffer.offset + this.fbeOffset + this.fbeSize) > this._buffer.size) {
+
5234 return
+
5235 }
+
5236
+
5237 let fbeBytesSize = value.length
+
5238 let fbeBytesOffset = this._buffer.allocate(4 + fbeBytesSize) - this._buffer.offset
+
5239 console.assert(((fbeBytesOffset > 0) && ((this._buffer.offset + fbeBytesOffset + 4 + fbeBytesSize) <= this._buffer.size)), 'Model is broken!')
+
5240 if (((fbeBytesOffset <= 0) || ((this._buffer.offset + fbeBytesOffset + 4 + fbeBytesSize) > this._buffer.size))) {
+
5241 return
+
5242 }
+
5243
+
5244 this.writeUInt32(this.fbeOffset, fbeBytesOffset)
+
5245 this.writeUInt32(fbeBytesOffset, fbeBytesSize)
+
5246 this.writeBytes(fbeBytesOffset + 4, value)
+
5247 }
+
5248}
+
5249
+
5250exports.FieldModelBytes = FieldModelBytes
+
5251)CODE";
+
5252
+
5253 // Prepare code template
+
5254 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
5255
+
5256 Write(code);
+
5257}
+
5258
+
5259void GeneratorJavaScript::GenerateFBEFieldModelString()
+
5260{
+
5261 std::string code = R"CODE(
+
5265class FieldModelString extends FieldModel {
+
5271 get fbeSize () {
+
5272 return 4
+
5273 }
+
5274
+
5280 get fbeExtra () {
+
5281 if ((this._buffer.offset + this.fbeOffset + this.fbeSize) > this._buffer.size) {
+
5282 return 0
+
5283 }
+
5284
+
5285 let fbeStringOffset = this.readUInt32(this.fbeOffset)
+
5286 if ((fbeStringOffset === 0) || ((this._buffer.offset + fbeStringOffset + 4) > this._buffer.size)) {
+
5287 return 0
+
5288 }
+
5289
+
5290 let fbeStringSize = this.readUInt32(fbeStringOffset)
+
5291 return 4 + fbeStringSize
+
5292 }
+
5293
+
5299 verify () {
+
5300 if ((this._buffer.offset + this.fbeOffset + this.fbeSize) > this._buffer.size) {
+
5301 return true
+
5302 }
+
5303
+
5304 let fbeStringOffset = this.readUInt32(this.fbeOffset)
+
5305 if (fbeStringOffset === 0) {
+
5306 return true
+
5307 }
+
5308
+
5309 if ((this._buffer.offset + fbeStringOffset + 4) > this._buffer.size) {
+
5310 return false
+
5311 }
+
5312
+
5313 let fbeStringSize = this.readUInt32(fbeStringOffset)
+
5314 return (this._buffer.offset + fbeStringOffset + 4 + fbeStringSize) <= this._buffer.size
+
5315 }
+
5316
+
5323 get (defaults = '') {
+
5324 if ((this._buffer.offset + this.fbeOffset + this.fbeSize) > this._buffer.size) {
+
5325 return defaults
+
5326 }
+
5327
+
5328 let fbeStringOffset = this.readUInt32(this.fbeOffset)
+
5329 if (fbeStringOffset === 0) {
+
5330 return defaults
+
5331 }
+
5332
+
5333 console.assert(((this._buffer.offset + fbeStringOffset + 4) <= this._buffer.size), 'Model is broken!')
+
5334 if ((this._buffer.offset + fbeStringOffset + 4) > this._buffer.size) {
+
5335 return defaults
+
5336 }
+
5337
+
5338 let fbeStringSize = this.readUInt32(fbeStringOffset)
+
5339 console.assert(((this._buffer.offset + fbeStringOffset + 4 + fbeStringSize) <= this._buffer.size), 'Model is broken!')
+
5340 if ((this._buffer.offset + fbeStringOffset + 4 + fbeStringSize) > this._buffer.size) {
+
5341 return defaults
+
5342 }
+
5343
+
5344 return this.readString(fbeStringOffset + 4, fbeStringSize)
+
5345 }
+
5346
+
5352 set (value) {
+
5353 console.assert(((this._buffer.offset + this.fbeOffset + this.fbeSize) <= this._buffer.size), 'Model is broken!')
+
5354 if ((this._buffer.offset + this.fbeOffset + this.fbeSize) > this._buffer.size) {
+
5355 return
+
5356 }
+
5357
+
5358 let fbeStringSize = utf8count(value)
+
5359 let fbeStringOffset = this._buffer.allocate(4 + fbeStringSize) - this._buffer.offset
+
5360 console.assert(((fbeStringOffset > 0) && ((this._buffer.offset + fbeStringOffset + 4 + fbeStringSize) <= this._buffer.size)), 'Model is broken!')
+
5361 if ((fbeStringOffset <= 0) || ((this._buffer.offset + fbeStringOffset + 4 + fbeStringSize) > this._buffer.size)) {
+
5362 return
+
5363 }
+
5364
+
5365 this.writeUInt32(this.fbeOffset, fbeStringOffset)
+
5366 this.writeUInt32(fbeStringOffset, fbeStringSize)
+
5367 this.writeString(fbeStringOffset + 4, value, fbeStringSize)
+
5368 }
+
5369}
+
5370
+
5371exports.FieldModelString = FieldModelString
+
5372)CODE";
+
5373
+
5374 // Prepare code template
+
5375 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
5376
+
5377 Write(code);
+
5378}
+
5379
+
5380void GeneratorJavaScript::GenerateFBEFieldModelOptional()
+
5381{
+
5382 std::string code = R"CODE(
+
5386class FieldModelOptional extends FieldModel {
+
5394 constructor (model, buffer, offset) {
+
5395 super(buffer, offset)
+
5396 this._model = model
+
5397 this._model.fbeOffset = 0
+
5398 }
+
5399
+
5405 get fbeSize () {
+
5406 return 1 + 4
+
5407 }
+
5408
+
5414 get fbeExtra () {
+
5415 if (!this.hasValue) {
+
5416 return 0
+
5417 }
+
5418
+
5419 let fbeOptionalOffset = this.readUInt32(this.fbeOffset + 1)
+
5420 if ((fbeOptionalOffset === 0) || ((this._buffer.offset + fbeOptionalOffset + 4) > this._buffer.size)) {
+
5421 return 0
+
5422 }
+
5423
+
5424 this._buffer.shift(fbeOptionalOffset)
+
5425 let fbeResult = this.value.fbeSize + this.value.fbeExtra
+
5426 this._buffer.unshift(fbeOptionalOffset)
+
5427 return fbeResult
+
5428 }
+
5429
+
5435 get hasValue () {
+
5436 if ((this._buffer.offset + this.fbeOffset + this.fbeSize) > this._buffer.size) {
+
5437 return false
+
5438 }
+
5439
+
5440 let fbeHasValue = this.readUInt8(this.fbeOffset)
+
5441 return fbeHasValue !== 0
+
5442 }
+
5443
+
5449 get value () {
+
5450 return this._model
+
5451 }
+
5452
+
5458 verify () {
+
5459 if ((this._buffer.offset + this.fbeOffset + this.fbeSize) > this._buffer.size) {
+
5460 return true
+
5461 }
+
5462
+
5463 let fbeHasValue = this.readUInt8(this.fbeOffset)
+
5464 if (fbeHasValue === 0) {
+
5465 return true
+
5466 }
+
5467
+
5468 let fbeOptionalOffset = this.readUInt32(this.fbeOffset + 1)
+
5469 if (fbeOptionalOffset === 0) {
+
5470 return false
+
5471 }
+
5472
+
5473 this._buffer.shift(fbeOptionalOffset)
+
5474 let fbeResult = this.value.verify()
+
5475 this._buffer.unshift(fbeOptionalOffset)
+
5476 return fbeResult
+
5477 }
+
5478
+
5484 getBegin () {
+
5485 if (!this.hasValue) {
+
5486 return 0
+
5487 }
+
5488
+
5489 let fbeOptionalOffset = this.readUInt32(this.fbeOffset + 1)
+
5490 console.assert((fbeOptionalOffset > 0), 'Model is broken!')
+
5491 if (fbeOptionalOffset <= 0) {
+
5492 return 0
+
5493 }
+
5494
+
5495 this._buffer.shift(fbeOptionalOffset)
+
5496 return fbeOptionalOffset
+
5497 }
+
5498
+
5504 getEnd (begin) {
+
5505 this._buffer.unshift(begin)
+
5506 }
+
5507
+
5514 get (defaults = undefined) {
+
5515 let fbeBegin = this.getBegin()
+
5516 if (fbeBegin === 0) {
+
5517 return defaults
+
5518 }
+
5519 let optional = this.value.get()
+
5520 this.getEnd(fbeBegin)
+
5521 return optional
+
5522 }
+
5523
+
5530 setBegin (hasValue) {
+
5531 console.assert(((this._buffer.offset + this.fbeOffset + this.fbeSize) <= this._buffer.size), 'Model is broken!')
+
5532 if ((this._buffer.offset + this.fbeOffset + this.fbeSize) > this._buffer.size) {
+
5533 return 0
+
5534 }
+
5535
+
5536 this.writeUInt8(this.fbeOffset, (hasValue ? 1 : 0))
+
5537 if (!hasValue) {
+
5538 return 0
+
5539 }
+
5540
+
5541 let fbeOptionalSize = this.value.fbeSize
+
5542 let fbeOptionalOffset = this._buffer.allocate(fbeOptionalSize) - this._buffer.offset
+
5543 console.assert(((fbeOptionalOffset > 0) && ((this._buffer.offset + fbeOptionalOffset + fbeOptionalSize) <= this._buffer.size)), 'Model is broken!')
+
5544 if ((fbeOptionalOffset <= 0) || ((this._buffer.offset + fbeOptionalOffset + fbeOptionalSize) > this._buffer.size)) {
+
5545 return 0
+
5546 }
+
5547
+
5548 this.writeUInt32(this.fbeOffset + 1, fbeOptionalOffset)
+
5549
+
5550 this._buffer.shift(fbeOptionalOffset)
+
5551 return fbeOptionalOffset
+
5552 }
+
5553
+
5559 setEnd (begin) {
+
5560 this._buffer.unshift(begin)
+
5561 }
+
5562
+
5568 set (optional) {
+
5569 let fbeBegin = this.setBegin(optional != null)
+
5570 if (fbeBegin === 0) {
+
5571 return
+
5572 }
+
5573 this.value.set(optional)
+
5574 this.setEnd(fbeBegin)
+
5575 }
+
5576}
+
5577
+
5578exports.FieldModelOptional = FieldModelOptional
+
5579)CODE";
+
5580
+
5581 // Prepare code template
+
5582 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
5583
+
5584 Write(code);
+
5585}
+
5586
+
5587void GeneratorJavaScript::GenerateFBEFieldModelArray()
+
5588{
+
5589 std::string code = R"CODE(
+
5593class FieldModelArray extends FieldModel {
+
5602 constructor (model, buffer, offset, size) {
+
5603 super(buffer, offset)
+
5604 this._model = model
+
5605 this._size = size
+
5606 }
+
5607
+
5613 get fbeSize () {
+
5614 return this._size * this._model.fbeSize
+
5615 }
+
5616
+
5622 get fbeExtra () {
+
5623 return 0
+
5624 }
+
5625
+
5631 get offset () {
+
5632 return 0
+
5633 }
+
5634
+
5640 get size () {
+
5641 return this._size
+
5642 }
+
5643
+
5650 getItem (index) {
+
5651 console.assert(((this._buffer.offset + this.fbeOffset + this.fbeSize) <= this._buffer.size), 'Model is broken!')
+
5652 if (index >= this._size) {
+
5653 throw new Error('Index is out of bounds!')
+
5654 }
+
5655
+
5656 this._model.fbeOffset = this.fbeOffset
+
5657 this._model.fbeShift(index * this._model.fbeSize)
+
5658 return this._model
+
5659 }
+
5660
+
5666 verify () {
+
5667 if ((this._buffer.offset + this.fbeOffset + this.fbeSize) > this._buffer.size) {
+
5668 return false
+
5669 }
+
5670
+
5671 this._model.fbeOffset = this.fbeOffset
+
5672 for (let i = 0; i < this._size; i++) {
+
5673 if (!this._model.verify()) {
+
5674 return false
+
5675 }
+
5676 this._model.fbeShift(this._model.fbeSize)
+
5677 }
+
5678
+
5679 return true
+
5680 }
+
5681
+
5688 get (values = []) {
+
5689 values.length = 0
+
5690
+
5691 let fbeModel = this.getItem(0)
+
5692 for (let i = 0; i < this._size; i++) {
+
5693 let value = fbeModel.get()
+
5694 values.push(value)
+
5695 fbeModel.fbeShift(fbeModel.fbeSize)
+
5696 }
+
5697
+
5698 return values
+
5699 }
+
5700
+
5706 set (values) {
+
5707 console.assert(((this._buffer.offset + this.fbeOffset + this.fbeSize) <= this._buffer.size), 'Model is broken!')
+
5708 if ((this._buffer.offset + this.fbeOffset + this.fbeSize) > this._buffer.size) {
+
5709 return
+
5710 }
+
5711
+
5712 let fbeModel = this.getItem(0)
+
5713 for (let i = 0; i < Math.min(values.length, this._size); i++) {
+
5714 fbeModel.set(values[i])
+
5715 fbeModel.fbeShift(fbeModel.fbeSize)
+
5716 }
+
5717 }
+
5718}
+
5719
+
5720exports.FieldModelArray = FieldModelArray
+
5721)CODE";
+
5722
+
5723 // Prepare code template
+
5724 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
5725
+
5726 Write(code);
+
5727}
+
5728
+
5729void GeneratorJavaScript::GenerateFBEFieldModelVector()
+
5730{
+
5731 std::string code = R"CODE(
+
5735class FieldModelVector extends FieldModel {
+
5743 constructor (model, buffer, offset) {
+
5744 super(buffer, offset)
+
5745 this._model = model
+
5746 }
+
5747
+
5753 get fbeSize () {
+
5754 return 4
+
5755 }
+
5756
+
5762 get fbeExtra () {
+
5763 if ((this._buffer.offset + this.fbeOffset + this.fbeSize) > this._buffer.size) {
+
5764 return 0
+
5765 }
+
5766
+
5767 let fbeVectorOffset = this.readUInt32(this.fbeOffset)
+
5768 if ((fbeVectorOffset === 0) || ((this._buffer.offset + fbeVectorOffset + 4) > this._buffer.size)) {
+
5769 return 0
+
5770 }
+
5771
+
5772 let fbeVectorSize = this.readUInt32(fbeVectorOffset)
+
5773
+
5774 let fbeResult = 4
+
5775 this._model.fbeOffset = fbeVectorOffset + 4
+
5776 for (let i = 0; i < fbeVectorSize; i++) {
+
5777 fbeResult += this._model.fbeSize + this._model.fbeExtra
+
5778 this._model.fbeShift(this._model.fbeSize)
+
5779 }
+
5780 return fbeResult
+
5781 }
+
5782
+
5788 get offset () {
+
5789 if ((this._buffer.offset + this.fbeOffset + this.fbeSize) > this._buffer.size) {
+
5790 return 0
+
5791 }
+
5792
+
5793 // noinspection UnnecessaryLocalVariableJS
+
5794 let fbeVectorOffset = this.readUInt32(this.fbeOffset)
+
5795 return fbeVectorOffset
+
5796 }
+
5797
+
5803 get size () {
+
5804 if ((this._buffer.offset + this.fbeOffset + this.fbeSize) > this._buffer.size) {
+
5805 return 0
+
5806 }
+
5807
+
5808 let fbeVectorOffset = this.readUInt32(this.fbeOffset)
+
5809 if ((fbeVectorOffset === 0) || ((this._buffer.offset + fbeVectorOffset + 4) > this._buffer.size)) {
+
5810 return 0
+
5811 }
+
5812
+
5813 // noinspection UnnecessaryLocalVariableJS
+
5814 let fbeVectorSize = this.readUInt32(fbeVectorOffset)
+
5815 return fbeVectorSize
+
5816 }
+
5817
+
5824 getItem (index) {
+
5825 console.assert(((this._buffer.offset + this.fbeOffset + this.fbeSize) <= this._buffer.size), 'Model is broken!')
+
5826
+
5827 let fbeVectorOffset = this.readUInt32(this.fbeOffset)
+
5828 console.assert(((fbeVectorOffset > 0) && ((this._buffer.offset + fbeVectorOffset + 4) <= this._buffer.size)), 'Model is broken!')
+
5829
+
5830 let fbeVectorSize = this.readUInt32(fbeVectorOffset)
+
5831 if (index >= fbeVectorSize) {
+
5832 throw new Error('Index is out of bounds!')
+
5833 }
+
5834
+
5835 this._model.fbeOffset = fbeVectorOffset + 4
+
5836 this._model.fbeShift(index * this._model.fbeSize)
+
5837 return this._model
+
5838 }
+
5839
+
5846 resize (size) {
+
5847 let fbeVectorSize = size * this._model.fbeSize
+
5848 let fbeVectorOffset = this._buffer.allocate(4 + fbeVectorSize) - this._buffer.offset
+
5849 console.assert(((fbeVectorOffset > 0) && ((this._buffer.offset + fbeVectorOffset + 4) <= this._buffer.size)), 'Model is broken!')
+
5850
+
5851 this.writeUInt32(this.fbeOffset, fbeVectorOffset)
+
5852 this.writeUInt32(fbeVectorOffset, size)
+
5853 this.writeCount(fbeVectorOffset + 4, 0, fbeVectorSize)
+
5854
+
5855 this._model.fbeOffset = fbeVectorOffset + 4
+
5856 return this._model
+
5857 }
+
5858
+
5864 verify () {
+
5865 if ((this._buffer.offset + this.fbeOffset + this.fbeSize) > this._buffer.size) {
+
5866 return true
+
5867 }
+
5868
+
5869 let fbeVectorOffset = this.readUInt32(this.fbeOffset)
+
5870 if (fbeVectorOffset === 0) {
+
5871 return true
+
5872 }
+
5873
+
5874 if ((this._buffer.offset + fbeVectorOffset + 4) > this._buffer.size) {
+
5875 return false
+
5876 }
+
5877
+
5878 let fbeVectorSize = this.readUInt32(fbeVectorOffset)
+
5879
+
5880 this._model.fbeOffset = fbeVectorOffset + 4
+
5881 for (let i = 0; i < fbeVectorSize; i++) {
+
5882 if (!this._model.verify()) {
+
5883 return false
+
5884 }
+
5885 this._model.fbeShift(this._model.fbeSize)
+
5886 }
+
5887
+
5888 return true
+
5889 }
+
5890
+
5897 get (values = []) {
+
5898 values.length = 0
+
5899
+
5900 let fbeVectorSize = this.size
+
5901 if (fbeVectorSize === 0) {
+
5902 return values
+
5903 }
+
5904
+
5905 let fbeModel = this.getItem(0)
+
5906 for (let i = 0; i < fbeVectorSize; i++) {
+
5907 let value = fbeModel.get()
+
5908 values.push(value)
+
5909 fbeModel.fbeShift(fbeModel.fbeSize)
+
5910 }
+
5911
+
5912 return values
+
5913 }
+
5914
+
5920 set (values) {
+
5921 console.assert(((this._buffer.offset + this.fbeOffset + this.fbeSize) <= this._buffer.size), 'Model is broken!')
+
5922 if ((this._buffer.offset + this.fbeOffset + this.fbeSize) > this._buffer.size) {
+
5923 return
+
5924 }
+
5925
+
5926 let fbeModel = this.resize(values.length)
+
5927 for (let value of values) {
+
5928 fbeModel.set(value)
+
5929 fbeModel.fbeShift(fbeModel.fbeSize)
+
5930 }
+
5931 }
+
5932}
+
5933
+
5934exports.FieldModelVector = FieldModelVector
+
5935)CODE";
+
5936
+
5937 // Prepare code template
+
5938 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
5939
+
5940 Write(code);
+
5941}
+
5942
+
5943void GeneratorJavaScript::GenerateFBEFieldModelSet()
+
5944{
+
5945 std::string code = R"CODE(
+
5949class FieldModelSet extends FieldModel {
+
5957 constructor (model, buffer, offset) {
+
5958 super(buffer, offset)
+
5959 this._model = model
+
5960 }
+
5961
+
5967 get fbeSize () {
+
5968 return 4
+
5969 }
+
5970
+
5976 get fbeExtra () {
+
5977 if ((this._buffer.offset + this.fbeOffset + this.fbeSize) > this._buffer.size) {
+
5978 return 0
+
5979 }
+
5980
+
5981 let fbeSetOffset = this.readUInt32(this.fbeOffset)
+
5982 if ((fbeSetOffset === 0) || ((this._buffer.offset + fbeSetOffset + 4) > this._buffer.size)) {
+
5983 return 0
+
5984 }
+
5985
+
5986 let fbeSetSize = this.readUInt32(fbeSetOffset)
+
5987
+
5988 let fbeResult = 4
+
5989 this._model.fbeOffset = fbeSetOffset + 4
+
5990 for (let i = 0; i < fbeSetSize; i++) {
+
5991 fbeResult += this._model.fbeSize + this._model.fbeExtra
+
5992 this._model.fbeShift(this._model.fbeSize)
+
5993 }
+
5994 return fbeResult
+
5995 }
+
5996
+
6002 get offset () {
+
6003 if ((this._buffer.offset + this.fbeOffset + this.fbeSize) > this._buffer.size) {
+
6004 return 0
+
6005 }
+
6006
+
6007 // noinspection UnnecessaryLocalVariableJS
+
6008 let fbeSetOffset = this.readUInt32(this.fbeOffset)
+
6009 return fbeSetOffset
+
6010 }
+
6011
+
6017 get size () {
+
6018 if ((this._buffer.offset + this.fbeOffset + this.fbeSize) > this._buffer.size) {
+
6019 return 0
+
6020 }
+
6021
+
6022 let fbeSetOffset = this.readUInt32(this.fbeOffset)
+
6023 if ((fbeSetOffset === 0) || ((this._buffer.offset + fbeSetOffset + 4) > this._buffer.size)) {
+
6024 return 0
+
6025 }
+
6026
+
6027 // noinspection UnnecessaryLocalVariableJS
+
6028 let fbeSetSize = this.readUInt32(fbeSetOffset)
+
6029 return fbeSetSize
+
6030 }
+
6031
+
6038 getItem (index) {
+
6039 console.assert(((this._buffer.offset + this.fbeOffset + this.fbeSize) <= this._buffer.size), 'Model is broken!')
+
6040
+
6041 let fbeSetOffset = this.readUInt32(this.fbeOffset)
+
6042 console.assert(((fbeSetOffset > 0) && ((this._buffer.offset + fbeSetOffset + 4) <= this._buffer.size)), 'Model is broken!')
+
6043
+
6044 let fbeSetSize = this.readUInt32(fbeSetOffset)
+
6045 if (index >= fbeSetSize) {
+
6046 throw new Error('Index is out of bounds!')
+
6047 }
+
6048
+
6049 this._model.fbeOffset = fbeSetOffset + 4
+
6050 this._model.fbeShift(index * this._model.fbeSize)
+
6051 return this._model
+
6052 }
+
6053
+
6060 resize (size) {
+
6061 let fbeSetSize = size * this._model.fbeSize
+
6062 let fbeSetOffset = this._buffer.allocate(4 + fbeSetSize) - this._buffer.offset
+
6063 console.assert(((fbeSetOffset > 0) && ((this._buffer.offset + fbeSetOffset + 4) <= this._buffer.size)), 'Model is broken!')
+
6064
+
6065 this.writeUInt32(this.fbeOffset, fbeSetOffset)
+
6066 this.writeUInt32(fbeSetOffset, size)
+
6067 this.writeCount(fbeSetOffset + 4, 0, fbeSetSize)
+
6068
+
6069 this._model.fbeOffset = fbeSetOffset + 4
+
6070 return this._model
+
6071 }
+
6072
+
6078 verify () {
+
6079 if ((this._buffer.offset + this.fbeOffset + this.fbeSize) > this._buffer.size) {
+
6080 return true
+
6081 }
+
6082
+
6083 let fbeSetOffset = this.readUInt32(this.fbeOffset)
+
6084 if (fbeSetOffset === 0) {
+
6085 return true
+
6086 }
+
6087
+
6088 if ((this._buffer.offset + fbeSetOffset + 4) > this._buffer.size) {
+
6089 return false
+
6090 }
+
6091
+
6092 let fbeSetSize = this.readUInt32(fbeSetOffset)
+
6093
+
6094 this._model.fbeOffset = fbeSetOffset + 4
+
6095 for (let i = 0; i < fbeSetSize; i++) {
+
6096 if (!this._model.verify()) {
+
6097 return false
+
6098 }
+
6099 this._model.fbeShift(this._model.fbeSize)
+
6100 }
+
6101
+
6102 return true
+
6103 }
+
6104
+
6111 get (values = new Set()) {
+
6112 values.clear()
+
6113
+
6114 let fbeSetSize = this.size
+
6115 if (fbeSetSize === 0) {
+
6116 return values
+
6117 }
+
6118
+
6119 let fbeModel = this.getItem(0)
+
6120 for (let i = 0; i < fbeSetSize; i++) {
+
6121 let value = fbeModel.get()
+
6122 values.add(value)
+
6123 fbeModel.fbeShift(fbeModel.fbeSize)
+
6124 }
+
6125
+
6126 return values
+
6127 }
+
6128
+
6134 set (values) {
+
6135 console.assert(((this._buffer.offset + this.fbeOffset + this.fbeSize) <= this._buffer.size), 'Model is broken!')
+
6136 if ((this._buffer.offset + this.fbeOffset + this.fbeSize) > this._buffer.size) {
+
6137 return
+
6138 }
+
6139
+
6140 let fbeModel = this.resize(values.size)
+
6141 for (let value of values) {
+
6142 fbeModel.set(value)
+
6143 fbeModel.fbeShift(fbeModel.fbeSize)
+
6144 }
+
6145 }
+
6146}
+
6147
+
6148exports.FieldModelSet = FieldModelSet
+
6149)CODE";
+
6150
+
6151 // Prepare code template
+
6152 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
6153
+
6154 Write(code);
+
6155}
+
6156
+
6157void GeneratorJavaScript::GenerateFBEFieldModelMap()
+
6158{
+
6159 std::string code = R"CODE(
+
6163class FieldModelMap extends FieldModel {
+
6172 constructor (modelKey, modelValue, buffer, offset) {
+
6173 super(buffer, offset)
+
6174 this._modelKey = modelKey
+
6175 this._modelValue = modelValue
+
6176 }
+
6177
+
6183 get fbeSize () {
+
6184 return 4
+
6185 }
+
6186
+
6192 get fbeExtra () {
+
6193 if ((this._buffer.offset + this.fbeOffset + this.fbeSize) > this._buffer.size) {
+
6194 return 0
+
6195 }
+
6196
+
6197 let fbeMapOffset = this.readUInt32(this.fbeOffset)
+
6198 if ((fbeMapOffset === 0) || ((this._buffer.offset + fbeMapOffset + 4) > this._buffer.size)) {
+
6199 return 0
+
6200 }
+
6201
+
6202 let fbeMapSize = this.readUInt32(fbeMapOffset)
+
6203
+
6204 let fbeResult = 4
+
6205 this._modelKey.fbeOffset = fbeMapOffset + 4
+
6206 this._modelValue.fbeOffset = fbeMapOffset + 4 + this._modelKey.fbeSize
+
6207 for (let i = 0; i < fbeMapSize; i++) {
+
6208 fbeResult += this._modelKey.fbeSize + this._modelKey.fbeExtra
+
6209 this._modelKey.fbeShift(this._modelKey.fbeSize + this._modelValue.fbeSize)
+
6210 fbeResult += this._modelValue.fbeSize + this._modelValue.fbeExtra
+
6211 this._modelValue.fbeShift(this._modelKey.fbeSize + this._modelValue.fbeSize)
+
6212 }
+
6213 return fbeResult
+
6214 }
+
6215
+
6221 get offset () {
+
6222 if ((this._buffer.offset + this.fbeOffset + this.fbeSize) > this._buffer.size) {
+
6223 return 0
+
6224 }
+
6225
+
6226 // noinspection UnnecessaryLocalVariableJS
+
6227 let fbeMapOffset = this.readUInt32(this.fbeOffset)
+
6228 return fbeMapOffset
+
6229 }
+
6230
+
6236 get size () {
+
6237 if ((this._buffer.offset + this.fbeOffset + this.fbeSize) > this._buffer.size) {
+
6238 return 0
+
6239 }
+
6240
+
6241 let fbeMapOffset = this.readUInt32(this.fbeOffset)
+
6242 if ((fbeMapOffset === 0) || ((this._buffer.offset + fbeMapOffset + 4) > this._buffer.size)) {
+
6243 return 0
+
6244 }
+
6245
+
6246 // noinspection UnnecessaryLocalVariableJS
+
6247 let fbeMapSize = this.readUInt32(fbeMapOffset)
+
6248 return fbeMapSize
+
6249 }
+
6250
+
6257 getItem (index) {
+
6258 console.assert(((this._buffer.offset + this.fbeOffset + this.fbeSize) <= this._buffer.size), 'Model is broken!')
+
6259
+
6260 let fbeMapOffset = this.readUInt32(this.fbeOffset)
+
6261 console.assert(((fbeMapOffset > 0) && ((this._buffer.offset + fbeMapOffset + 4) <= this._buffer.size)), 'Model is broken!')
+
6262
+
6263 let fbeMapSize = this.readUInt32(fbeMapOffset)
+
6264 if (index >= fbeMapSize) {
+
6265 throw new Error('Index is out of bounds!')
+
6266 }
+
6267
+
6268 this._modelKey.fbeOffset = fbeMapOffset + 4
+
6269 this._modelValue.fbeOffset = fbeMapOffset + 4 + this._modelKey.fbeSize
+
6270 this._modelKey.fbeShift(index * (this._modelKey.fbeSize + this._modelValue.fbeSize))
+
6271 this._modelValue.fbeShift(index * (this._modelKey.fbeSize + this._modelValue.fbeSize))
+
6272 return [this._modelKey, this._modelValue]
+
6273 }
+
6274
+
6281 resize (size) {
+
6282 let fbeMapSize = size * (this._modelKey.fbeSize + this._modelValue.fbeSize)
+
6283 let fbeMapOffset = this._buffer.allocate(4 + fbeMapSize) - this._buffer.offset
+
6284 console.assert(((fbeMapOffset > 0) && ((this._buffer.offset + fbeMapOffset + 4) <= this._buffer.size)), 'Model is broken!')
+
6285
+
6286 this.writeUInt32(this.fbeOffset, fbeMapOffset)
+
6287 this.writeUInt32(fbeMapOffset, size)
+
6288 this.writeCount(fbeMapOffset + 4, 0, fbeMapSize)
+
6289
+
6290 this._modelKey.fbeOffset = fbeMapOffset + 4
+
6291 this._modelValue.fbeOffset = fbeMapOffset + 4 + this._modelKey.fbeSize
+
6292 return [this._modelKey, this._modelValue]
+
6293 }
+
6294
+
6300 verify () {
+
6301 if ((this._buffer.offset + this.fbeOffset + this.fbeSize) > this._buffer.size) {
+
6302 return true
+
6303 }
+
6304
+
6305 let fbeMapOffset = this.readUInt32(this.fbeOffset)
+
6306 if (fbeMapOffset === 0) {
+
6307 return true
+
6308 }
+
6309
+
6310 if ((this._buffer.offset + fbeMapOffset + 4) > this._buffer.size) {
+
6311 return false
+
6312 }
+
6313
+
6314 let fbeMapSize = this.readUInt32(fbeMapOffset)
+
6315
+
6316 this._modelKey.fbeOffset = fbeMapOffset + 4
+
6317 this._modelValue.fbeOffset = fbeMapOffset + 4 + this._modelKey.fbeSize
+
6318 for (let i = 0; i < fbeMapSize; i++) {
+
6319 if (!this._modelKey.verify()) {
+
6320 return false
+
6321 }
+
6322 this._modelKey.fbeShift(this._modelKey.fbeSize + this._modelValue.fbeSize)
+
6323 if (!this._modelValue.verify()) {
+
6324 return false
+
6325 }
+
6326 this._modelValue.fbeShift(this._modelKey.fbeSize + this._modelValue.fbeSize)
+
6327 }
+
6328
+
6329 return true
+
6330 }
+
6331
+
6338 get (values = new Map()) {
+
6339 values.clear()
+
6340
+
6341 let fbeMapSize = this.size
+
6342 if (fbeMapSize === 0) {
+
6343 return values
+
6344 }
+
6345
+
6346 let [fbeModelKey, fbeModelValue] = this.getItem(0)
+
6347 for (let i = 0; i < fbeMapSize; i++) {
+
6348 let key = fbeModelKey.get()
+
6349 let value = fbeModelValue.get()
+
6350 values.set(key, value)
+
6351 fbeModelKey.fbeShift(fbeModelKey.fbeSize + fbeModelValue.fbeSize)
+
6352 fbeModelValue.fbeShift(fbeModelKey.fbeSize + fbeModelValue.fbeSize)
+
6353 }
+
6354
+
6355 return values
+
6356 }
+
6357
+
6363 set (values) {
+
6364 console.assert(((this._buffer.offset + this.fbeOffset + this.fbeSize) <= this._buffer.size), 'Model is broken!')
+
6365 if ((this._buffer.offset + this.fbeOffset + this.fbeSize) > this._buffer.size) {
+
6366 return
+
6367 }
+
6368
+
6369 let [fbeModelKey, fbeModelValue] = this.resize(values.size)
+
6370 for (let [key, value] of values) {
+
6371 fbeModelKey.set(key)
+
6372 fbeModelKey.fbeShift(fbeModelKey.fbeSize + fbeModelValue.fbeSize)
+
6373 fbeModelValue.set(value)
+
6374 fbeModelValue.fbeShift(fbeModelKey.fbeSize + fbeModelValue.fbeSize)
+
6375 }
+
6376 }
+
6377}
+
6378
+
6379exports.FieldModelMap = FieldModelMap
+
6380)CODE";
+
6381
+
6382 // Prepare code template
+
6383 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
6384
+
6385 Write(code);
+
6386}
+
6387
+
6388void GeneratorJavaScript::GenerateFBEFinalModel()
+
6389{
+
6390 std::string code = R"CODE(
+
6394class FinalModel extends FieldModelBase {
+
6400 verify () {
+
6401 return Number.MAX_SAFE_INTEGER
+
6402 }
+
6403}
+
6404
+
6405exports.FinalModel = FinalModel
+
6406)CODE";
+
6407
+
6408 // Prepare code template
+
6409 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
6410
+
6411 Write(code);
+
6412}
+
6413
+
6414void GeneratorJavaScript::GenerateFBEFinalModel(const std::string& name, const std::string& type, const std::string& base, const std::string& size, const std::string& defaults)
+
6415{
+
6416 std::string code = R"CODE(
+
6420class FinalModel_NAME_ extends FinalModel {
+
6427 fbeAllocationSize (value) {
+
6428 return this.fbeSize
+
6429 }
+
6430
+
6436 get fbeSize () {
+
6437 return _SIZE_
+
6438 }
+
6439
+
6445 verify () {
+
6446 if ((this._buffer.offset + this.fbeOffset + this.fbeSize) > this._buffer.size) {
+
6447 return Number.MAX_SAFE_INTEGER
+
6448 }
+
6449
+
6450 return this.fbeSize
+
6451 }
+
6452
+
6458 get () {
+
6459 if ((this._buffer.offset + this.fbeOffset + this.fbeSize) > this._buffer.size) {
+
6460 return { value: _DEFAULTS_, size: 0 }
+
6461 }
+
6462
+
6463 return { value: this.read_NAME_(this.fbeOffset), size: this.fbeSize }
+
6464 }
+
6465
+
6472 set (value) {
+
6473 console.assert(((this._buffer.offset + this.fbeOffset + this.fbeSize) <= this._buffer.size), 'Model is broken!')
+
6474 if ((this._buffer.offset + this.fbeOffset + this.fbeSize) > this._buffer.size) {
+
6475 return 0
+
6476 }
+
6477
+
6478 this.write_NAME_(this.fbeOffset, value)
+
6479 return this.fbeSize
+
6480 }
+
6481}
+
6482
+
6483exports.FinalModel_NAME_ = FinalModel_NAME_
+
6484)CODE";
+
6485
+
6486 // Prepare code template
+
6487 code = std::regex_replace(code, std::regex("_NAME_"), name);
+
6488 code = std::regex_replace(code, std::regex("_TYPE_"), type);
+
6489 code = std::regex_replace(code, std::regex("_BASE_"), base);
+
6490 code = std::regex_replace(code, std::regex("_SIZE_"), size);
+
6491 code = std::regex_replace(code, std::regex("_DEFAULTS_"), defaults);
+
6492 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
6493
+
6494 Write(code);
+
6495}
+
6496
+
6497void GeneratorJavaScript::GenerateFBEFinalModelDecimal()
+
6498{
+
6499 std::string code = R"CODE(
+
6503class FinalModelDecimal extends FinalModel {
+
6510 fbeAllocationSize (value) {
+
6511 return this.fbeSize
+
6512 }
+
6513
+
6519 get fbeSize () {
+
6520 return 16
+
6521 }
+
6522
+
6528 verify () {
+
6529 if ((this._buffer.offset + this.fbeOffset + this.fbeSize) > this._buffer.size) {
+
6530 return Number.MAX_SAFE_INTEGER
+
6531 }
+
6532
+
6533 return this.fbeSize
+
6534 }
+
6535
+
6541 get () {
+
6542 if ((this._buffer.offset + this.fbeOffset + this.fbeSize) > this._buffer.size) {
+
6543 return { value: new Big(0), size: 0 }
+
6544 }
+
6545
+
6546 // Read decimal parts
+
6547 let low = this.readUInt32(this.fbeOffset)
+
6548 let mid = this.readUInt32(this.fbeOffset + 4)
+
6549 let high = this.readUInt32(this.fbeOffset + 8)
+
6550 let flags = this.readUInt32(this.fbeOffset + 12)
+
6551
+
6552 // Calculate decimal value
+
6553 let negative = (flags & 0x80000000) !== 0
+
6554 let scale = (flags & 0x7FFFFFFF) >> 16
+
6555 let result = new Big(0)
+
6556 result = result.add(new Big(high).mul('18446744073709551616'))
+
6557 result = result.add(new Big(mid).mul('4294967296'))
+
6558 result = result.add(new Big(low))
+
6559 result = result.div(Math.pow(10, scale))
+
6560 if (negative) {
+
6561 result.s = -1
+
6562 }
+
6563
+
6564 return { value: result, size: this.fbeSize }
+
6565 }
+
6566
+
6573 set (value) {
+
6574 console.assert(((this._buffer.offset + this.fbeOffset + this.fbeSize) <= this._buffer.size), 'Model is broken!')
+
6575 if ((this._buffer.offset + this.fbeOffset + this.fbeSize) > this._buffer.size) {
+
6576 return 0
+
6577 }
+
6578
+
6579 // Extract decimal parts
+
6580 let negative = value.s < 0
+
6581 let scale = Math.max(0, value.c.length - 1 - value.e)
+
6582 let number = value.mul(Math.pow(10, scale)).abs()
+
6583
+
6584 // Check for decimal scale overflow
+
6585 if ((scale < 0) || (scale > 28)) {
+
6586 // Value scale exceeds .NET Decimal limit of [0, 28]
+
6587 this.writeCount(this.fbeOffset, 0, this.fbeSize)
+
6588 return this.fbeSize
+
6589 }
+
6590
+
6591 // Write unscaled value to bytes 0-11
+
6592 let index = 0
+
6593 while (number > 0) {
+
6594 // Check for decimal number overflow
+
6595 if (index > 11) {
+
6596 // Value too big for .NET Decimal (bit length is limited to [0, 96])
+
6597 this.writeCount(this.fbeOffset, 0, this.fbeSize)
+
6598 return this.fbeSize
+
6599 }
+
6600 let byte = parseInt(number.mod(256))
+
6601 this.writeByte(this.fbeOffset + index, byte)
+
6602 number = number.div(256).round(0, 0)
+
6603 index++
+
6604 }
+
6605
+
6606 // Fill remaining bytes with zeros
+
6607 while (index < 12) {
+
6608 this.writeByte(this.fbeOffset + index, 0)
+
6609 index++
+
6610 }
+
6611
+
6612 // Write scale at byte 14
+
6613 this.writeByte(this.fbeOffset + 14, scale)
+
6614
+
6615 // Write signum at byte 15
+
6616 this.writeByte(this.fbeOffset + 15, (negative ? 0x80 : 0))
+
6617 return this.fbeSize
+
6618 }
+
6619}
+
6620
+
6621exports.FinalModelDecimal = FinalModelDecimal
+
6622)CODE";
+
6623
+
6624 // Prepare code template
+
6625 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
6626
+
6627 Write(code);
+
6628}
+
6629
+
6630void GeneratorJavaScript::GenerateFBEFinalModelTimestamp()
+
6631{
+
6632 std::string code = R"CODE(
+
6636class FinalModelTimestamp extends FinalModel {
+
6643 fbeAllocationSize (value) {
+
6644 return this.fbeSize
+
6645 }
+
6646
+
6652 get fbeSize () {
+
6653 return 8
+
6654 }
+
6655
+
6661 verify () {
+
6662 if ((this._buffer.offset + this.fbeOffset + this.fbeSize) > this._buffer.size) {
+
6663 return Number.MAX_SAFE_INTEGER
+
6664 }
+
6665
+
6666 return this.fbeSize
+
6667 }
+
6668
+
6674 get () {
+
6675 if ((this._buffer.offset + this.fbeOffset + this.fbeSize) > this._buffer.size) {
+
6676 return { value: new Date(0), size: 0 }
+
6677 }
+
6678
+
6679 let nanoseconds = this.readUInt64(this.fbeOffset)
+
6680 return { value: new Date(Math.round(nanoseconds / 1000000)), size: this.fbeSize }
+
6681 }
+
6682
+
6689 set (value) {
+
6690 console.assert(((this._buffer.offset + this.fbeOffset + this.fbeSize) <= this._buffer.size), 'Model is broken!')
+
6691 if ((this._buffer.offset + this.fbeOffset + this.fbeSize) > this._buffer.size) {
+
6692 return 0
+
6693 }
+
6694
+
6695 let nanoseconds = UInt64.fromNumber(value.getTime()).mul(1000000)
+
6696 this.writeUInt64(this.fbeOffset, nanoseconds)
+
6697 return this.fbeSize
+
6698 }
+
6699}
+
6700
+
6701exports.FinalModelTimestamp = FinalModelTimestamp
+
6702)CODE";
+
6703
+
6704 // Prepare code template
+
6705 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
6706
+
6707 Write(code);
+
6708}
+
6709
+
6710void GeneratorJavaScript::GenerateFBEFinalModelUUID()
+
6711{
+
6712 std::string code = R"CODE(
+
6716class FinalModelUUID extends FinalModel {
+
6723 fbeAllocationSize (value) {
+
6724 return this.fbeSize
+
6725 }
+
6726
+
6732 get fbeSize () {
+
6733 return 16
+
6734 }
+
6735
+
6741 verify () {
+
6742 if ((this._buffer.offset + this.fbeOffset + this.fbeSize) > this._buffer.size) {
+
6743 return Number.MAX_SAFE_INTEGER
+
6744 }
+
6745
+
6746 return this.fbeSize
+
6747 }
+
6748
+
6754 get () {
+
6755 if ((this._buffer.offset + this.fbeOffset + this.fbeSize) > this._buffer.size) {
+
6756 return { value: new UUID(), size: 0 }
+
6757 }
+
6758
+
6759 return { value: new UUID(this.readBytes(this.fbeOffset, 16)), size: this.fbeSize }
+
6760 }
+
6761
+
6768 set (value) {
+
6769 console.assert(((this._buffer.offset + this.fbeOffset + this.fbeSize) <= this._buffer.size), 'Model is broken!')
+
6770 if ((this._buffer.offset + this.fbeOffset + this.fbeSize) > this._buffer.size) {
+
6771 return 0
+
6772 }
+
6773
+
6774 this.writeBytes(this.fbeOffset, value.data)
+
6775 return this.fbeSize
+
6776 }
+
6777}
+
6778
+
6779exports.FinalModelUUID = FinalModelUUID
+
6780)CODE";
+
6781
+
6782 // Prepare code template
+
6783 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
6784
+
6785 Write(code);
+
6786}
+
6787
+
6788void GeneratorJavaScript::GenerateFBEFinalModelBytes()
+
6789{
+
6790 std::string code = R"CODE(
+
6794class FinalModelBytes extends FinalModel {
+
6801 fbeAllocationSize (value) {
+
6802 return 4 + value.length
+
6803 }
+
6804
+
6810 verify () {
+
6811 if ((this._buffer.offset + this.fbeOffset + 4) > this._buffer.size) {
+
6812 return Number.MAX_SAFE_INTEGER
+
6813 }
+
6814
+
6815 let fbeBytesSize = this.readUInt32(this.fbeOffset)
+
6816 if ((this._buffer.offset + this.fbeOffset + 4 + fbeBytesSize) > this._buffer.size) {
+
6817 return Number.MAX_SAFE_INTEGER
+
6818 }
+
6819
+
6820 return 4 + fbeBytesSize
+
6821 }
+
6822
+
6828 get () {
+
6829 if ((this._buffer.offset + this.fbeOffset + 4) > this._buffer.size) {
+
6830 return { value: new Uint8Array(0), size: 0 }
+
6831 }
+
6832
+
6833 let fbeBytesSize = this.readUInt32(this.fbeOffset)
+
6834 console.assert(((this._buffer.offset + this.fbeOffset + 4 + fbeBytesSize) <= this._buffer.size), 'Model is broken!')
+
6835 if ((this._buffer.offset + this.fbeOffset + 4 + fbeBytesSize) > this._buffer.size) {
+
6836 return { value: new Uint8Array(0), size: 4 }
+
6837 }
+
6838
+
6839 return { value: this.readBytes(this.fbeOffset + 4, fbeBytesSize), size: (4 + fbeBytesSize) }
+
6840 }
+
6841
+
6848 set (value) {
+
6849 console.assert(((this._buffer.offset + this.fbeOffset + 4) <= this._buffer.size), 'Model is broken!')
+
6850 if ((this._buffer.offset + this.fbeOffset + 4) > this._buffer.size) {
+
6851 return 0
+
6852 }
+
6853
+
6854 let fbeBytesSize = value.length
+
6855 console.assert(((this._buffer.offset + this.fbeOffset + 4 + fbeBytesSize) <= this._buffer.size), 'Model is broken!')
+
6856 if (((this._buffer.offset + this.fbeOffset + 4 + fbeBytesSize) > this._buffer.size)) {
+
6857 return 4
+
6858 }
+
6859
+
6860 this.writeUInt32(this.fbeOffset, fbeBytesSize)
+
6861 this.writeBytes(this.fbeOffset + 4, value)
+
6862 return 4 + fbeBytesSize
+
6863 }
+
6864}
+
6865
+
6866exports.FinalModelBytes = FinalModelBytes
+
6867)CODE";
+
6868
+
6869 // Prepare code template
+
6870 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
6871
+
6872 Write(code);
+
6873}
+
6874
+
6875void GeneratorJavaScript::GenerateFBEFinalModelString()
+
6876{
+
6877 std::string code = R"CODE(
+
6881class FinalModelString extends FinalModel {
+
6888 fbeAllocationSize (value) {
+
6889 return 4 + 3 * (value.length + 1)
+
6890 }
+
6891
+
6897 verify () {
+
6898 if ((this._buffer.offset + this.fbeOffset + 4) > this._buffer.size) {
+
6899 return Number.MAX_SAFE_INTEGER
+
6900 }
+
6901
+
6902 let fbeStringSize = this.readUInt32(this.fbeOffset)
+
6903 if ((this._buffer.offset + this.fbeOffset + 4 + fbeStringSize) > this._buffer.size) {
+
6904 return Number.MAX_SAFE_INTEGER
+
6905 }
+
6906
+
6907 return 4 + fbeStringSize
+
6908 }
+
6909
+
6915 get () {
+
6916 if ((this._buffer.offset + this.fbeOffset + 4) > this._buffer.size) {
+
6917 return { value: '', size: 0 }
+
6918 }
+
6919
+
6920 let fbeStringSize = this.readUInt32(this.fbeOffset)
+
6921 console.assert(((this._buffer.offset + this.fbeOffset + 4 + fbeStringSize) <= this._buffer.size), 'Model is broken!')
+
6922 if ((this._buffer.offset + this.fbeOffset + 4 + fbeStringSize) > this._buffer.size) {
+
6923 return { value: '', size: 4 }
+
6924 }
+
6925
+
6926 return { value: this.readString(this.fbeOffset + 4, fbeStringSize), size: (4 + fbeStringSize) }
+
6927 }
+
6928
+
6935 set (value) {
+
6936 console.assert(((this._buffer.offset + this.fbeOffset + 4) <= this._buffer.size), 'Model is broken!')
+
6937 if ((this._buffer.offset + this.fbeOffset + 4) > this._buffer.size) {
+
6938 return 0
+
6939 }
+
6940
+
6941 let fbeStringSize = utf8count(value)
+
6942 console.assert(((this._buffer.offset + this.fbeOffset + 4 + fbeStringSize) <= this._buffer.size), 'Model is broken!')
+
6943 if ((this._buffer.offset + this.fbeOffset + 4 + fbeStringSize) > this._buffer.size) {
+
6944 return 4
+
6945 }
+
6946
+
6947 this.writeUInt32(this.fbeOffset, fbeStringSize)
+
6948 this.writeString(this.fbeOffset + 4, value, fbeStringSize)
+
6949 return 4 + fbeStringSize
+
6950 }
+
6951}
+
6952
+
6953exports.FinalModelString = FinalModelString
+
6954)CODE";
+
6955
+
6956 // Prepare code template
+
6957 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
6958
+
6959 Write(code);
+
6960}
+
6961
+
6962void GeneratorJavaScript::GenerateFBEFinalModelOptional()
+
6963{
+
6964 std::string code = R"CODE(
+
6968class FinalModelOptional extends FinalModel {
+
6976 constructor (model, buffer, offset) {
+
6977 super(buffer, offset)
+
6978 this._model = model
+
6979 this._model.fbeOffset = 0
+
6980 }
+
6981
+
6988 fbeAllocationSize (optional) {
+
6989 return 1 + ((optional != null) ? this.value.fbeAllocationSize(optional) : 0)
+
6990 }
+
6991
+
6997 get hasValue () {
+
6998 if ((this._buffer.offset + this.fbeOffset + 1) > this._buffer.size) {
+
6999 return false
+
7000 }
+
7001
+
7002 let fbeHasValue = this.readUInt8(this.fbeOffset)
+
7003 return fbeHasValue !== 0
+
7004 }
+
7005
+
7011 get value () {
+
7012 return this._model
+
7013 }
+
7014
+
7020 verify () {
+
7021 if ((this._buffer.offset + this.fbeOffset + 1) > this._buffer.size) {
+
7022 return Number.MAX_SAFE_INTEGER
+
7023 }
+
7024
+
7025 let fbeHasValue = this.readUInt8(this.fbeOffset)
+
7026 if (fbeHasValue === 0) {
+
7027 return 1
+
7028 }
+
7029
+
7030 this._buffer.shift(this.fbeOffset + 1)
+
7031 let fbeResult = this.value.verify()
+
7032 this._buffer.unshift(this.fbeOffset + 1)
+
7033 return 1 + fbeResult
+
7034 }
+
7035
+
7041 get () {
+
7042 console.assert(((this._buffer.offset + this.fbeOffset + 1) <= this._buffer.size), 'Model is broken!')
+
7043 if ((this._buffer.offset + this.fbeOffset + 1) > this._buffer.size) {
+
7044 return { value: undefined, size: 0 }
+
7045 }
+
7046
+
7047 if (!this.hasValue) {
+
7048 return { value: undefined, size: 1 }
+
7049 }
+
7050
+
7051 this._buffer.shift(this.fbeOffset + 1)
+
7052 let optional = this.value.get()
+
7053 this._buffer.unshift(this.fbeOffset + 1)
+
7054 return { value: optional.value, size: (1 + optional.size) }
+
7055 }
+
7056
+
7063 set (optional) {
+
7064 console.assert(((this._buffer.offset + this.fbeOffset + 1) <= this._buffer.size), 'Model is broken!')
+
7065 if ((this._buffer.offset + this.fbeOffset + 1) > this._buffer.size) {
+
7066 return 0
+
7067 }
+
7068
+
7069 let hasValue = (optional != null)
+
7070 this.writeUInt8(this.fbeOffset, (hasValue ? 1 : 0))
+
7071 if (!hasValue) {
+
7072 return 1
+
7073 }
+
7074
+
7075 this._buffer.shift(this.fbeOffset + 1)
+
7076 let size = this.value.set(optional)
+
7077 this._buffer.unshift(this.fbeOffset + 1)
+
7078 return 1 + size
+
7079 }
+
7080}
+
7081
+
7082exports.FinalModelOptional = FinalModelOptional
+
7083)CODE";
+
7084
+
7085 // Prepare code template
+
7086 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
7087
+
7088 Write(code);
+
7089}
+
7090
+
7091void GeneratorJavaScript::GenerateFBEFinalModelArray()
+
7092{
+
7093 std::string code = R"CODE(
+
7097class FinalModelArray extends FinalModel {
+
7106 constructor (model, buffer, offset, size) {
+
7107 super(buffer, offset)
+
7108 this._model = model
+
7109 this._size = size
+
7110 }
+
7111
+
7118 fbeAllocationSize (values) {
+
7119 let size = 0
+
7120 for (let i = 0; i < Math.min(values.length, this._size); i++) {
+
7121 size += this._model.fbeAllocationSize(values[i])
+
7122 }
+
7123 return size
+
7124 }
+
7125
+
7131 verify () {
+
7132 if ((this._buffer.offset + this.fbeOffset) > this._buffer.size) {
+
7133 return Number.MAX_SAFE_INTEGER
+
7134 }
+
7135
+
7136 let size = 0
+
7137 this._model.fbeOffset = this.fbeOffset
+
7138 for (let i = 0; i < this._size; i++) {
+
7139 let offset = this._model.verify()
+
7140 if (offset === Number.MAX_SAFE_INTEGER) {
+
7141 return Number.MAX_SAFE_INTEGER
+
7142 }
+
7143 this._model.fbeShift(offset)
+
7144 size += offset
+
7145 }
+
7146 return size
+
7147 }
+
7148
+
7155 get (values = []) {
+
7156 values.length = 0
+
7157
+
7158 console.assert(((this._buffer.offset + this.fbeOffset) <= this._buffer.size), 'Model is broken!')
+
7159 if ((this._buffer.offset + this.fbeOffset) > this._buffer.size) {
+
7160 return { value: values, size: 0 }
+
7161 }
+
7162
+
7163 let size = 0
+
7164 this._model.fbeOffset = this.fbeOffset
+
7165 for (let i = 0; i < this._size; i++) {
+
7166 let value = this._model.get()
+
7167 values.push(value.value)
+
7168 this._model.fbeShift(value.size)
+
7169 size += value.size
+
7170 }
+
7171 return { value: values, size: size }
+
7172 }
+
7173
+
7180 set (values) {
+
7181 console.assert(((this._buffer.offset + this.fbeOffset) <= this._buffer.size), 'Model is broken!')
+
7182 if ((this._buffer.offset + this.fbeOffset) > this._buffer.size) {
+
7183 return 0
+
7184 }
+
7185
+
7186 let size = 0
+
7187 this._model.fbeOffset = this.fbeOffset
+
7188 for (let i = 0; i < Math.min(values.length, this._size); i++) {
+
7189 let offset = this._model.set(values[i])
+
7190 this._model.fbeShift(offset)
+
7191 size += offset
+
7192 }
+
7193 return size
+
7194 }
+
7195}
+
7196
+
7197exports.FinalModelArray = FinalModelArray
+
7198)CODE";
+
7199
+
7200 // Prepare code template
+
7201 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
7202
+
7203 Write(code);
+
7204}
+
7205
+
7206void GeneratorJavaScript::GenerateFBEFinalModelVector()
+
7207{
+
7208 std::string code = R"CODE(
+
7212class FinalModelVector extends FinalModel {
+
7220 constructor (model, buffer, offset) {
+
7221 super(buffer, offset)
+
7222 this._model = model
+
7223 }
+
7224
+
7231 fbeAllocationSize (values) {
+
7232 let size = 0
+
7233 for (let value of values) {
+
7234 size += this._model.fbeAllocationSize(value)
+
7235 }
+
7236 return size
+
7237 }
+
7238
+
7244 verify () {
+
7245 if ((this._buffer.offset + this.fbeOffset + 4) > this._buffer.size) {
+
7246 return Number.MAX_SAFE_INTEGER
+
7247 }
+
7248
+
7249 let fbeVectorSize = this.readUInt32(this.fbeOffset)
+
7250
+
7251 let size = 4
+
7252 this._model.fbeOffset = this.fbeOffset + 4
+
7253 for (let i = 0; i < fbeVectorSize; i++) {
+
7254 let offset = this._model.verify()
+
7255 if (offset === Number.MAX_SAFE_INTEGER) {
+
7256 return Number.MAX_SAFE_INTEGER
+
7257 }
+
7258 this._model.fbeShift(offset)
+
7259 size += offset
+
7260 }
+
7261 return size
+
7262 }
+
7263
+
7270 get (values = []) {
+
7271 values.length = 0
+
7272
+
7273 console.assert(((this._buffer.offset + this.fbeOffset + 4) <= this._buffer.size), 'Model is broken!')
+
7274 if ((this._buffer.offset + this.fbeOffset + 4) > this._buffer.size) {
+
7275 return { value: values, size: 0 }
+
7276 }
+
7277
+
7278 let fbeVectorSize = this.readUInt32(this.fbeOffset)
+
7279 if (fbeVectorSize === 0) {
+
7280 return { value: values, size: 4 }
+
7281 }
+
7282
+
7283 let size = 4
+
7284 this._model.fbeOffset = this.fbeOffset + 4
+
7285 for (let i = 0; i < fbeVectorSize; i++) {
+
7286 let value = this._model.get()
+
7287 values.push(value.value)
+
7288 this._model.fbeShift(value.size)
+
7289 size += value.size
+
7290 }
+
7291 return { value: values, size: size }
+
7292 }
+
7293
+
7300 set (values) {
+
7301 console.assert(((this._buffer.offset + this.fbeOffset + 4) <= this._buffer.size), 'Model is broken!')
+
7302 if ((this._buffer.offset + this.fbeOffset + 4) > this._buffer.size) {
+
7303 return 0
+
7304 }
+
7305
+
7306 this.writeUInt32(this.fbeOffset, values.length)
+
7307
+
7308 let size = 4
+
7309 this._model.fbeOffset = this.fbeOffset + 4
+
7310 for (let value of values) {
+
7311 let offset = this._model.set(value)
+
7312 this._model.fbeShift(offset)
+
7313 size += offset
+
7314 }
+
7315 return size
+
7316 }
+
7317}
+
7318
+
7319exports.FinalModelVector = FinalModelVector
+
7320)CODE";
+
7321
+
7322 // Prepare code template
+
7323 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
7324
+
7325 Write(code);
+
7326}
+
7327
+
7328void GeneratorJavaScript::GenerateFBEFinalModelSet()
+
7329{
+
7330 std::string code = R"CODE(
+
7334class FinalModelSet extends FinalModel {
+
7342 constructor (model, buffer, offset) {
+
7343 super(buffer, offset)
+
7344 this._model = model
+
7345 }
+
7346
+
7353 fbeAllocationSize (values) {
+
7354 let size = 0
+
7355 for (let value of values) {
+
7356 size += this._model.fbeAllocationSize(value)
+
7357 }
+
7358 return size
+
7359 }
+
7360
+
7366 verify () {
+
7367 if ((this._buffer.offset + this.fbeOffset + 4) > this._buffer.size) {
+
7368 return Number.MAX_SAFE_INTEGER
+
7369 }
+
7370
+
7371 let fbeSetSize = this.readUInt32(this.fbeOffset)
+
7372
+
7373 let size = 4
+
7374 this._model.fbeOffset = this.fbeOffset + 4
+
7375 for (let i = 0; i < fbeSetSize; i++) {
+
7376 let offset = this._model.verify()
+
7377 if (offset === Number.MAX_SAFE_INTEGER) {
+
7378 return Number.MAX_SAFE_INTEGER
+
7379 }
+
7380 this._model.fbeShift(offset)
+
7381 size += offset
+
7382 }
+
7383 return size
+
7384 }
+
7385
+
7392 get (values = new Set()) {
+
7393 values.clear()
+
7394
+
7395 console.assert(((this._buffer.offset + this.fbeOffset + 4) <= this._buffer.size), 'Model is broken!')
+
7396 if ((this._buffer.offset + this.fbeOffset + 4) > this._buffer.size) {
+
7397 return { value: values, size: 0 }
+
7398 }
+
7399
+
7400 let fbeSetSize = this.readUInt32(this.fbeOffset)
+
7401 if (fbeSetSize === 0) {
+
7402 return { value: values, size: 4 }
+
7403 }
+
7404
+
7405 let size = 4
+
7406 this._model.fbeOffset = this.fbeOffset + 4
+
7407 for (let i = 0; i < fbeSetSize; i++) {
+
7408 let value = this._model.get()
+
7409 values.add(value.value)
+
7410 this._model.fbeShift(value.size)
+
7411 size += value.size
+
7412 }
+
7413 return { value: values, size: size }
+
7414 }
+
7415
+
7422 set (values) {
+
7423 console.assert(((this._buffer.offset + this.fbeOffset + 4) <= this._buffer.size), 'Model is broken!')
+
7424 if ((this._buffer.offset + this.fbeOffset + 4) > this._buffer.size) {
+
7425 return 0
+
7426 }
+
7427
+
7428 this.writeUInt32(this.fbeOffset, values.size)
+
7429
+
7430 let size = 4
+
7431 this._model.fbeOffset = this.fbeOffset + 4
+
7432 for (let value of values) {
+
7433 let offset = this._model.set(value)
+
7434 this._model.fbeShift(offset)
+
7435 size += offset
+
7436 }
+
7437 return size
+
7438 }
+
7439}
+
7440
+
7441exports.FinalModelSet = FinalModelSet
+
7442)CODE";
+
7443
+
7444 // Prepare code template
+
7445 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
7446
+
7447 Write(code);
+
7448}
+
7449
+
7450void GeneratorJavaScript::GenerateFBEFinalModelMap()
+
7451{
+
7452 std::string code = R"CODE(
+
7456class FinalModelMap extends FinalModel {
+
7465 constructor (modelKey, modelValue, buffer, offset) {
+
7466 super(buffer, offset)
+
7467 this._modelKey = modelKey
+
7468 this._modelValue = modelValue
+
7469 }
+
7470
+
7477 fbeAllocationSize (values) {
+
7478 let size = 0
+
7479 for (let [key, value] of values) {
+
7480 size += this._modelKey.fbeAllocationSize(key)
+
7481 size += this._modelValue.fbeAllocationSize(value)
+
7482 }
+
7483 return size
+
7484 }
+
7485
+
7491 verify () {
+
7492 if ((this._buffer.offset + this.fbeOffset + 4) > this._buffer.size) {
+
7493 return Number.MAX_SAFE_INTEGER
+
7494 }
+
7495
+
7496 let fbeMapSize = this.readUInt32(this.fbeOffset)
+
7497
+
7498 let size = 4
+
7499 this._modelKey.fbeOffset = this.fbeOffset + 4
+
7500 this._modelValue.fbeOffset = this.fbeOffset + 4
+
7501 for (let i = 0; i < fbeMapSize; i++) {
+
7502 let offsetKey = this._modelKey.verify()
+
7503 if (offsetKey === Number.MAX_SAFE_INTEGER) {
+
7504 return Number.MAX_SAFE_INTEGER
+
7505 }
+
7506 this._modelKey.fbeShift(offsetKey)
+
7507 this._modelValue.fbeShift(offsetKey)
+
7508 size += offsetKey
+
7509 let offsetValue = this._modelValue.verify()
+
7510 if (offsetValue === Number.MAX_SAFE_INTEGER) {
+
7511 return Number.MAX_SAFE_INTEGER
+
7512 }
+
7513 this._modelKey.fbeShift(offsetValue)
+
7514 this._modelValue.fbeShift(offsetValue)
+
7515 size += offsetValue
+
7516 }
+
7517 return size
+
7518 }
+
7519
+
7526 get (values = new Map()) {
+
7527 values.clear()
+
7528
+
7529 console.assert(((this._buffer.offset + this.fbeOffset + 4) <= this._buffer.size), 'Model is broken!')
+
7530 if ((this._buffer.offset + this.fbeOffset + 4) > this._buffer.size) {
+
7531 return { value: values, size: 0 }
+
7532 }
+
7533
+
7534 let fbeMapSize = this.readUInt32(this.fbeOffset)
+
7535 if (fbeMapSize === 0) {
+
7536 return { value: values, size: 4 }
+
7537 }
+
7538
+
7539 let size = 4
+
7540 this._modelKey.fbeOffset = this.fbeOffset + 4
+
7541 this._modelValue.fbeOffset = this.fbeOffset + 4
+
7542 for (let i = 0; i < fbeMapSize; i++) {
+
7543 let key = this._modelKey.get()
+
7544 this._modelKey.fbeShift(key.size)
+
7545 this._modelValue.fbeShift(key.size)
+
7546 size += key.size
+
7547 let value = this._modelValue.get()
+
7548 this._modelKey.fbeShift(value.size)
+
7549 this._modelValue.fbeShift(value.size)
+
7550 size += value.size
+
7551 values.set(key.value, value.value)
+
7552 }
+
7553 return { value: values, size: size }
+
7554 }
+
7555
+
7562 set (values) {
+
7563 console.assert(((this._buffer.offset + this.fbeOffset + 4) <= this._buffer.size), 'Model is broken!')
+
7564 if ((this._buffer.offset + this.fbeOffset + 4) > this._buffer.size) {
+
7565 return 0
+
7566 }
+
7567
+
7568 this.writeUInt32(this.fbeOffset, values.size)
+
7569
+
7570 let size = 4
+
7571 this._modelKey.fbeOffset = this.fbeOffset + 4
+
7572 this._modelValue.fbeOffset = this.fbeOffset + 4
+
7573 for (let [key, value] of values) {
+
7574 let offsetKey = this._modelKey.set(key)
+
7575 this._modelKey.fbeShift(offsetKey)
+
7576 this._modelValue.fbeShift(offsetKey)
+
7577 size += offsetKey
+
7578 let offsetValue = this._modelValue.set(value)
+
7579 this._modelKey.fbeShift(offsetValue)
+
7580 this._modelValue.fbeShift(offsetValue)
+
7581 size += offsetValue
+
7582 }
+
7583 return size
+
7584 }
+
7585}
+
7586
+
7587exports.FinalModelMap = FinalModelMap
+
7588)CODE";
+
7589
+
7590 // Prepare code template
+
7591 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
7592
+
7593 Write(code);
+
7594}
+
7595
+
7596void GeneratorJavaScript::GenerateFBESender()
+
7597{
+
7598 std::string code = R"CODE(
+
7602class Sender {
+
7609 constructor (buffer = new WriteBuffer(), final = false) {
+
7610 this._buffer = buffer
+
7611 this._logging = false
+
7612 this._final = final
+
7613 }
+
7614
+
7620 get buffer () {
+
7621 return this._buffer
+
7622 }
+
7623
+
7629 get final () {
+
7630 return this._final
+
7631 }
+
7632
+
7638 get logging () {
+
7639 return this._logging
+
7640 }
+
7641
+
7647 set logging (logging) {
+
7648 this._logging = logging
+
7649 }
+
7650
+
7655 reset () {
+
7656 this._buffer.reset()
+
7657 }
+
7658
+
7667 sendSerialized (serialized) {
+
7668 console.assert((serialized > 0), 'Invalid size of the serialized buffer!')
+
7669 if (serialized <= 0) {
+
7670 return 0
+
7671 }
+
7672
+
7673 // Shift the send buffer
+
7674 this._buffer.shift(serialized)
+
7675
+
7676 // Send the value
+
7677 let sent = this.onSend(this._buffer.buffer, 0, this._buffer.size)
+
7678 this._buffer.remove(0, sent)
+
7679 return sent
+
7680 }
+
7681
+
7689 onSend (buffer, offset, size) {
+
7690 console.assert(true, 'Abstract method call!')
+
7691 debugger // eslint-disable-line
+
7692 return 0
+
7693 }
+
7694
+
7700 onSendLog (message) {}
+
7701
+
7707 set onSendHandler (handler) { // eslint-disable-line
+
7708 this.onSend = handler
+
7709 }
+
7710
+
7716 set onSendLogHandler (handler) { // eslint-disable-line
+
7717 this.onSendLog = handler
+
7718 }
+
7719}
+
7720
+
7721exports.Sender = Sender
+
7722)CODE";
+
7723
+
7724 // Prepare code template
+
7725 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
7726
+
7727 Write(code);
+
7728}
+
7729
+
7730void GeneratorJavaScript::GenerateFBEReceiver()
+
7731{
+
7732 std::string code = R"CODE(
+
7736class Receiver {
+
7743 constructor (buffer = new WriteBuffer(), final = false) {
+
7744 this._buffer = buffer
+
7745 this._logging = false
+
7746 this._final = final
+
7747 }
+
7748
+
7754 get buffer () {
+
7755 return this._buffer
+
7756 }
+
7757
+
7763 get final () {
+
7764 return this._final
+
7765 }
+
7766
+
7772 get logging () {
+
7773 return this._logging
+
7774 }
+
7775
+
7781 set logging (logging) {
+
7782 this._logging = logging
+
7783 }
+
7784
+
7789 reset () {
+
7790 this._buffer.reset()
+
7791 }
+
7792
+
7800 receive (buffer, offset = 0, size = undefined) {
+
7801 if (size == null) {
+
7802 size = buffer.length
+
7803 }
+
7804
+
7805 console.assert(((offset + size) <= buffer.length), 'Invalid offset & size!')
+
7806 if ((offset + size) > buffer.length) {
+
7807 throw new Error('Invalid offset & size!')
+
7808 }
+
7809
+
7810 if (size === 0) {
+
7811 return
+
7812 }
+
7813
+
7814 if ((buffer instanceof ReadBuffer) || (buffer instanceof WriteBuffer)) {
+
7815 buffer = buffer.buffer
+
7816 }
+
7817
+
7818 // Storage buffer
+
7819 let offset0 = this._buffer.offset
+
7820 let offset1 = this._buffer.size
+
7821 let size1 = this._buffer.size
+
7822
+
7823 // Receive buffer
+
7824 let offset2 = 0
+
7825 let size2 = size
+
7826
+
7827 // While receive buffer is available to handle...
+
7828 while (offset2 < size2) {
+
7829 let messageBuffer = null
+
7830 let messageOffset = 0
+
7831 let messageSize = 0
+
7832
+
7833 // Try to receive message size
+
7834 let messageSizeCopied = false
+
7835 let messageSizeFound = false
+
7836 while (!messageSizeFound) {
+
7837 // Look into the storage buffer
+
7838 if (offset0 < size1) {
+
7839 let count = Math.min(size1 - offset0, 4)
+
7840 if (count === 4) {
+
7841 messageSizeCopied = true
+
7842 messageSizeFound = true
+
7843 messageSize = Receiver.readUInt32(this._buffer.buffer, this._buffer.offset + offset0)
+
7844 offset0 += 4
+
7845 break
+
7846 } else {
+
7847 // Fill remaining data from the receive buffer
+
7848 if (offset2 < size2) {
+
7849 count = Math.min(size2 - offset2, 4 - count)
+
7850
+
7851 // Allocate and refresh the storage buffer
+
7852 this._buffer.allocate(count)
+
7853 size1 += count
+
7854
+
7855 for (let i = 0; i < count; i++) {
+
7856 this._buffer.buffer[offset1 + i] = buffer[offset + offset2 + i]
+
7857 }
+
7858 offset1 += count
+
7859 offset2 += count
+
7860 continue
+
7861 } else {
+
7862 break
+
7863 }
+
7864 }
+
7865 }
+
7866
+
7867 // Look into the receive buffer
+
7868 if (offset2 < size2) {
+
7869 let count = Math.min(size2 - offset2, 4)
+
7870 if (count === 4) {
+
7871 messageSizeFound = true
+
7872 messageSize = Receiver.readUInt32(buffer, offset + offset2)
+
7873 offset2 += 4
+
7874 break
+
7875 } else {
+
7876 // Allocate and refresh the storage buffer
+
7877 this._buffer.allocate(count)
+
7878 size1 += count
+
7879
+
7880 for (let i = 0; i < count; i++) {
+
7881 this._buffer.buffer[offset1 + i] = buffer[offset + offset2 + i]
+
7882 }
+
7883 offset1 += count
+
7884 offset2 += count
+
7885 // noinspection UnnecessaryContinueJS
+
7886 continue
+
7887 }
+
7888 } else {
+
7889 break
+
7890 }
+
7891 }
+
7892
+
7893 if (!messageSizeFound) {
+
7894 return
+
7895 }
+
7896
+
7897 // Check the message full size
+
7898 let minSize = this._final ? (4 + 4) : (4 + 4 + 4 + 4)
+
7899 console.assert((messageSize >= minSize), 'Invalid receive data!')
+
7900 if (messageSize < minSize) {
+
7901 return
+
7902 }
+
7903
+
7904 // Try to receive message body
+
7905 let messageFound = false
+
7906 while (!messageFound) {
+
7907 // Look into the storage buffer
+
7908 if (offset0 < size1) {
+
7909 let count = Math.min(size1 - offset0, messageSize - 4)
+
7910 if (count === (messageSize - 4)) {
+
7911 messageFound = true
+
7912 messageBuffer = this._buffer.buffer
+
7913 messageOffset = offset0 - 4
+
7914 offset0 += messageSize - 4
+
7915 break
+
7916 } else {
+
7917 // Fill remaining data from the receive buffer
+
7918 if (offset2 < size2) {
+
7919 // Copy message size into the storage buffer
+
7920 if (!messageSizeCopied) {
+
7921 // Allocate and refresh the storage buffer
+
7922 this._buffer.allocate(4)
+
7923 size1 += 4
+
7924
+
7925 Receiver.writeUInt32(this._buffer.buffer, this._buffer.offset + offset0, messageSize)
+
7926 offset0 += 4
+
7927 offset1 += 4
+
7928
+
7929 messageSizeCopied = true
+
7930 }
+
7931
+
7932 count = Math.min(size2 - offset2, messageSize - 4 - count)
+
7933
+
7934 // Allocate and refresh the storage buffer
+
7935 this._buffer.allocate(count)
+
7936 size1 += count
+
7937
+
7938 for (let i = 0; i < count; i++) {
+
7939 this._buffer.buffer[offset1 + i] = buffer[offset + offset2 + i]
+
7940 }
+
7941 offset1 += count
+
7942 offset2 += count
+
7943 continue
+
7944 } else {
+
7945 break
+
7946 }
+
7947 }
+
7948 }
+
7949
+
7950 // Look into the receive buffer
+
7951 if (offset2 < size2) {
+
7952 let count = Math.min(size2 - offset2, messageSize - 4)
+
7953 if (!messageSizeCopied && (count === (messageSize - 4))) {
+
7954 messageFound = true
+
7955 messageBuffer = buffer
+
7956 messageOffset = offset + offset2 - 4
+
7957 offset2 += messageSize - 4
+
7958 break
+
7959 } else {
+
7960 // Copy message size into the storage buffer
+
7961 if (!messageSizeCopied) {
+
7962 // Allocate and refresh the storage buffer
+
7963 this._buffer.allocate(4)
+
7964 size1 += 4
+
7965
+
7966 Receiver.writeUInt32(this._buffer.buffer, this._buffer.offset + offset0, messageSize)
+
7967 offset0 += 4
+
7968 offset1 += 4
+
7969
+
7970 messageSizeCopied = true
+
7971 }
+
7972
+
7973 // Allocate and refresh the storage buffer
+
7974 this._buffer.allocate(count)
+
7975 size1 += count
+
7976
+
7977 for (let i = 0; i < count; i++) {
+
7978 this._buffer.buffer[offset1 + i] = buffer[offset + offset2 + i]
+
7979 }
+
7980 offset1 += count
+
7981 offset2 += count
+
7982 // noinspection UnnecessaryContinueJS
+
7983 continue
+
7984 }
+
7985 } else {
+
7986 break
+
7987 }
+
7988 }
+
7989
+
7990 if (!messageFound) {
+
7991 // Copy message size into the storage buffer
+
7992 if (!messageSizeCopied) {
+
7993 // Allocate and refresh the storage buffer
+
7994 this._buffer.allocate(4)
+
7995 size1 += 4
+
7996
+
7997 Receiver.writeUInt32(this._buffer.buffer, this._buffer.offset + offset0, messageSize)
+
7998 offset0 += 4
+
7999 offset1 += 4
+
8000
+
8001 messageSizeCopied = true
+
8002 }
+
8003 return
+
8004 }
+
8005
+
8006 // noinspection JSUnusedLocalSymbols
+
8007 let fbeStructSize // eslint-disable-line
+
8008 let fbeStructType
+
8009
+
8010 // Read the message parameters
+
8011 if (this._final) {
+
8012 fbeStructSize = Receiver.readUInt32(messageBuffer, messageOffset)
+
8013 fbeStructType = Receiver.readUInt32(messageBuffer, messageOffset + 4)
+
8014 } else {
+
8015 let fbeStructOffset = Receiver.readUInt32(messageBuffer, messageOffset + 4)
+
8016 // noinspection JSUnusedLocalSymbols
+
8017 fbeStructSize = Receiver.readUInt32(messageBuffer, messageOffset + fbeStructOffset) // eslint-disable-line
+
8018 fbeStructType = Receiver.readUInt32(messageBuffer, messageOffset + fbeStructOffset + 4)
+
8019 }
+
8020
+
8021 // Handle the message
+
8022 this.onReceive(fbeStructType, messageBuffer, messageOffset, messageSize)
+
8023
+
8024 // Reset the storage buffer
+
8025 this._buffer.reset()
+
8026
+
8027 // Refresh the storage buffer
+
8028 offset0 = this._buffer.offset
+
8029 offset1 = this._buffer.size
+
8030 size1 = this._buffer.size
+
8031 }
+
8032 }
+
8033
+
8043 onReceive (type, buffer, offset, size) {
+
8044 console.assert(true, 'Abstract method call!')
+
8045 debugger // eslint-disable-line
+
8046 return false
+
8047 }
+
8048
+
8054 onReceiveLog (message) {}
+
8055
+
8061 set onReceiveLogHandler (handler) { // eslint-disable-line
+
8062 this.onReceiveLog = handler
+
8063 }
+
8064
+
8065 // Buffer I/O methods
+
8066
+
8073 static checkOffset (buffer, offset, size) {
+
8074 if (((offset % 1) !== 0) || (offset < 0)) {
+
8075 throw new RangeError('Invalid offset!')
+
8076 }
+
8077 if ((offset + size) > buffer.length) {
+
8078 throw new RangeError('Out of bounds!')
+
8079 }
+
8080 }
+
8081
+
8091 static checkValue (buffer, offset, size, value, min, max) {
+
8092 this.checkOffset(buffer, offset, size)
+
8093 if ((value < min) || (value > max)) {
+
8094 throw new RangeError('Value is out of bounds!')
+
8095 }
+
8096 }
+
8097
+
8105 static readUInt32 (buffer, offset) {
+
8106 offset = offset >>> 0
+
8107 Receiver.checkOffset(buffer, offset, 4)
+
8108 return (
+
8109 (buffer[offset + 0] << 0) |
+
8110 (buffer[offset + 1] << 8) |
+
8111 (buffer[offset + 2] << 16)) +
+
8112 (buffer[offset + 3] * 0x1000000)
+
8113 }
+
8114
+
8122 static writeUInt32 (buffer, offset, value) {
+
8123 value = +value
+
8124 Receiver.checkValue(buffer, offset, 4, value, 0, 0xFFFFFFFF)
+
8125 buffer[offset + 3] = (value >>> 24)
+
8126 buffer[offset + 2] = (value >>> 16)
+
8127 buffer[offset + 1] = (value >>> 8)
+
8128 buffer[offset + 0] = (value & 0xFF)
+
8129 }
+
8130}
+
8131
+
8132exports.Receiver = Receiver
+
8133)CODE";
+
8134
+
8135 // Prepare code template
+
8136 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
8137
+
8138 Write(code);
+
8139}
+
8140
+
8141void GeneratorJavaScript::GenerateFBEClient()
+
8142{
+
8143 std::string code = R"CODE(
+
8147class Client {
+
8155 constructor (sendBuffer = new WriteBuffer(), receiveBuffer = new WriteBuffer(), final = false) {
+
8156 this._sendBuffer = sendBuffer
+
8157 this._receiveBuffer = receiveBuffer
+
8158 this._logging = false
+
8159 this._final = final
+
8160 }
+
8161
+
8167 get sendBuffer () {
+
8168 return this._sendBuffer
+
8169 }
+
8170
+
8176 get receiveBuffer () {
+
8177 return this._receiveBuffer
+
8178 }
+
8179
+
8185 get final () {
+
8186 return this._final
+
8187 }
+
8188
+
8194 get logging () {
+
8195 return this._logging
+
8196 }
+
8197
+
8203 set logging (logging) {
+
8204 this._logging = logging
+
8205 }
+
8206
+
8211 reset () {
+
8212 this._sendBuffer.reset()
+
8213 this._receiveBuffer.reset()
+
8214 }
+
8215
+
8224 sendSerialized (serialized) {
+
8225 console.assert((serialized > 0), 'Invalid size of the serialized buffer!')
+
8226 if (serialized <= 0) {
+
8227 return 0
+
8228 }
+
8229
+
8230 // Shift the send buffer
+
8231 this._sendBuffer.shift(serialized)
+
8232
+
8233 // Send the value
+
8234 let sent = this.onSend(this._sendBuffer.buffer, 0, this._sendBuffer.size)
+
8235 this._sendBuffer.remove(0, sent)
+
8236 return sent
+
8237 }
+
8238
+
8246 onSend (buffer, offset, size) {
+
8247 console.assert(true, 'Abstract method call!')
+
8248 debugger // eslint-disable-line
+
8249 return 0
+
8250 }
+
8251
+
8257 onSendLog (message) {}
+
8258
+
8264 set onSendHandler (handler) { // eslint-disable-line
+
8265 this.onSend = handler
+
8266 }
+
8267
+
8273 set onSendLogHandler (handler) { // eslint-disable-line
+
8274 this.onSendLog = handler
+
8275 }
+
8276
+
8284 receive (buffer, offset = 0, size = undefined) {
+
8285 if (size == null) {
+
8286 size = buffer.length
+
8287 }
+
8288
+
8289 console.assert(((offset + size) <= buffer.length), 'Invalid offset & size!')
+
8290 if ((offset + size) > buffer.length) {
+
8291 throw new Error('Invalid offset & size!')
+
8292 }
+
8293
+
8294 if (size === 0) {
+
8295 return
+
8296 }
+
8297
+
8298 if ((buffer instanceof ReadBuffer) || (buffer instanceof WriteBuffer)) {
+
8299 buffer = buffer.buffer
+
8300 }
+
8301
+
8302 // Storage buffer
+
8303 let offset0 = this._receiveBuffer.offset
+
8304 let offset1 = this._receiveBuffer.size
+
8305 let size1 = this._receiveBuffer.size
+
8306
+
8307 // Receive buffer
+
8308 let offset2 = 0
+
8309 let size2 = size
+
8310
+
8311 // While receive buffer is available to handle...
+
8312 while (offset2 < size2) {
+
8313 let messageBuffer = null
+
8314 let messageOffset = 0
+
8315 let messageSize = 0
+
8316
+
8317 // Try to receive message size
+
8318 let messageSizeCopied = false
+
8319 let messageSizeFound = false
+
8320 while (!messageSizeFound) {
+
8321 // Look into the storage buffer
+
8322 if (offset0 < size1) {
+
8323 let count = Math.min(size1 - offset0, 4)
+
8324 if (count === 4) {
+
8325 messageSizeCopied = true
+
8326 messageSizeFound = true
+
8327 messageSize = Receiver.readUInt32(this._receiveBuffer.buffer, this._receiveBuffer.offset + offset0)
+
8328 offset0 += 4
+
8329 break
+
8330 } else {
+
8331 // Fill remaining data from the receive buffer
+
8332 if (offset2 < size2) {
+
8333 count = Math.min(size2 - offset2, 4 - count)
+
8334
+
8335 // Allocate and refresh the storage buffer
+
8336 this._receiveBuffer.allocate(count)
+
8337 size1 += count
+
8338
+
8339 for (let i = 0; i < count; i++) {
+
8340 this._receiveBuffer.buffer[offset1 + i] = buffer[offset + offset2 + i]
+
8341 }
+
8342 offset1 += count
+
8343 offset2 += count
+
8344 continue
+
8345 } else {
+
8346 break
+
8347 }
+
8348 }
+
8349 }
+
8350
+
8351 // Look into the receive buffer
+
8352 if (offset2 < size2) {
+
8353 let count = Math.min(size2 - offset2, 4)
+
8354 if (count === 4) {
+
8355 messageSizeFound = true
+
8356 messageSize = Receiver.readUInt32(buffer, offset + offset2)
+
8357 offset2 += 4
+
8358 break
+
8359 } else {
+
8360 // Allocate and refresh the storage buffer
+
8361 this._receiveBuffer.allocate(count)
+
8362 size1 += count
+
8363
+
8364 for (let i = 0; i < count; i++) {
+
8365 this._receiveBuffer.buffer[offset1 + i] = buffer[offset + offset2 + i]
+
8366 }
+
8367 offset1 += count
+
8368 offset2 += count
+
8369 // noinspection UnnecessaryContinueJS
+
8370 continue
+
8371 }
+
8372 } else {
+
8373 break
+
8374 }
+
8375 }
+
8376
+
8377 if (!messageSizeFound) {
+
8378 return
+
8379 }
+
8380
+
8381 // Check the message full size
+
8382 let minSize = this._final ? (4 + 4) : (4 + 4 + 4 + 4)
+
8383 console.assert((messageSize >= minSize), 'Invalid receive data!')
+
8384 if (messageSize < minSize) {
+
8385 return
+
8386 }
+
8387
+
8388 // Try to receive message body
+
8389 let messageFound = false
+
8390 while (!messageFound) {
+
8391 // Look into the storage buffer
+
8392 if (offset0 < size1) {
+
8393 let count = Math.min(size1 - offset0, messageSize - 4)
+
8394 if (count === (messageSize - 4)) {
+
8395 messageFound = true
+
8396 messageBuffer = this._receiveBuffer.buffer
+
8397 messageOffset = offset0 - 4
+
8398 offset0 += messageSize - 4
+
8399 break
+
8400 } else {
+
8401 // Fill remaining data from the receive buffer
+
8402 if (offset2 < size2) {
+
8403 // Copy message size into the storage buffer
+
8404 if (!messageSizeCopied) {
+
8405 // Allocate and refresh the storage buffer
+
8406 this._receiveBuffer.allocate(4)
+
8407 size1 += 4
+
8408
+
8409 Receiver.writeUInt32(this._receiveBuffer.buffer, this._receiveBuffer.offset + offset0, messageSize)
+
8410 offset0 += 4
+
8411 offset1 += 4
+
8412
+
8413 messageSizeCopied = true
+
8414 }
+
8415
+
8416 count = Math.min(size2 - offset2, messageSize - 4 - count)
+
8417
+
8418 // Allocate and refresh the storage buffer
+
8419 this._receiveBuffer.allocate(count)
+
8420 size1 += count
+
8421
+
8422 for (let i = 0; i < count; i++) {
+
8423 this._receiveBuffer.buffer[offset1 + i] = buffer[offset + offset2 + i]
+
8424 }
+
8425 offset1 += count
+
8426 offset2 += count
+
8427 continue
+
8428 } else {
+
8429 break
+
8430 }
+
8431 }
+
8432 }
+
8433
+
8434 // Look into the receive buffer
+
8435 if (offset2 < size2) {
+
8436 let count = Math.min(size2 - offset2, messageSize - 4)
+
8437 if (!messageSizeCopied && (count === (messageSize - 4))) {
+
8438 messageFound = true
+
8439 messageBuffer = buffer
+
8440 messageOffset = offset + offset2 - 4
+
8441 offset2 += messageSize - 4
+
8442 break
+
8443 } else {
+
8444 // Copy message size into the storage buffer
+
8445 if (!messageSizeCopied) {
+
8446 // Allocate and refresh the storage buffer
+
8447 this._receiveBuffer.allocate(4)
+
8448 size1 += 4
+
8449
+
8450 Receiver.writeUInt32(this._receiveBuffer.buffer, this._receiveBuffer.offset + offset0, messageSize)
+
8451 offset0 += 4
+
8452 offset1 += 4
+
8453
+
8454 messageSizeCopied = true
+
8455 }
+
8456
+
8457 // Allocate and refresh the storage buffer
+
8458 this._receiveBuffer.allocate(count)
+
8459 size1 += count
+
8460
+
8461 for (let i = 0; i < count; i++) {
+
8462 this._receiveBuffer.buffer[offset1 + i] = buffer[offset + offset2 + i]
+
8463 }
+
8464 offset1 += count
+
8465 offset2 += count
+
8466 // noinspection UnnecessaryContinueJS
+
8467 continue
+
8468 }
+
8469 } else {
+
8470 break
+
8471 }
+
8472 }
+
8473
+
8474 if (!messageFound) {
+
8475 // Copy message size into the storage buffer
+
8476 if (!messageSizeCopied) {
+
8477 // Allocate and refresh the storage buffer
+
8478 this._receiveBuffer.allocate(4)
+
8479 size1 += 4
+
8480
+
8481 Receiver.writeUInt32(this._receiveBuffer.buffer, this._receiveBuffer.offset + offset0, messageSize)
+
8482 offset0 += 4
+
8483 offset1 += 4
+
8484
+
8485 messageSizeCopied = true
+
8486 }
+
8487 return
+
8488 }
+
8489
+
8490 // noinspection JSUnusedLocalSymbols
+
8491 let fbeStructSize // eslint-disable-line
+
8492 let fbeStructType
+
8493
+
8494 // Read the message parameters
+
8495 if (this._final) {
+
8496 fbeStructSize = Receiver.readUInt32(messageBuffer, messageOffset)
+
8497 fbeStructType = Receiver.readUInt32(messageBuffer, messageOffset + 4)
+
8498 } else {
+
8499 let fbeStructOffset = Receiver.readUInt32(messageBuffer, messageOffset + 4)
+
8500 // noinspection JSUnusedLocalSymbols
+
8501 fbeStructSize = Receiver.readUInt32(messageBuffer, messageOffset + fbeStructOffset) // eslint-disable-line
+
8502 fbeStructType = Receiver.readUInt32(messageBuffer, messageOffset + fbeStructOffset + 4)
+
8503 }
+
8504
+
8505 // Handle the message
+
8506 this.onReceive(fbeStructType, messageBuffer, messageOffset, messageSize)
+
8507
+
8508 // Reset the storage buffer
+
8509 this._receiveBuffer.reset()
+
8510
+
8511 // Refresh the storage buffer
+
8512 offset0 = this._receiveBuffer.offset
+
8513 offset1 = this._receiveBuffer.size
+
8514 size1 = this._receiveBuffer.size
+
8515 }
+
8516 }
+
8517
+
8527 onReceive (type, buffer, offset, size) {
+
8528 console.assert(true, 'Abstract method call!')
+
8529 debugger // eslint-disable-line
+
8530 return false
+
8531 }
+
8532
+
8538 onReceiveLog (message) {}
+
8539
+
8545 set onReceiveLogHandler (handler) { // eslint-disable-line
+
8546 this.onReceiveLog = handler
+
8547 }
+
8548
+
8549 // Buffer I/O methods
+
8550
+
8557 static checkOffset (buffer, offset, size) {
+
8558 if (((offset % 1) !== 0) || (offset < 0)) {
+
8559 throw new RangeError('Invalid offset!')
+
8560 }
+
8561 if ((offset + size) > buffer.length) {
+
8562 throw new RangeError('Out of bounds!')
+
8563 }
+
8564 }
+
8565
+
8575 static checkValue (buffer, offset, size, value, min, max) {
+
8576 this.checkOffset(buffer, offset, size)
+
8577 if ((value < min) || (value > max)) {
+
8578 throw new RangeError('Value is out of bounds!')
+
8579 }
+
8580 }
+
8581
+
8589 static readUInt32 (buffer, offset) {
+
8590 offset = offset >>> 0
+
8591 Receiver.checkOffset(buffer, offset, 4)
+
8592 return (
+
8593 (buffer[offset + 0] << 0) |
+
8594 (buffer[offset + 1] << 8) |
+
8595 (buffer[offset + 2] << 16)) +
+
8596 (buffer[offset + 3] * 0x1000000)
+
8597 }
+
8598
+
8606 static writeUInt32 (buffer, offset, value) {
+
8607 value = +value
+
8608 Receiver.checkValue(buffer, offset, 4, value, 0, 0xFFFFFFFF)
+
8609 buffer[offset + 3] = (value >>> 24)
+
8610 buffer[offset + 2] = (value >>> 16)
+
8611 buffer[offset + 1] = (value >>> 8)
+
8612 buffer[offset + 0] = (value & 0xFF)
+
8613 }
+
8614}
+
8615
+
8616exports.Client = Client
+
8617)CODE";
+
8618
+
8619 // Prepare code template
+
8620 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
8621
+
8622 Write(code);
+
8623}
+
8624
+
8625void GeneratorJavaScript::GenerateFBEJson()
+
8626{
+
8627 std::string code = R"CODE(
+
8633let MapToObject = function (map) {
+
8634 let obj = {}
+
8635 map.forEach((value, key) => { obj[key] = value })
+
8636 return obj
+
8637}
+
8638
+
8639exports.MapToObject = MapToObject
+
8640
+
8646let ObjectToMap = function (obj) {
+
8647 let map = new Map()
+
8648 Object.keys(obj).forEach(key => { map.set(key, obj[key]) })
+
8649 return map
+
8650}
+
8651
+
8652exports.ObjectToMap = ObjectToMap
+
8653)CODE";
+
8654
+
8655 // Prepare code template
+
8656 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
8657
+
8658 Write(code);
+
8659}
+
8660
+
8661void GeneratorJavaScript::GenerateImports(const std::shared_ptr<Package>& p)
+
8662{
+
8663 // Generate common import
+
8664 WriteLine();
+
8665 WriteLineIndent("const util = require('util')");
+
8666 WriteLine();
+
8667 WriteLineIndent("const big = require('./big')");
+
8668 WriteLineIndent("const int64 = require('./int64')");
+
8669 WriteLineIndent("const uuid = require('./uuid')");
+
8670 WriteLine();
+
8671 WriteLineIndent("const Big = big.Big // eslint-disable-line");
+
8672 WriteLineIndent("const Int64 = int64.Int64 // eslint-disable-line");
+
8673 WriteLineIndent("const UInt64 = int64.UInt64 // eslint-disable-line");
+
8674 WriteLineIndent("const UUID = uuid.UUID // eslint-disable-line");
+
8675
+
8676 // Generate FBE import
+
8677 WriteLine();
+
8678 WriteLineIndent("const fbe = require('./fbe')");
+
8679
+
8680 // Generate packages import
+
8681 if (p->import)
+
8682 for (const auto& import : p->import->imports)
+
8683 WriteLineIndent("const " + *import + " = require('./" + *import + "')");
+
8684}
+
8685
+
8686void GeneratorJavaScript::GeneratePackage(const std::shared_ptr<Package>& p)
+
8687{
+
8688 CppCommon::Path output = _output;
+
8689
+
8690 // Create package path
+
8691 CppCommon::Directory::CreateTree(output);
+
8692
+
8693 // Generate common files
+
8694 GenerateBig(output);
+
8695 GenerateInt64(output);
+
8696 GenerateUUID(output);
+
8697 GenerateIEEE754(output);
+
8698 GenerateUTF8(output);
+
8699 GenerateFBE(output);
+
8700
+
8701 // Generate the output file
+
8702 output /= *p->name + ".js";
+
8703 WriteBegin();
+
8704
+
8705 // Generate package header
+
8706 GenerateHeader(CppCommon::Path(_input).filename().string());
+
8707
+
8708 // Generate eslint deflations
+
8709 WriteLine();
+
8710 WriteLineIndent("/* eslint-disable prefer-const,no-loss-of-precision */");
+
8711 WriteLineIndent("'use strict'");
+
8712
+
8713 // Generate package imports
+
8714 GenerateImports(p);
+
8715
+
8716 // Generate namespace
+
8717 if (p->body)
+
8718 {
+
8719 // Generate child enums
+
8720 for (const auto& child_e : p->body->enums)
+
8721 GenerateEnum(child_e);
+
8722
+
8723 // Generate child flags
+
8724 for (const auto& child_f : p->body->flags)
+
8725 GenerateFlags(child_f);
+
8726
+
8727 // Generate child structs
+
8728 for (const auto& child_s : p->body->structs)
+
8729 GenerateStruct(child_s);
+
8730 }
+
8731
+
8732 // Generate protocol
+
8733 if (Proto())
+
8734 {
+
8735 // Generate protocol version
+
8736 GenerateProtocolVersion(p);
+
8737
+
8738 // Generate sender & receiver
+
8739 GenerateSender(p, false);
+
8740 GenerateReceiver(p, false);
+
8741 GenerateProxy(p, false);
+
8742 GenerateClient(p, false);
+
8743 if (Final())
+
8744 {
+
8745 GenerateSender(p, true);
+
8746 GenerateReceiver(p, true);
+
8747 GenerateClient(p, true);
+
8748 }
+
8749 }
+
8750
+
8751 // Generate package footer
+
8752 GenerateFooter();
+
8753
+
8754 // Store the output file
+
8755 WriteEnd();
+
8756 Store(output);
+
8757}
+
8758
+
8759void GeneratorJavaScript::GenerateEnum(const std::shared_ptr<EnumType>& e)
+
8760{
+
8761 // Generate enum begin
+
8762 WriteLine();
+
8763 WriteLineIndent("/**");
+
8764 WriteLineIndent(" * " + *e->name + " enum");
+
8765 WriteLineIndent(" */");
+
8766 WriteLineIndent("class " + *e->name + " {");
+
8767 Indent(1);
+
8768
+
8769 std::string enum_type = (e->base && !e->base->empty()) ? *e->base : "int32";
+
8770
+
8771 // Javascript enums are limited to 32-bit integer numbers
+
8772 if (enum_type == "int64")
+
8773 enum_type = "int32";
+
8774 else if (enum_type == "uint64")
+
8775 enum_type = "uint32";
+
8776
+
8777 // Generate enum constructor
+
8778 WriteLineIndent("/**");
+
8779 WriteLineIndent(" * Initialize enum with a given value");
+
8780 WriteLineIndent(" * @param {" + *e->name + "|number|Int64|UInt64=} value Enum value, defaults is 0");
+
8781 WriteLineIndent(" * @constructor");
+
8782 WriteLineIndent(" */");
+
8783 WriteLineIndent("constructor (value = 0) {");
+
8784 Indent(1);
+
8785 WriteLineIndent("if (value instanceof " + *e->name + ") {");
+
8786 Indent(1);
+
8787 WriteLineIndent("this.value = value.value");
+
8788 Indent(-1);
+
8789 WriteLineIndent("} else {");
+
8790 Indent(1);
+
8791 WriteLineIndent("this.value = value");
+
8792 Indent(-1);
+
8793 WriteLineIndent("}");
+
8794 Indent(-1);
+
8795 WriteLineIndent("}");
+
8796
+
8797 // Generate enum eq() method
+
8798 WriteLine();
+
8799 WriteLineIndent("/**");
+
8800 WriteLineIndent(" * Is this enum equal to other one?");
+
8801 WriteLineIndent(" * @this {!" + *e->name + "}");
+
8802 WriteLineIndent(" * @param {!" + *e->name + "} other Other enum");
+
8803 WriteLineIndent(" * @returns {boolean} Equal result");
+
8804 WriteLineIndent(" */");
+
8805 WriteLineIndent("eq (other) {");
+
8806 Indent(1);
+
8807 WriteLineIndent("if (!(other instanceof " + *e->name + ")) {");
+
8808 Indent(1);
+
8809 WriteLineIndent("throw new TypeError('Instance of " + *e->name + " is required!')");
+
8810 Indent(-1);
+
8811 WriteLineIndent("}");
+
8812 WriteLineIndent("return this.value === other.value");
+
8813 Indent(-1);
+
8814 WriteLineIndent("}");
+
8815
+
8816 // Generate enum valueOf() method
+
8817 WriteLine();
+
8818 WriteLineIndent("/**");
+
8819 WriteLineIndent(" * Get enum value");
+
8820 WriteLineIndent(" * @this {!" + *e->name + "}");
+
8821 WriteLineIndent(" * @returns {!number|!Int64|!UInt64} Enum value");
+
8822 WriteLineIndent(" */");
+
8823 WriteLineIndent("valueOf () {");
+
8824 Indent(1);
+
8825 WriteLineIndent("return this.value");
+
8826 Indent(-1);
+
8827 WriteLineIndent("}");
+
8828
+
8829 // Generate enum toString() method
+
8830 WriteLine();
+
8831 WriteLineIndent("/**");
+
8832 WriteLineIndent(" * Convert enum to string");
+
8833 WriteLineIndent(" * @this {!" + *e->name + "}");
+
8834 WriteLineIndent(" * @returns {!string} Enum value string");
+
8835 WriteLineIndent(" */");
+
8836 WriteLineIndent("toString () {");
+
8837 Indent(1);
+
8838 if (e->body && !e->body->values.empty())
+
8839 {
+
8840 for (auto it = e->body->values.begin(); it != e->body->values.end(); ++it)
+
8841 {
+
8842 WriteLineIndent("if (this.value === " + *e->name + "." + *(*it)->name + ".value) {");
+
8843 Indent(1);
+
8844 WriteLineIndent("return '" + *(*it)->name + "'");
+
8845 Indent(-1);
+
8846 WriteLineIndent("}");
+
8847 }
+
8848 WriteLineIndent("return '<unknown>'");
+
8849 }
+
8850 else
+
8851 WriteLineIndent("return '<empty>'");
+
8852 Indent(-1);
+
8853 WriteLineIndent("}");
+
8854
+
8855 // Generate enum [util.inspect.custom]() method
+
8856 WriteLine();
+
8857 WriteLineIndent("/**");
+
8858 WriteLineIndent(" * Inspect enum");
+
8859 WriteLineIndent(" * @this {!" + *e->name + "}");
+
8860 WriteLineIndent(" * @returns {!string} Enum value string");
+
8861 WriteLineIndent(" */");
+
8862 WriteLineIndent("[util.inspect.custom] () {");
+
8863 Indent(1);
+
8864 WriteLineIndent("return this.toString()");
+
8865 Indent(-1);
+
8866 WriteLineIndent("}");
+
8867
+
8868 // Generate enum toJSON() method
+
8869 WriteLine();
+
8870 WriteLineIndent("/**");
+
8871 WriteLineIndent(" * Convert enum to JSON");
+
8872 WriteLineIndent(" * @this {!" + *e->name + "}");
+
8873 WriteLineIndent(" * @returns {!number} Enum value for JSON");
+
8874 WriteLineIndent(" */");
+
8875 WriteLineIndent("toJSON () {");
+
8876 Indent(1);
+
8877 WriteLineIndent("return this.value");
+
8878 Indent(-1);
+
8879 WriteLineIndent("}");
+
8880
+
8881 // Generate enum fromObject() method
+
8882 WriteLine();
+
8883 WriteLineIndent("/**");
+
8884 WriteLineIndent(" * Create enum from object value");
+
8885 WriteLineIndent(" * @param {!number} other Object value");
+
8886 WriteLineIndent(" * @returns {!" + *e->name + "} Created enum");
+
8887 WriteLineIndent(" */");
+
8888 WriteLineIndent("static fromObject (other) {");
+
8889 Indent(1);
+
8890 WriteLineIndent("return new " + *e->name + "(other)");
+
8891 Indent(-1);
+
8892 WriteLineIndent("}");
+
8893
+
8894 // Generate enum end
+
8895 Indent(-1);
+
8896 WriteLineIndent("}");
+
8897
+
8898 // Generate enum values
+
8899 if (e->body && !e->body->values.empty())
+
8900 {
+
8901 WriteLine();
+
8902 int index = 0;
+
8903 std::string last = ConvertEnumConstant(*e->name, "int32", "0");
+
8904 for (const auto& value : e->body->values)
+
8905 {
+
8906 WriteLineIndent("// noinspection PointlessArithmeticExpressionJS");
+
8907 WriteIndent(*e->name + "." + *value->name + " = new " + *e->name + "(");
+
8908 if (value->value)
+
8909 {
+
8910 if (value->value->constant && !value->value->constant->empty())
+
8911 {
+
8912 index = 0;
+
8913 last = ConvertEnumConstant(*e->name, enum_type, *value->value->constant);
+
8914 Write(last + " + " + std::to_string(index++));
+
8915 }
+
8916 else if (value->value->reference && !value->value->reference->empty())
+
8917 {
+
8918 index = 0;
+
8919 last = ConvertEnumConstant(*e->name, "", *value->value->reference);
+
8920 Write(last);
+
8921 }
+
8922 }
+
8923 else
+
8924 Write(last + " + " + std::to_string(index++));
+
8925 Write(")");
+
8926 WriteLine();
+
8927 }
+
8928 }
+
8929
+
8930 // Generate enum exports
+
8931 WriteLine();
+
8932 WriteLineIndent("exports." + *e->name + " = " + *e->name);
+
8933
+
8934 // Generate enum field model
+
8935 GenerateEnumFieldModel(e);
+
8936
+
8937 // Generate enum final model
+
8938 if (Final())
+
8939 GenerateEnumFinalModel(e);
+
8940}
+
8941
+
8942void GeneratorJavaScript::GenerateEnumFieldModel(const std::shared_ptr<EnumType>& e)
+
8943{
+
8944 std::string code = R"CODE(
+
8948class FieldModel_ENUM_NAME_ extends fbe.FieldModel {
+
8954 get fbeSize () {
+
8955 return _ENUM_SIZE_
+
8956 }
+
8957
+
8964 get (defaults = new _ENUM_NAME_()) {
+
8965 if ((this._buffer.offset + this.fbeOffset + this.fbeSize) > this._buffer.size) {
+
8966 return defaults
+
8967 }
+
8968
+
8969 return new _ENUM_NAME_(this.read_ENUM_TYPE_(this.fbeOffset)_ENUM_READ_SUFFIX_)
+
8970 }
+
8971
+
8977 set (value) {
+
8978 console.assert(((this._buffer.offset + this.fbeOffset + this.fbeSize) <= this._buffer.size), 'Model is broken!')
+
8979 if ((this._buffer.offset + this.fbeOffset + this.fbeSize) > this._buffer.size) {
+
8980 return
+
8981 }
+
8982
+
8983 this.write_ENUM_TYPE_(this.fbeOffset, _ENUM_WRITE_PREFIX_value.value_ENUM_WRITE_SUFFIX_)
+
8984 }
+
8985}
+
8986
+
8987exports.FieldModel_ENUM_NAME_ = FieldModel_ENUM_NAME_
+
8988)CODE";
+
8989
+
8990 std::string enum_type = (e->base && !e->base->empty()) ? *e->base : "int32";
+
8991 std::string enum_read_suffix = "";
+
8992 std::string enum_write_prefix = "";
+
8993 std::string enum_write_suffix = "";
+
8994
+
8995 // Javascript enums are limited to 32-bit integer numbers
+
8996 if (enum_type == "int64")
+
8997 {
+
8998 enum_read_suffix = ".toNumber()";
+
8999 enum_write_prefix = "Int64.fromNumber(";
+
9000 enum_write_suffix = ")";
+
9001 }
+
9002 else if (enum_type == "uint64")
+
9003 {
+
9004 enum_read_suffix = ".toNumber()";
+
9005 enum_write_prefix = "UInt64.fromNumber(";
+
9006 enum_write_suffix = ")";
+
9007 }
+
9008
+
9009 // Prepare code template
+
9010 code = std::regex_replace(code, std::regex("_ENUM_NAME_"), *e->name);
+
9011 code = std::regex_replace(code, std::regex("_ENUM_TYPE_"), ConvertEnumType(enum_type));
+
9012 code = std::regex_replace(code, std::regex("_ENUM_SIZE_"), ConvertEnumSize(enum_type));
+
9013 code = std::regex_replace(code, std::regex("_ENUM_READ_SUFFIX_"), enum_read_suffix);
+
9014 code = std::regex_replace(code, std::regex("_ENUM_WRITE_PREFIX_"), enum_write_prefix);
+
9015 code = std::regex_replace(code, std::regex("_ENUM_WRITE_SUFFIX_"), enum_write_suffix);
+
9016 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
9017
+
9018 Write(code);
+
9019}
+
9020
+
9021void GeneratorJavaScript::GenerateEnumFinalModel(const std::shared_ptr<EnumType>& e)
+
9022{
+
9023 std::string code = R"CODE(
+
9027class FinalModel_ENUM_NAME_ extends fbe.FinalModel {
+
9034 fbeAllocationSize (value) {
+
9035 return this.fbeSize
+
9036 }
+
9037
+
9043 get fbeSize () {
+
9044 return _ENUM_SIZE_
+
9045 }
+
9046
+
9052 verify () {
+
9053 if ((this._buffer.offset + this.fbeOffset + this.fbeSize) > this._buffer.size) {
+
9054 return Number.MAX_SAFE_INTEGER
+
9055 }
+
9056
+
9057 return this.fbeSize
+
9058 }
+
9059
+
9065 get () {
+
9066 if ((this._buffer.offset + this.fbeOffset + this.fbeSize) > this._buffer.size) {
+
9067 return { value: new _ENUM_NAME_(), size: 0 }
+
9068 }
+
9069
+
9070 return { value: new _ENUM_NAME_(this.read_ENUM_TYPE_(this.fbeOffset)_ENUM_READ_SUFFIX_), size: this.fbeSize }
+
9071 }
+
9072
+
9079 set (value) {
+
9080 console.assert(((this._buffer.offset + this.fbeOffset + this.fbeSize) <= this._buffer.size), 'Model is broken!')
+
9081 if ((this._buffer.offset + this.fbeOffset + this.fbeSize) > this._buffer.size) {
+
9082 return 0
+
9083 }
+
9084
+
9085 this.write_ENUM_TYPE_(this.fbeOffset, _ENUM_WRITE_PREFIX_value.value_ENUM_WRITE_SUFFIX_)
+
9086 return this.fbeSize
+
9087 }
+
9088}
+
9089
+
9090exports.FinalModel_ENUM_NAME_ = FinalModel_ENUM_NAME_
+
9091)CODE";
+
9092
+
9093 std::string enum_type = (e->base && !e->base->empty()) ? *e->base : "int32";
+
9094 std::string enum_read_suffix = "";
+
9095 std::string enum_write_prefix = "";
+
9096 std::string enum_write_suffix = "";
+
9097
+
9098 // Javascript enums are limited to 32-bit integer numbers
+
9099 if (enum_type == "int64")
+
9100 {
+
9101 enum_read_suffix = ".toNumber()";
+
9102 enum_write_prefix = "Int64.fromNumber(";
+
9103 enum_write_suffix = ")";
+
9104 }
+
9105 else if (enum_type == "uint64")
+
9106 {
+
9107 enum_read_suffix = ".toNumber()";
+
9108 enum_write_prefix = "UInt64.fromNumber(";
+
9109 enum_write_suffix = ")";
+
9110 }
+
9111
+
9112 // Prepare code template
+
9113 code = std::regex_replace(code, std::regex("_ENUM_NAME_"), *e->name);
+
9114 code = std::regex_replace(code, std::regex("_ENUM_TYPE_"), ConvertEnumType(enum_type));
+
9115 code = std::regex_replace(code, std::regex("_ENUM_SIZE_"), ConvertEnumSize(enum_type));
+
9116 code = std::regex_replace(code, std::regex("_ENUM_READ_SUFFIX_"), enum_read_suffix);
+
9117 code = std::regex_replace(code, std::regex("_ENUM_WRITE_PREFIX_"), enum_write_prefix);
+
9118 code = std::regex_replace(code, std::regex("_ENUM_WRITE_SUFFIX_"), enum_write_suffix);
+
9119 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
9120
+
9121 Write(code);
+
9122}
+
9123
+
9124void GeneratorJavaScript::GenerateFlags(const std::shared_ptr<FlagsType>& f)
+
9125{
+
9126 // Generate flags begin
+
9127 WriteLine();
+
9128 WriteLineIndent("/**");
+
9129 WriteLineIndent(" * " + *f->name + " flags");
+
9130 WriteLineIndent(" */");
+
9131 WriteLineIndent("class " + *f->name + " {");
+
9132 Indent(1);
+
9133
+
9134 std::string flags_type = (f->base && !f->base->empty()) ? *f->base : "int32";
+
9135
+
9136 // Javascript flags are limited to 32-bit integer numbers
+
9137 if (flags_type == "int64")
+
9138 flags_type = "int32";
+
9139 else if (flags_type == "uint64")
+
9140 flags_type = "uint32";
+
9141
+
9142 // Generate flags constructor
+
9143 WriteLineIndent("/**");
+
9144 WriteLineIndent(" * Initialize flags with a given value");
+
9145 WriteLineIndent(" * @param {" + *f->name + "|number|Int64|UInt64=} value Flags value, defaults is 0");
+
9146 WriteLineIndent(" * @constructor");
+
9147 WriteLineIndent(" */");
+
9148 WriteLineIndent("constructor (value = 0) {");
+
9149 Indent(1);
+
9150 WriteLineIndent("if (value instanceof " + *f->name + ") {");
+
9151 Indent(1);
+
9152 WriteLineIndent("this.value = value.value");
+
9153 Indent(-1);
+
9154 WriteLineIndent("} else {");
+
9155 Indent(1);
+
9156 WriteLineIndent("this.value = value");
+
9157 Indent(-1);
+
9158 WriteLineIndent("}");
+
9159 Indent(-1);
+
9160 WriteLineIndent("}");
+
9161
+
9162 // Generate flags hasFlags() method
+
9163 WriteLine();
+
9164 WriteLineIndent("/**");
+
9165 WriteLineIndent(" * Check for the given flags set state");
+
9166 WriteLineIndent(" * @this {!" + *f->name + "}");
+
9167 WriteLineIndent(" * @param {!" + *f->name + "|!number|!Int64|!UInt64} flags Flags");
+
9168 WriteLineIndent(" * @returns {!boolean} Flags set state");
+
9169 WriteLineIndent(" */");
+
9170 WriteLineIndent("hasFlags (flags) {");
+
9171 Indent(1);
+
9172 WriteLineIndent("if (flags instanceof " + *f->name + ") {");
+
9173 Indent(1);
+
9174 WriteLineIndent("flags = flags.value");
+
9175 Indent(-1);
+
9176 WriteLineIndent("}");
+
9177 WriteLineIndent("return ((this.value & flags) !== 0) && ((this.value & flags) === flags)");
+
9178 Indent(-1);
+
9179 WriteLineIndent("}");
+
9180
+
9181 // Generate flags setFlags() method
+
9182 WriteLine();
+
9183 WriteLineIndent("/**");
+
9184 WriteLineIndent(" * Set the given flags");
+
9185 WriteLineIndent(" * @this {!" + *f->name + "}");
+
9186 WriteLineIndent(" * @param {!" + *f->name + "|!number|!Int64|!UInt64} flags Flags");
+
9187 WriteLineIndent(" */");
+
9188 WriteLineIndent("setFlags (flags) {");
+
9189 Indent(1);
+
9190 WriteLineIndent("if (flags instanceof " + *f->name + ") {");
+
9191 Indent(1);
+
9192 WriteLineIndent("flags = flags.value");
+
9193 Indent(-1);
+
9194 WriteLineIndent("}");
+
9195 WriteLineIndent("this.value |= flags");
+
9196 WriteLineIndent("return this");
+
9197 Indent(-1);
+
9198 WriteLineIndent("}");
+
9199
+
9200 // Generate flags removeFlags() method
+
9201 WriteLine();
+
9202 WriteLineIndent("/**");
+
9203 WriteLineIndent(" * Remove the given flags");
+
9204 WriteLineIndent(" * @this {!" + *f->name + "}");
+
9205 WriteLineIndent(" * @param {!" + *f->name + "|!number|!Int64|!UInt64} flags Flags");
+
9206 WriteLineIndent(" */");
+
9207 WriteLineIndent("removeFlags (flags) {");
+
9208 Indent(1);
+
9209 WriteLineIndent("if (flags instanceof " + *f->name + ") {");
+
9210 Indent(1);
+
9211 WriteLineIndent("flags = flags.value");
+
9212 Indent(-1);
+
9213 WriteLineIndent("}");
+
9214 WriteLineIndent("this.value &= ~flags");
+
9215 WriteLineIndent("return this");
+
9216 Indent(-1);
+
9217 WriteLineIndent("}");
+
9218
+
9219 // Generate flags eq() method
+
9220 WriteLine();
+
9221 WriteLineIndent("/**");
+
9222 WriteLineIndent(" * Is this flags equal to other one?");
+
9223 WriteLineIndent(" * @this {!" + *f->name + "}");
+
9224 WriteLineIndent(" * @param {!" + *f->name + "} other Other flags");
+
9225 WriteLineIndent(" * @returns {boolean} Equal result");
+
9226 WriteLineIndent(" */");
+
9227 WriteLineIndent("eq (other) {");
+
9228 Indent(1);
+
9229 WriteLineIndent("if (!(other instanceof " + *f->name + ")) {");
+
9230 Indent(1);
+
9231 WriteLineIndent("throw new TypeError('Instance of " + *f->name + " is required!')");
+
9232 Indent(-1);
+
9233 WriteLineIndent("}");
+
9234 WriteLineIndent("return this.value === other.value");
+
9235 Indent(-1);
+
9236 WriteLineIndent("}");
+
9237
+
9238 // Generate flags valueOf() method
+
9239 WriteLine();
+
9240 WriteLineIndent("/**");
+
9241 WriteLineIndent(" * Get flags value");
+
9242 WriteLineIndent(" * @this {!" + *f->name + "}");
+
9243 WriteLineIndent(" * @returns {!number|!Int64|!UInt64} Flags value");
+
9244 WriteLineIndent(" */");
+
9245 WriteLineIndent("valueOf () {");
+
9246 Indent(1);
+
9247 WriteLineIndent("return this.value");
+
9248 Indent(-1);
+
9249 WriteLineIndent("}");
+
9250
+
9251 // Generate flags toString() method
+
9252 WriteLine();
+
9253 WriteLineIndent("/**");
+
9254 WriteLineIndent(" * Convert flags to string");
+
9255 WriteLineIndent(" * @this {!" + *f->name + "}");
+
9256 WriteLineIndent(" * @returns {!string} Flags value string");
+
9257 WriteLineIndent(" */");
+
9258 WriteLineIndent("toString () {");
+
9259 Indent(1);
+
9260 WriteLineIndent("let result = ''");
+
9261 if (f->body && !f->body->values.empty())
+
9262 {
+
9263 WriteLineIndent("let first = true");
+
9264 for (auto it = f->body->values.begin(); it != f->body->values.end(); ++it)
+
9265 {
+
9266 WriteLineIndent("if ((this.value & " + *f->name + "." + *(*it)->name + ".value) && ((this.value & " + *f->name + "." + *(*it)->name + ".value) === " + *f->name + "." + *(*it)->name + ".value)) {");
+
9267 Indent(1);
+
9268 WriteLineIndent("result += (first ? '' : '|') + '" + *(*it)->name + "'");
+
9269 WriteLineIndent("// noinspection JSUnusedAssignment");
+
9270 WriteLineIndent("first = false");
+
9271 Indent(-1);
+
9272 WriteLineIndent("}");
+
9273 }
+
9274 }
+
9275 WriteLineIndent("return result");
+
9276 Indent(-1);
+
9277 WriteLineIndent("}");
+
9278
+
9279 // Generate flags [util.inspect.custom]() method
+
9280 WriteLine();
+
9281 WriteLineIndent("/**");
+
9282 WriteLineIndent(" * Inspect flags");
+
9283 WriteLineIndent(" * @this {!" + *f->name + "}");
+
9284 WriteLineIndent(" * @returns {!string} Flags value string");
+
9285 WriteLineIndent(" */");
+
9286 WriteLineIndent("[util.inspect.custom] () {");
+
9287 Indent(1);
+
9288 WriteLineIndent("return this.toString()");
+
9289 Indent(-1);
+
9290 WriteLineIndent("}");
+
9291
+
9292 // Generate flags toJSON() method
+
9293 WriteLine();
+
9294 WriteLineIndent("/**");
+
9295 WriteLineIndent(" * Convert flags to JSON");
+
9296 WriteLineIndent(" * @this {!" + *f->name + "}");
+
9297 WriteLineIndent(" * @returns {!number} Flags value for JSON");
+
9298 WriteLineIndent(" */");
+
9299 WriteLineIndent("toJSON () {");
+
9300 Indent(1);
+
9301 WriteLineIndent("return this.value");
+
9302 Indent(-1);
+
9303 WriteLineIndent("}");
+
9304
+
9305 // Generate flags fromFlags() method
+
9306 WriteLine();
+
9307 WriteLineIndent("/**");
+
9308 WriteLineIndent(" * Create flags from number flags representation");
+
9309 WriteLineIndent(" * @param {!number} flags Number flags representation");
+
9310 WriteLineIndent(" * @returns {!" + *f->name + "} Created flags");
+
9311 WriteLineIndent(" */");
+
9312 WriteLineIndent("static fromFlags (flags) {");
+
9313 Indent(1);
+
9314 WriteLineIndent("return new " + *f->name + "(flags)");
+
9315 Indent(-1);
+
9316 WriteLineIndent("}");
+
9317
+
9318 // Generate flags fromObject() method
+
9319 WriteLine();
+
9320 WriteLineIndent("/**");
+
9321 WriteLineIndent(" * Create flags from object value");
+
9322 WriteLineIndent(" * @param {!number} other Object value");
+
9323 WriteLineIndent(" * @returns {!" + *f->name + "} Created flags");
+
9324 WriteLineIndent(" */");
+
9325 WriteLineIndent("static fromObject (other) {");
+
9326 Indent(1);
+
9327 WriteLineIndent("return new " + *f->name + "(other)");
+
9328 Indent(-1);
+
9329 WriteLineIndent("}");
+
9330
+
9331 // Generate flags end
+
9332 Indent(-1);
+
9333 WriteLineIndent("}");
+
9334
+
9335 // Generate flags values
+
9336 if (f->body && !f->body->values.empty())
+
9337 {
+
9338 WriteLine();
+
9339 for (const auto& value : f->body->values)
+
9340 {
+
9341 WriteLineIndent("// noinspection PointlessArithmeticExpressionJS");
+
9342 WriteIndent(*f->name + "." + *value->name + " = new " + *f->name + "(");
+
9343 if (value->value)
+
9344 {
+
9345 if (value->value->constant && !value->value->constant->empty())
+
9346 Write(ConvertEnumConstant(*f->name, flags_type, *value->value->constant));
+
9347 else if (value->value->reference && !value->value->reference->empty())
+
9348 Write(ConvertEnumConstant(*f->name, "", *value->value->reference));
+
9349 }
+
9350 Write(")");
+
9351 WriteLine();
+
9352 }
+
9353 }
+
9354
+
9355 // Generate flags exports
+
9356 WriteLine();
+
9357 WriteLineIndent("exports." + *f->name + " = " + *f->name);
+
9358
+
9359 // Generate flags field model
+
9360 GenerateFlagsFieldModel(f);
+
9361
+
9362 // Generate flags final model
+
9363 if (Final())
+
9364 GenerateFlagsFinalModel(f);
+
9365}
+
9366
+
9367void GeneratorJavaScript::GenerateFlagsFieldModel(const std::shared_ptr<FlagsType>& f)
+
9368{
+
9369 std::string code = R"CODE(
+
9373class FieldModel_FLAGS_NAME_ extends fbe.FieldModel {
+
9379 get fbeSize () {
+
9380 return _FLAGS_SIZE_
+
9381 }
+
9382
+
9389 get (defaults = new _FLAGS_NAME_()) {
+
9390 if ((this._buffer.offset + this.fbeOffset + this.fbeSize) > this._buffer.size) {
+
9391 return defaults
+
9392 }
+
9393
+
9394 return new _FLAGS_NAME_(this.read_FLAGS_TYPE_(this.fbeOffset)_FLAGS_READ_SUFFIX_)
+
9395 }
+
9396
+
9402 set (value) {
+
9403 console.assert(((this._buffer.offset + this.fbeOffset + this.fbeSize) <= this._buffer.size), 'Model is broken!')
+
9404 if ((this._buffer.offset + this.fbeOffset + this.fbeSize) > this._buffer.size) {
+
9405 return
+
9406 }
+
9407
+
9408 this.write_FLAGS_TYPE_(this.fbeOffset, _FLAGS_WRITE_PREFIX_value.value_FLAGS_WRITE_SUFFIX_)
+
9409 }
+
9410}
+
9411
+
9412exports.FieldModel_FLAGS_NAME_ = FieldModel_FLAGS_NAME_
+
9413)CODE";
+
9414
+
9415 std::string flags_type = (f->base && !f->base->empty()) ? *f->base : "int32";
+
9416 std::string flags_read_suffix = "";
+
9417 std::string flags_write_prefix = "";
+
9418 std::string flags_write_suffix = "";
+
9419
+
9420 // Javascript flags are limited to 32-bit integer numbers
+
9421 if (flags_type == "int64")
+
9422 {
+
9423 flags_read_suffix = ".toNumber()";
+
9424 flags_write_prefix = "Int64.fromNumber(";
+
9425 flags_write_suffix = ")";
+
9426 }
+
9427 else if (flags_type == "uint64")
+
9428 {
+
9429 flags_read_suffix = ".toNumber()";
+
9430 flags_write_prefix = "UInt64.fromNumber(";
+
9431 flags_write_suffix = ")";
+
9432 }
+
9433
+
9434 // Prepare code template
+
9435 code = std::regex_replace(code, std::regex("_FLAGS_NAME_"), *f->name);
+
9436 code = std::regex_replace(code, std::regex("_FLAGS_TYPE_"), ConvertEnumType(flags_type));
+
9437 code = std::regex_replace(code, std::regex("_FLAGS_SIZE_"), ConvertEnumSize(flags_type));
+
9438 code = std::regex_replace(code, std::regex("_FLAGS_READ_SUFFIX_"), flags_read_suffix);
+
9439 code = std::regex_replace(code, std::regex("_FLAGS_WRITE_PREFIX_"), flags_write_prefix);
+
9440 code = std::regex_replace(code, std::regex("_FLAGS_WRITE_SUFFIX_"), flags_write_suffix);
+
9441 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
9442
+
9443 Write(code);
+
9444}
+
9445
+
9446void GeneratorJavaScript::GenerateFlagsFinalModel(const std::shared_ptr<FlagsType>& f)
+
9447{
+
9448 std::string code = R"CODE(
+
9452class FinalModel_FLAGS_NAME_ extends fbe.FinalModel {
+
9459 fbeAllocationSize (value) {
+
9460 return this.fbeSize
+
9461 }
+
9462
+
9468 get fbeSize () {
+
9469 return _FLAGS_SIZE_
+
9470 }
+
9471
+
9477 verify () {
+
9478 if ((this._buffer.offset + this.fbeOffset + this.fbeSize) > this._buffer.size) {
+
9479 return Number.MAX_SAFE_INTEGER
+
9480 }
+
9481
+
9482 return this.fbeSize
+
9483 }
+
9484
+
9490 get () {
+
9491 if ((this._buffer.offset + this.fbeOffset + this.fbeSize) > this._buffer.size) {
+
9492 return { value: new _FLAGS_NAME_(), size: 0 }
+
9493 }
+
9494
+
9495 return { value: new _FLAGS_NAME_(this.read_FLAGS_TYPE_(this.fbeOffset)_FLAGS_READ_SUFFIX_), size: this.fbeSize }
+
9496 }
+
9497
+
9504 set (value) {
+
9505 console.assert(((this._buffer.offset + this.fbeOffset + this.fbeSize) <= this._buffer.size), 'Model is broken!')
+
9506 if ((this._buffer.offset + this.fbeOffset + this.fbeSize) > this._buffer.size) {
+
9507 return 0
+
9508 }
+
9509
+
9510 this.write_FLAGS_TYPE_(this.fbeOffset, _FLAGS_WRITE_PREFIX_value.value_FLAGS_WRITE_SUFFIX_)
+
9511 return this.fbeSize
+
9512 }
+
9513}
+
9514
+
9515exports.FinalModel_FLAGS_NAME_ = FinalModel_FLAGS_NAME_
+
9516)CODE";
+
9517
+
9518 std::string flags_type = (f->base && !f->base->empty()) ? *f->base : "int32";
+
9519 std::string flags_read_suffix = "";
+
9520 std::string flags_write_prefix = "";
+
9521 std::string flags_write_suffix = "";
+
9522
+
9523 // Javascript flags are limited to 32-bit integer numbers
+
9524 if (flags_type == "int64")
+
9525 {
+
9526 flags_read_suffix = ".toNumber()";
+
9527 flags_write_prefix = "Int64.fromNumber(";
+
9528 flags_write_suffix = ")";
+
9529 }
+
9530 else if (flags_type == "uint64")
+
9531 {
+
9532 flags_read_suffix = ".toNumber()";
+
9533 flags_write_prefix = "UInt64.fromNumber(";
+
9534 flags_write_suffix = ")";
+
9535 }
+
9536
+
9537 // Prepare code template
+
9538 code = std::regex_replace(code, std::regex("_FLAGS_NAME_"), *f->name);
+
9539 code = std::regex_replace(code, std::regex("_FLAGS_TYPE_"), ConvertEnumType(flags_type));
+
9540 code = std::regex_replace(code, std::regex("_FLAGS_SIZE_"), ConvertEnumSize(flags_type));
+
9541 code = std::regex_replace(code, std::regex("_FLAGS_READ_SUFFIX_"), flags_read_suffix);
+
9542 code = std::regex_replace(code, std::regex("_FLAGS_WRITE_PREFIX_"), flags_write_prefix);
+
9543 code = std::regex_replace(code, std::regex("_FLAGS_WRITE_SUFFIX_"), flags_write_suffix);
+
9544 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
9545
+
9546 Write(code);
+
9547}
+
9548
+
9549void GeneratorJavaScript::GenerateStruct(const std::shared_ptr<StructType>& s)
+
9550{
+
9551 bool first;
+
9552
+
9553 // Generate struct begin
+
9554 WriteLine();
+
9555 WriteLineIndent("/**");
+
9556 WriteLineIndent(" * " + *s->name + " struct");
+
9557 WriteLineIndent(" */");
+
9558 WriteIndent("class " + *s->name);
+
9559 if (s->base && !s->base->empty())
+
9560 WriteIndent(" extends " + ConvertTypeName(*s->base, false));
+
9561 WriteLineIndent(" {");
+
9562 Indent(1);
+
9563
+
9564 // Generate struct constructor
+
9565 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
9566 {
+
9567 first = true;
+
9568 WriteLineIndent("/**");
+
9569 WriteLineIndent(" * Initialize struct");
+
9570 if (s->base && !s->base->empty())
+
9571 WriteLineIndent(" * @param {!" + ConvertTypeName(*s->base, false) + "=} parent");
+
9572 if (s->body)
+
9573 for (const auto& field : s->body->fields)
+
9574 WriteLineIndent(" * @param {" + std::string(field->optional ? "" : "!") + ConvertTypeName(*field) + "=} " + *field->name);
+
9575 WriteLineIndent(" * @constructor");
+
9576 WriteLineIndent(" */");
+
9577 WriteIndent("constructor (");
+
9578 if (s->base && !s->base->empty())
+
9579 {
+
9580 Write("parent = new " + ConvertTypeName(*s->base, false) + "()");
+
9581 first = false;
+
9582 }
+
9583 if (s->body)
+
9584 {
+
9585 for (const auto& field : s->body->fields)
+
9586 {
+
9587 Write(std::string(first ? "arg" : ", arg") + *field->name + " = " + ConvertDefault(*field));
+
9588 first = false;
+
9589 }
+
9590 }
+
9591 WriteLine(") {");
+
9592 Indent(1);
+
9593 if (s->base && !s->base->empty())
+
9594 {
+
9595 WriteLineIndent("super()");
+
9596 WriteLineIndent("super.copy(parent)");
+
9597 }
+
9598 if (s->body)
+
9599 for (const auto& field : s->body->fields)
+
9600 WriteLineIndent("this." + *field->name + " = arg" + *field->name);
+
9601 Indent(-1);
+
9602 WriteLineIndent("}");
+
9603 WriteLine();
+
9604 }
+
9605
+
9606 // Generate struct copy() method
+
9607 WriteLineIndent("/**");
+
9608 WriteLineIndent(" * Copy struct (shallow copy)");
+
9609 WriteLineIndent(" * @this {!" + *s->name + "}");
+
9610 WriteLineIndent(" * @param {!" + *s->name + "} other Other struct");
+
9611 WriteLineIndent(" * @returns {!" + *s->name + "} This struct");
+
9612 WriteLineIndent(" */");
+
9613 WriteLineIndent("copy (other) {");
+
9614 Indent(1);
+
9615 if (s->base && !s->base->empty())
+
9616 WriteLineIndent("super.copy(other)");
+
9617 if (s->body)
+
9618 {
+
9619 for (const auto& field : s->body->fields)
+
9620 {
+
9621 WriteLineIndent("if (other." + *field->name + " != null) {");
+
9622 Indent(1);
+
9623 if (field->array || field->vector || field->list)
+
9624 {
+
9625 WriteLineIndent("this." + *field->name + " = []");
+
9626 WriteLineIndent("for (let item of other." + *field->name + ") {");
+
9627 Indent(1);
+
9628 WriteLineIndent("if (item != null) {");
+
9629 Indent(1);
+
9630 WriteLineIndent("let tempItem");
+
9631 CopyValueToVariable(*field->type, "item", "tempItem", field->optional);
+
9632 WriteLineIndent("this." + *field->name + ".push(tempItem)");
+
9633 Indent(-1);
+
9634 WriteLineIndent("} else {");
+
9635 Indent(1);
+
9636 WriteLineIndent("this." + *field->name + ".push(undefined)");
+
9637 Indent(-1);
+
9638 WriteLineIndent("}");
+
9639 Indent(-1);
+
9640 WriteLineIndent("}");
+
9641 }
+
9642 else if (field->set)
+
9643 {
+
9644 WriteLineIndent("this." + *field->name + " = new Set()");
+
9645 WriteLineIndent("for (let item of other." + *field->name + ") {");
+
9646 Indent(1);
+
9647 WriteLineIndent("if (item != null) {");
+
9648 Indent(1);
+
9649 WriteLineIndent("let tempItem");
+
9650 CopyValueToVariable(*field->type, "item", "tempItem", field->optional);
+
9651 WriteLineIndent("this." + *field->name + ".add(tempItem)");
+
9652 Indent(-1);
+
9653 WriteLineIndent("} else {");
+
9654 Indent(1);
+
9655 WriteLineIndent("this." + *field->name + ".add(undefined)");
+
9656 Indent(-1);
+
9657 WriteLineIndent("}");
+
9658 Indent(-1);
+
9659 WriteLineIndent("}");
+
9660 }
+
9661 else if (field->map || field->hash)
+
9662 {
+
9663 WriteLineIndent("this." + *field->name + " = new Map()");
+
9664 WriteLineIndent("Object.keys(other." + *field->name + ").forEach(key => {");
+
9665 Indent(1);
+
9666 WriteLineIndent("if (key != null) {");
+
9667 Indent(1);
+
9668 WriteLineIndent("let tempKey");
+
9669 CopyValueToVariable(*field->key, "key", "tempKey", false);
+
9670 WriteLineIndent("if (other." + *field->name + "[key] != null) {");
+
9671 Indent(1);
+
9672 WriteLineIndent("let tempValue");
+
9673 CopyValueToVariable(*field->type, "other." + *field->name + "[key]", "tempValue", field->optional);
+
9674 WriteLineIndent("this." + *field->name + ".set(tempKey, tempValue)");
+
9675 Indent(-1);
+
9676 WriteLineIndent("} else {");
+
9677 Indent(1);
+
9678 WriteLineIndent("this." + *field->name + ".set(tempKey, undefined)");
+
9679 Indent(-1);
+
9680 WriteLineIndent("}");
+
9681 Indent(-1);
+
9682 WriteLineIndent("}");
+
9683 Indent(-1);
+
9684 WriteLineIndent("})");
+
9685 }
+
9686 else
+
9687 CopyValueToVariable(*field->type, "other." + *field->name, "this." + *field->name, field->optional);
+
9688 Indent(-1);
+
9689 WriteLineIndent("} else {");
+
9690 Indent(1);
+
9691 WriteLineIndent("this." + *field->name + " = undefined");
+
9692 Indent(-1);
+
9693 WriteLineIndent("}");
+
9694 }
+
9695 }
+
9696 WriteLineIndent("return this");
+
9697 Indent(-1);
+
9698 WriteLineIndent("}");
+
9699
+
9700 // Generate struct clone() method
+
9701 WriteLine();
+
9702 WriteLineIndent("/**");
+
9703 WriteLineIndent(" * Clone struct (deep clone)");
+
9704 WriteLineIndent(" * @this {!" + *s->name + "}");
+
9705 WriteLineIndent(" * @returns {!" + *s->name + "} Cloned struct");
+
9706 WriteLineIndent(" */");
+
9707 WriteLineIndent("clone () {");
+
9708 Indent(1);
+
9709 WriteLineIndent("// Serialize the struct to the FBE stream");
+
9710 WriteLineIndent("let writer = new " + *s->name + "Model(new fbe.WriteBuffer())");
+
9711 WriteLineIndent("writer.serialize(this)");
+
9712 WriteLine();
+
9713 WriteLineIndent("// Deserialize the struct from the FBE stream");
+
9714 WriteLineIndent("let reader = new " + *s->name + "Model(new fbe.ReadBuffer())");
+
9715 WriteLineIndent("reader.attachBuffer(writer.buffer)");
+
9716 WriteLineIndent("return reader.deserialize().value");
+
9717 Indent(-1);
+
9718 WriteLineIndent("}");
+
9719
+
9720 // Generate struct eq() method
+
9721 WriteLine();
+
9722 WriteLineIndent("/**");
+
9723 WriteLineIndent(" * Is this struct equal to other one?");
+
9724 WriteLineIndent(" * @this {!" + *s->name + "}");
+
9725 WriteLineIndent(" * @param {!" + *s->name + "} other Other struct");
+
9726 WriteLineIndent(" * @returns {boolean} Equal result");
+
9727 WriteLineIndent(" */");
+
9728 WriteLineIndent("eq (other) {");
+
9729 Indent(1);
+
9730 WriteLineIndent("if (!(other instanceof " + *s->name + ")) {");
+
9731 Indent(1);
+
9732 WriteLineIndent("throw new TypeError('Instance of " + *s->name + " is required!')");
+
9733 Indent(-1);
+
9734 WriteLineIndent("}");
+
9735 if (s->base && !s->base->empty())
+
9736 {
+
9737 WriteLineIndent("// noinspection RedundantIfStatementJS");
+
9738 WriteLineIndent("if (!super.eq(other)) {");
+
9739 Indent(1);
+
9740 WriteLineIndent("return false");
+
9741 Indent(-1);
+
9742 WriteLineIndent("}");
+
9743 }
+
9744 if (s->body)
+
9745 {
+
9746 for (const auto& field : s->body->fields)
+
9747 {
+
9748 if (field->keys)
+
9749 {
+
9750 WriteLineIndent("// noinspection RedundantIfStatementJS");
+
9751 if (IsJavaScriptType(*field->type))
+
9752 {
+
9753 WriteLineIndent("if (this." + *field->name + " !== other." + *field->name + ") {");
+
9754 Indent(1);
+
9755 WriteLineIndent("return false");
+
9756 Indent(-1);
+
9757 WriteLineIndent("}");
+
9758 }
+
9759 else
+
9760 {
+
9761 WriteLineIndent("if (this." + *field->name + " != null) {");
+
9762 Indent(1);
+
9763 WriteLineIndent("if ((other." + *field->name + " == null) || !this." + *field->name + ".eq(other." + *field->name + ")) {");
+
9764 Indent(1);
+
9765 WriteLineIndent("return false");
+
9766 Indent(-1);
+
9767 WriteLineIndent("}");
+
9768 Indent(-1);
+
9769 WriteLineIndent("} else if (other." + *field->name + " != null) {");
+
9770 Indent(1);
+
9771 WriteLineIndent("return false");
+
9772 Indent(-1);
+
9773 WriteLineIndent("}");
+
9774 }
+
9775 }
+
9776 }
+
9777 }
+
9778 WriteLineIndent("return true");
+
9779 Indent(-1);
+
9780 WriteLineIndent("}");
+
9781
+
9782 // Generate flags toString() method
+
9783 WriteLine();
+
9784 WriteLineIndent("/**");
+
9785 WriteLineIndent(" * Convert struct to string");
+
9786 WriteLineIndent(" * @this {!" + *s->name + "}");
+
9787 WriteLineIndent(" * @returns {!string} Struct value string");
+
9788 WriteLineIndent(" */");
+
9789 WriteLineIndent("toString () {");
+
9790 Indent(1);
+
9791 WriteLineIndent("let result = ''");
+
9792 WriteLineIndent("result += '" + *s->name + "('");
+
9793 first = true;
+
9794 if (s->base && !s->base->empty())
+
9795 {
+
9796 WriteLineIndent("result += super.toString()");
+
9797 first = false;
+
9798 }
+
9799 if (s->body)
+
9800 {
+
9801 for (const auto& field : s->body->fields)
+
9802 {
+
9803 WriteLineIndent("result += '" + std::string(first ? "" : ",") + *field->name + "='");
+
9804 if (field->attributes && field->attributes->hidden)
+
9805 WriteLineIndent("result += '***'");
+
9806 else if (field->array || field->vector)
+
9807 {
+
9808 WriteLineIndent("if (this." + *field->name + " != null) {");
+
9809 Indent(1);
+
9810 WriteLineIndent("let first = true");
+
9811 WriteLineIndent("result += '[' + this." + *field->name + ".length + ']['");
+
9812 WriteLineIndent("for (let item of this." + *field->name + ") {");
+
9813 Indent(1);
+
9814 WriteOutputStreamValue(*field->type, "item", field->optional, true);
+
9815 WriteLineIndent("first = false");
+
9816 Indent(-1);
+
9817 WriteLineIndent("}");
+
9818 WriteLineIndent("result += ']'");
+
9819 Indent(-1);
+
9820 WriteLineIndent("} else {");
+
9821 Indent(1);
+
9822 WriteLineIndent("result += '[0][]'");
+
9823 Indent(-1);
+
9824 WriteLineIndent("}");
+
9825 }
+
9826 else if (field->list)
+
9827 {
+
9828 WriteLineIndent("if (this." + *field->name + " != null) {");
+
9829 Indent(1);
+
9830 WriteLineIndent("let first = true");
+
9831 WriteLineIndent("result += '[' + this." + *field->name + ".length + ']<'");
+
9832 WriteLineIndent("for (let item of this." + *field->name + ") {");
+
9833 Indent(1);
+
9834 WriteOutputStreamValue(*field->type, "item", field->optional, true);
+
9835 WriteLineIndent("first = false");
+
9836 Indent(-1);
+
9837 WriteLineIndent("}");
+
9838 WriteLineIndent("result += '>'");
+
9839 Indent(-1);
+
9840 WriteLineIndent("} else {");
+
9841 Indent(1);
+
9842 WriteLineIndent("result += '[0]<>'");
+
9843 Indent(-1);
+
9844 WriteLineIndent("}");
+
9845 }
+
9846 else if (field->set)
+
9847 {
+
9848 WriteLineIndent("if (this." + *field->name + " != null) {");
+
9849 Indent(1);
+
9850 WriteLineIndent("let first = true");
+
9851 WriteLineIndent("result += '[' + this." + *field->name + ".size + ']{'");
+
9852 WriteLineIndent("for (let item of this." + *field->name + ") {");
+
9853 Indent(1);
+
9854 WriteOutputStreamValue(*field->type, "item", field->optional, true);
+
9855 WriteLineIndent("first = false");
+
9856 Indent(-1);
+
9857 WriteLineIndent("}");
+
9858 WriteLineIndent("result += '}'");
+
9859 Indent(-1);
+
9860 WriteLineIndent("} else {");
+
9861 Indent(1);
+
9862 WriteLineIndent("result += '[0]{}'");
+
9863 Indent(-1);
+
9864 WriteLineIndent("}");
+
9865 }
+
9866 else if (field->map)
+
9867 {
+
9868 WriteLineIndent("if (this." + *field->name + " != null) {");
+
9869 Indent(1);
+
9870 WriteLineIndent("let first = true");
+
9871 WriteLineIndent("result += '[' + this." + *field->name + ".size + ']<{'");
+
9872 WriteLineIndent("for (let [key, value] of this." + *field->name + ") {");
+
9873 Indent(1);
+
9874 WriteOutputStreamValue(*field->key, "key", false, true);
+
9875 WriteLineIndent("result += '->'");
+
9876 WriteOutputStreamValue(*field->type, "value", field->optional, false);
+
9877 WriteLineIndent("first = false");
+
9878 Indent(-1);
+
9879 WriteLineIndent("}");
+
9880 WriteLineIndent("result += '}>'");
+
9881 Indent(-1);
+
9882 WriteLineIndent("} else {");
+
9883 Indent(1);
+
9884 WriteLineIndent("result += '[0]<{}>'");
+
9885 Indent(-1);
+
9886 WriteLineIndent("}");
+
9887 }
+
9888 else if (field->hash)
+
9889 {
+
9890 WriteLineIndent("if (this." + *field->name + " != null) {");
+
9891 Indent(1);
+
9892 WriteLineIndent("let first = true");
+
9893 WriteLineIndent("result += '[' + this." + *field->name + ".size + '][{'");
+
9894 WriteLineIndent("for (let [key, value] of this." + *field->name + ") {");
+
9895 Indent(1);
+
9896 WriteOutputStreamValue(*field->key, "key", false, true);
+
9897 WriteLineIndent("result += '->'");
+
9898 WriteOutputStreamValue(*field->type, "value", field->optional, false);
+
9899 WriteLineIndent("first = false");
+
9900 Indent(-1);
+
9901 WriteLineIndent("}");
+
9902 WriteLineIndent("result += '}]'");
+
9903 Indent(-1);
+
9904 WriteLineIndent("} else {");
+
9905 Indent(1);
+
9906 WriteLineIndent("result += '[0][{}]'");
+
9907 Indent(-1);
+
9908 WriteLineIndent("}");
+
9909 }
+
9910 else
+
9911 WriteOutputStreamValue(*field->type, "this." + *field->name, field->optional, false);
+
9912 first = false;
+
9913 }
+
9914 }
+
9915 WriteLineIndent("result += ')'");
+
9916 WriteLineIndent("return result");
+
9917 Indent(-1);
+
9918 WriteLineIndent("}");
+
9919
+
9920 // Generate struct [util.inspect.custom]() method
+
9921 WriteLine();
+
9922 WriteLineIndent("/**");
+
9923 WriteLineIndent(" * Inspect struct");
+
9924 WriteLineIndent(" * @this {!" + *s->name + "}");
+
9925 WriteLineIndent(" * @returns {!string} Struct value string");
+
9926 WriteLineIndent(" */");
+
9927 WriteLineIndent("[util.inspect.custom] () {");
+
9928 Indent(1);
+
9929 WriteLineIndent("return this.toString()");
+
9930 Indent(-1);
+
9931 WriteLineIndent("}");
+
9932
+
9933 // Generate struct toJSON() method
+
9934 WriteLine();
+
9935 WriteLineIndent("/**");
+
9936 WriteLineIndent(" * Convert struct to JSON");
+
9937 WriteLineIndent(" * @this {!" + *s->name + "}");
+
9938 WriteLineIndent(" * @returns {!object} Struct value for JSON");
+
9939 WriteLineIndent(" */");
+
9940 WriteLineIndent("toJSON () {");
+
9941 Indent(1);
+
9942 if (s->base && !s->base->empty())
+
9943 {
+
9944 WriteLineIndent("let parent = super.toJSON()");
+
9945 WriteLineIndent("let current = {");
+
9946 }
+
9947 else
+
9948 WriteLineIndent("return {");
+
9949 Indent(1);
+
9950 if (s->body)
+
9951 {
+
9952 for (size_t i = 0; i < s->body->fields.size(); ++i)
+
9953 {
+
9954 bool last = (i == (s->body->fields.size() - 1));
+
9955 auto field = s->body->fields[i];
+
9956 if (field->array || field->vector || field->list || field->set)
+
9957 WriteLineIndent(*field->name + ": ((this." + *field->name + " != null) ? Array.from(this." + *field->name + ", item => " + ConvertVariable(*field->type, "item", field->optional) + ") : null)" + std::string(last ? "" : ","));
+
9958 else if (field->map || field->hash)
+
9959 WriteLineIndent(*field->name + ": ((this." + *field->name + " != null) ? fbe.MapToObject(new Map(Array.from(this." + *field->name + ", item => [" + ConvertVariable(*field->key, "item[0]", false) + ", " + ConvertVariable(*field->type, "item[1]", field->optional) + "]))) : null)" + std::string(last ? "" : ","));
+
9960 else
+
9961 WriteLineIndent(*field->name + ": " + ConvertVariable(*field->type, "this." + *field->name, field->optional) + std::string(last ? "" : ","));
+
9962
+
9963 }
+
9964 }
+
9965 Indent(-1);
+
9966 WriteLineIndent("}");
+
9967 if (s->base && !s->base->empty())
+
9968 WriteLineIndent("return { ...parent, ...current }");
+
9969 Indent(-1);
+
9970 WriteLineIndent("}");
+
9971
+
9972 // Generate struct fromJSON() method
+
9973 WriteLine();
+
9974 WriteLineIndent("/**");
+
9975 WriteLineIndent(" * Convert JSON to struct");
+
9976 WriteLineIndent(" * @param {!string} json JSON string");
+
9977 WriteLineIndent(" * @returns {!object} Struct value for JSON");
+
9978 WriteLineIndent(" */");
+
9979 WriteLineIndent("static fromJSON (json) {");
+
9980 Indent(1);
+
9981 WriteLineIndent("return " + *s->name + ".fromObject(JSON.parse(json))");
+
9982 Indent(-1);
+
9983 WriteLineIndent("}");
+
9984
+
9985 // Generate struct fromObject() method
+
9986 WriteLine();
+
9987 WriteLineIndent("/**");
+
9988 WriteLineIndent(" * Create struct from object value");
+
9989 WriteLineIndent(" * @param {!" + *s->name + "} other Object value");
+
9990 WriteLineIndent(" * @returns {!" + *s->name + "} Created struct");
+
9991 WriteLineIndent(" */");
+
9992 WriteLineIndent("static fromObject (other) {");
+
9993 Indent(1);
+
9994 WriteLineIndent("return new " + *s->name + "().copy(other)");
+
9995 Indent(-1);
+
9996 WriteLineIndent("}");
+
9997
+
9998 // Generate struct FBE type property
+
9999 WriteLine();
+
10000 WriteLineIndent("/**");
+
10001 WriteLineIndent(" * Get the FBE type");
+
10002 WriteLineIndent(" * @this {!" + *s->name + "}");
+
10003 WriteLineIndent(" * @returns {!number} FBE type");
+
10004 WriteLineIndent(" */");
+
10005 WriteLineIndent("get fbeType () {");
+
10006 Indent(1);
+
10007 WriteLineIndent("return " + *s->name + ".fbeType");
+
10008 Indent(-1);
+
10009 WriteLineIndent("}");
+
10010 WriteLine();
+
10011 WriteLineIndent("/**");
+
10012 WriteLineIndent(" * Get the FBE type (static)");
+
10013 WriteLineIndent(" * @this {!" + *s->name + "}");
+
10014 WriteLineIndent(" * @returns {!number} FBE type");
+
10015 WriteLineIndent(" */");
+
10016 WriteLineIndent("static get fbeType () {");
+
10017 Indent(1);
+
10018 if (s->base && !s->base->empty() && (s->type == 0))
+
10019 WriteLineIndent("return " + ConvertTypeName(*s->base, false) + ".fbeType");
+
10020 else
+
10021 WriteLineIndent("return " + std::to_string(s->type));
+
10022 Indent(-1);
+
10023 WriteLineIndent("}");
+
10024
+
10025 // Generate struct end
+
10026 Indent(-1);
+
10027 WriteLineIndent("}");
+
10028
+
10029 // Generate struct exports
+
10030 WriteLine();
+
10031 WriteLineIndent("exports." + *s->name + " = " + *s->name);
+
10032
+
10033 // Generate struct field model
+
10034 GenerateStructFieldModel(s);
+
10035
+
10036 // Generate struct model
+
10037 GenerateStructModel(s);
+
10038
+
10039 // Generate struct final models
+
10040 if (Final())
+
10041 {
+
10042 GenerateStructFinalModel(s);
+
10043 GenerateStructModelFinal(s);
+
10044 }
+
10045}
+
10046
+
10047void GeneratorJavaScript::GenerateStructFieldModel(const std::shared_ptr<StructType>& s)
+
10048{
+
10049 // Generate struct field model begin
+
10050 WriteLine();
+
10051 WriteLineIndent("/**");
+
10052 WriteLineIndent(" * Fast Binary Encoding " + *s->name + " field model");
+
10053 WriteLineIndent(" */");
+
10054 WriteLineIndent("class FieldModel" + *s->name + " extends fbe.FieldModel {");
+
10055 Indent(1);
+
10056
+
10057 // Generate struct field model constructor
+
10058 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
10059 {
+
10060 WriteLineIndent("/**");
+
10061 WriteLineIndent(" * Initialize field model with the given buffer and offset");
+
10062 WriteLineIndent(" * @param {!fbe.ReadBuffer|!fbe.WriteBuffer} buffer Buffer");
+
10063 WriteLineIndent(" * @param {!number} offset Offset");
+
10064 WriteLineIndent(" * @constructor");
+
10065 WriteLineIndent(" */");
+
10066 WriteLineIndent("constructor (buffer, offset) {");
+
10067 Indent(1);
+
10068 WriteLineIndent("super(buffer, offset)");
+
10069 std::string prev_offset("4");
+
10070 std::string prev_size("4");
+
10071 if (s->base && !s->base->empty())
+
10072 {
+
10073 WriteLineIndent("this._parent = new " + ConvertTypeFieldName(*s->base, false) + "(buffer, " + prev_offset + " + " + prev_size + ")");
+
10074 prev_offset = "this._parent.fbeOffset";
+
10075 prev_size = "this._parent.fbeBody - 4 - 4";
+
10076 }
+
10077 if (s->body)
+
10078 {
+
10079 for (const auto& field : s->body->fields)
+
10080 {
+
10081 WriteLineIndent("this._" + *field->name + " = new " + ConvertTypeFieldInitialization(*field, prev_offset + " + " + prev_size, false));
+
10082 prev_offset = "this._" + *field->name + ".fbeOffset";
+
10083 prev_size = "this._" + *field->name + ".fbeSize";
+
10084 }
+
10085 }
+
10086 Indent(-1);
+
10087 WriteLineIndent("}");
+
10088 WriteLine();
+
10089 }
+
10090
+
10091 // Generate struct field model accessors
+
10092 if (s->base && !s->base->empty())
+
10093 {
+
10094 WriteLineIndent("/**");
+
10095 WriteLineIndent(" * Get the " + *s->base + " field model");
+
10096 WriteLineIndent(" * @this {!FieldModel" + *s->name + "}");
+
10097 WriteLineIndent(" * @returns {!" + ConvertTypeFieldName(*s->base, false) + "} " + *s->base + " field model");
+
10098 WriteLineIndent(" */");
+
10099 WriteLineIndent("get parent () {");
+
10100 Indent(1);
+
10101 WriteLineIndent("return this._parent");
+
10102 Indent(-1);
+
10103 WriteLineIndent("}");
+
10104 WriteLine();
+
10105 }
+
10106 if (s->body)
+
10107 {
+
10108 for (const auto& field : s->body->fields)
+
10109 {
+
10110 WriteLineIndent("/**");
+
10111 WriteLineIndent(" * Get the " + *field->name + " field model");
+
10112 WriteLineIndent(" * @this {!FieldModel" + *s->name + "}");
+
10113 WriteLineIndent(" * @returns {!" + ConvertTypeFieldDeclaration(*field, false) + "} " + *field->name + " field model");
+
10114 WriteLineIndent(" */");
+
10115 WriteLineIndent("get " + *field->name + " () {");
+
10116 Indent(1);
+
10117 WriteLineIndent("return this._" + *field->name);
+
10118 Indent(-1);
+
10119 WriteLineIndent("}");
+
10120 WriteLine();
+
10121 }
+
10122 }
+
10123
+
10124 // Generate struct field model FBE properties
+
10125 WriteLineIndent("/**");
+
10126 WriteLineIndent(" * Get the field size");
+
10127 WriteLineIndent(" * @this {!FieldModel" + *s->name + "}");
+
10128 WriteLineIndent(" * @returns {!number} Field size");
+
10129 WriteLineIndent(" */");
+
10130 WriteLineIndent("get fbeSize () {");
+
10131 Indent(1);
+
10132 WriteLineIndent("return 4");
+
10133 Indent(-1);
+
10134 WriteLineIndent("}");
+
10135 WriteLine();
+
10136 WriteLineIndent("/**");
+
10137 WriteLineIndent(" * Get the field body size");
+
10138 WriteLineIndent(" * @this {!FieldModel" + *s->name + "}");
+
10139 WriteLineIndent(" * @returns {!number} Field body size");
+
10140 WriteLineIndent(" */");
+
10141 WriteLineIndent("get fbeBody () {");
+
10142 Indent(1);
+
10143 WriteIndent("return 4 + 4");
+
10144 if (s->base && !s->base->empty())
+
10145 Write(" + this.parent.fbeBody - 4 - 4");
+
10146 if (s->body)
+
10147 for (const auto& field : s->body->fields)
+
10148 Write(" + this." + *field->name + ".fbeSize");
+
10149 WriteLine();
+
10150 Indent(-1);
+
10151 WriteLineIndent("}");
+
10152 WriteLine();
+
10153 WriteLineIndent("/**");
+
10154 WriteLineIndent(" * Get the field extra size");
+
10155 WriteLineIndent(" * @this {!FieldModel" + *s->name + "}");
+
10156 WriteLineIndent(" * @returns {!number} Field extra size");
+
10157 WriteLineIndent(" */");
+
10158 WriteLineIndent("get fbeExtra () {");
+
10159 Indent(1);
+
10160 WriteLineIndent("if ((this._buffer.offset + this.fbeOffset + this.fbeSize) > this._buffer.size) {");
+
10161 Indent(1);
+
10162 WriteLineIndent("return 0");
+
10163 Indent(-1);
+
10164 WriteLineIndent("}");
+
10165 WriteLine();
+
10166 WriteLineIndent("let fbeStructOffset = this.readUInt32(this.fbeOffset)");
+
10167 WriteLineIndent("if ((fbeStructOffset === 0) || ((this._buffer.offset + fbeStructOffset + 4) > this._buffer.size)) {");
+
10168 Indent(1);
+
10169 WriteLineIndent("return 0");
+
10170 Indent(-1);
+
10171 WriteLineIndent("}");
+
10172 WriteLine();
+
10173 WriteLineIndent("this._buffer.shift(fbeStructOffset)");
+
10174 WriteLine();
+
10175 WriteIndent("let fbeResult = this.fbeBody");
+
10176 Indent(1);
+
10177 if (s->base && !s->base->empty())
+
10178 Write(" + this.parent.fbeExtra");
+
10179 if (s->body)
+
10180 for (const auto& field : s->body->fields)
+
10181 Write(" + this." + *field->name + ".fbeExtra");
+
10182 WriteLine();
+
10183 Indent(-1);
+
10184 WriteLine();
+
10185 WriteLineIndent("this._buffer.unshift(fbeStructOffset)");
+
10186 WriteLine();
+
10187 WriteLineIndent("return fbeResult");
+
10188 Indent(-1);
+
10189 WriteLineIndent("}");
+
10190 WriteLine();
+
10191 WriteLineIndent("/**");
+
10192 WriteLineIndent(" * Get the field type");
+
10193 WriteLineIndent(" * @this {!FieldModel" + *s->name + "}");
+
10194 WriteLineIndent(" * @returns {!number} Field type");
+
10195 WriteLineIndent(" */");
+
10196 WriteLineIndent("get fbeType () {");
+
10197 Indent(1);
+
10198 WriteLineIndent("return FieldModel" + *s->name + ".fbeType");
+
10199 Indent(-1);
+
10200 WriteLineIndent("}");
+
10201 WriteLine();
+
10202 WriteLineIndent("/**");
+
10203 WriteLineIndent(" * Get the field type (static)");
+
10204 WriteLineIndent(" * @this {!FieldModel" + *s->name + "}");
+
10205 WriteLineIndent(" * @returns {!number} Field type");
+
10206 WriteLineIndent(" */");
+
10207 WriteLineIndent("static get fbeType () {");
+
10208 Indent(1);
+
10209 if (s->base && !s->base->empty() && (s->type == 0))
+
10210 WriteLineIndent("return " + ConvertTypeFieldName(*s->base, false) + ".fbeType");
+
10211 else
+
10212 WriteLineIndent("return " + std::to_string(s->type));
+
10213 Indent(-1);
+
10214 WriteLineIndent("}");
+
10215
+
10216 // Generate struct field model verify() method
+
10217 WriteLine();
+
10218 WriteLineIndent("/**");
+
10219 WriteLineIndent(" * Check if the struct value is valid");
+
10220 WriteLineIndent(" * @this {!FieldModel" + *s->name + "}");
+
10221 WriteLineIndent(" * @param {!boolean} fbeVerifyType Verify model type flag, defaults is true");
+
10222 WriteLineIndent(" * @returns {!boolean} Field model valid state");
+
10223 WriteLineIndent(" */");
+
10224 WriteLineIndent("verify (fbeVerifyType = true) {");
+
10225 Indent(1);
+
10226 WriteLineIndent("if ((this._buffer.offset + this.fbeOffset + this.fbeSize) > this._buffer.size) {");
+
10227 Indent(1);
+
10228 WriteLineIndent("return true");
+
10229 Indent(-1);
+
10230 WriteLineIndent("}");
+
10231 WriteLine();
+
10232 WriteLineIndent("let fbeStructOffset = this.readUInt32(this.fbeOffset)");
+
10233 WriteLineIndent("if ((fbeStructOffset === 0) || ((this._buffer.offset + fbeStructOffset + 4 + 4) > this._buffer.size)) {");
+
10234 Indent(1);
+
10235 WriteLineIndent("return false");
+
10236 Indent(-1);
+
10237 WriteLineIndent("}");
+
10238 WriteLine();
+
10239 WriteLineIndent("let fbeStructSize = this.readUInt32(fbeStructOffset)");
+
10240 WriteLineIndent("if (fbeStructSize < (4 + 4)) {");
+
10241 Indent(1);
+
10242 WriteLineIndent("return false");
+
10243 Indent(-1);
+
10244 WriteLineIndent("}");
+
10245 WriteLine();
+
10246 WriteLineIndent("let fbeStructType = this.readUInt32(fbeStructOffset + 4)");
+
10247 WriteLineIndent("if (fbeVerifyType && (fbeStructType !== this.fbeType)) {");
+
10248 Indent(1);
+
10249 WriteLineIndent("return false");
+
10250 Indent(-1);
+
10251 WriteLineIndent("}");
+
10252 WriteLine();
+
10253 WriteLineIndent("this._buffer.shift(fbeStructOffset)");
+
10254 WriteLineIndent("let fbeResult = this.verifyFields(fbeStructSize)");
+
10255 WriteLineIndent("this._buffer.unshift(fbeStructOffset)");
+
10256 WriteLineIndent("return fbeResult");
+
10257 Indent(-1);
+
10258 WriteLineIndent("}");
+
10259
+
10260 // Generate struct field model verifyFields() method
+
10261 WriteLine();
+
10262 WriteLineIndent("/**");
+
10263 WriteLineIndent(" * Check if the struct fields are valid");
+
10264 WriteLineIndent(" * @this {!FieldModel" + *s->name + "}");
+
10265 WriteLineIndent(" * @param {!number} fbeStructSize FBE struct size");
+
10266 WriteLineIndent(" * @returns {!boolean} Field model valid state");
+
10267 WriteLineIndent(" */");
+
10268 WriteLineIndent("verifyFields (fbeStructSize) {");
+
10269 Indent(1);
+
10270 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
10271 {
+
10272 WriteLineIndent("let fbeCurrentSize = 4 + 4");
+
10273 if (s->base && !s->base->empty())
+
10274 {
+
10275 WriteLine();
+
10276 WriteLineIndent("if ((fbeCurrentSize + this.parent.fbeBody - 4 - 4) > fbeStructSize) {");
+
10277 Indent(1);
+
10278 WriteLineIndent("return true");
+
10279 Indent(-1);
+
10280 WriteLineIndent("}");
+
10281 WriteLineIndent("if (!this.parent.verifyFields(fbeStructSize)) {");
+
10282 Indent(1);
+
10283 WriteLineIndent("return false");
+
10284 Indent(-1);
+
10285 WriteLineIndent("}");
+
10286 WriteLineIndent("// noinspection JSUnusedAssignment");
+
10287 WriteLineIndent("fbeCurrentSize += this.parent.fbeBody - 4 - 4");
+
10288 }
+
10289 if (s->body)
+
10290 {
+
10291 for (const auto& field : s->body->fields)
+
10292 {
+
10293 WriteLine();
+
10294 WriteLineIndent("if ((fbeCurrentSize + this." + *field->name + ".fbeSize) > fbeStructSize) {");
+
10295 Indent(1);
+
10296 WriteLineIndent("return true");
+
10297 Indent(-1);
+
10298 WriteLineIndent("}");
+
10299 WriteLineIndent("if (!this." + *field->name + ".verify()) {");
+
10300 Indent(1);
+
10301 WriteLineIndent("return false");
+
10302 Indent(-1);
+
10303 WriteLineIndent("}");
+
10304 WriteLineIndent("// noinspection JSUnusedAssignment");
+
10305 WriteLineIndent("fbeCurrentSize += this." + *field->name + ".fbeSize");
+
10306 }
+
10307 }
+
10308 WriteLine();
+
10309 }
+
10310 WriteLineIndent("return true");
+
10311 Indent(-1);
+
10312 WriteLineIndent("}");
+
10313
+
10314 // Generate struct field model getBegin() method
+
10315 WriteLine();
+
10316 WriteLineIndent("/**");
+
10317 WriteLineIndent(" * Get the struct value (begin phase)");
+
10318 WriteLineIndent(" * @this {!FieldModel" + *s->name + "}");
+
10319 WriteLineIndent(" * @returns {!number} Field model begin offset");
+
10320 WriteLineIndent(" */");
+
10321 WriteLineIndent("getBegin () {");
+
10322 Indent(1);
+
10323 WriteLineIndent("if ((this._buffer.offset + this.fbeOffset + this.fbeSize) > this._buffer.size) {");
+
10324 Indent(1);
+
10325 WriteLineIndent("return 0");
+
10326 Indent(-1);
+
10327 WriteLineIndent("}");
+
10328 WriteLine();
+
10329 WriteLineIndent("let fbeStructOffset = this.readUInt32(this.fbeOffset)");
+
10330 WriteLineIndent("console.assert((fbeStructOffset > 0) && ((this._buffer.offset + fbeStructOffset + 4 + 4) <= this._buffer.size), 'Model is broken!')");
+
10331 WriteLineIndent("if ((fbeStructOffset === 0) || ((this._buffer.offset + fbeStructOffset + 4 + 4) > this._buffer.size)) {");
+
10332 Indent(1);
+
10333 WriteLineIndent("return 0");
+
10334 Indent(-1);
+
10335 WriteLineIndent("}");
+
10336 WriteLine();
+
10337 WriteLineIndent("let fbeStructSize = this.readUInt32(fbeStructOffset)");
+
10338 WriteLineIndent("console.assert((fbeStructSize >= (4 + 4)), 'Model is broken!')");
+
10339 WriteLineIndent("if (fbeStructSize < (4 + 4)) {");
+
10340 Indent(1);
+
10341 WriteLineIndent("return 0");
+
10342 Indent(-1);
+
10343 WriteLineIndent("}");
+
10344 WriteLine();
+
10345 WriteLineIndent("this._buffer.shift(fbeStructOffset)");
+
10346 WriteLineIndent("return fbeStructOffset");
+
10347 Indent(-1);
+
10348 WriteLineIndent("}");
+
10349
+
10350 // Generate struct field model getEnd() method
+
10351 WriteLine();
+
10352 WriteLineIndent("/**");
+
10353 WriteLineIndent(" * Get the struct value (end phase)");
+
10354 WriteLineIndent(" * @this {!FieldModel" + *s->name + "}");
+
10355 WriteLineIndent(" * @param {!number} fbeBegin Field model begin offset");
+
10356 WriteLineIndent(" */");
+
10357 WriteLineIndent("getEnd (fbeBegin) {");
+
10358 Indent(1);
+
10359 WriteLineIndent("this._buffer.unshift(fbeBegin)");
+
10360 Indent(-1);
+
10361 WriteLineIndent("}");
+
10362
+
10363 // Generate struct field model get() method
+
10364 WriteLine();
+
10365 WriteLineIndent("/**");
+
10366 WriteLineIndent(" * Get the struct value");
+
10367 WriteLineIndent(" * @this {!FieldModel" + *s->name + "}");
+
10368 WriteLineIndent(" * @param {!" + *s->name + "} fbeValue Default value, defaults is new " + *s->name + "()");
+
10369 WriteLineIndent(" * @returns {!" + *s->name + "} " + *s->name + " value");
+
10370 WriteLineIndent(" */");
+
10371 WriteLineIndent("get (fbeValue = new " + *s->name + "()) {");
+
10372 Indent(1);
+
10373 WriteLineIndent("let fbeBegin = this.getBegin()");
+
10374 WriteLineIndent("if (fbeBegin === 0) {");
+
10375 Indent(1);
+
10376 WriteLineIndent("return fbeValue");
+
10377 Indent(-1);
+
10378 WriteLineIndent("}");
+
10379 WriteLine();
+
10380 WriteLineIndent("let fbeStructSize = this.readUInt32(0)");
+
10381 WriteLineIndent("this.getFields(fbeValue, fbeStructSize)");
+
10382 WriteLineIndent("this.getEnd(fbeBegin)");
+
10383 WriteLineIndent("return fbeValue");
+
10384 Indent(-1);
+
10385 WriteLineIndent("}");
+
10386
+
10387 // Generate struct field model getFields() method
+
10388 WriteLine();
+
10389 WriteLineIndent("/**");
+
10390 WriteLineIndent(" * Get the struct fields values");
+
10391 WriteLineIndent(" * @this {!FieldModel" + *s->name + "}");
+
10392 WriteLineIndent(" * @param {!" + *s->name + "} fbeValue " + *s->name + " value");
+
10393 WriteLineIndent(" * @param {!number} fbeStructSize Struct size");
+
10394 WriteLineIndent(" */");
+
10395 WriteLineIndent("getFields (fbeValue, fbeStructSize) {");
+
10396 Indent(1);
+
10397 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
10398 {
+
10399 WriteLineIndent("let fbeCurrentSize = 4 + 4");
+
10400 if (s->base && !s->base->empty())
+
10401 {
+
10402 WriteLine();
+
10403 WriteLineIndent("if ((fbeCurrentSize + this.parent.fbeBody - 4 - 4) <= fbeStructSize) {");
+
10404 Indent(1);
+
10405 WriteLineIndent("this.parent.getFields(fbeValue, fbeStructSize)");
+
10406 Indent(-1);
+
10407 WriteLineIndent("}");
+
10408 WriteLineIndent("// noinspection JSUnusedAssignment");
+
10409 WriteLineIndent("fbeCurrentSize += this.parent.fbeBody - 4 - 4");
+
10410 }
+
10411 if (s->body)
+
10412 {
+
10413 for (const auto& field : s->body->fields)
+
10414 {
+
10415 WriteLine();
+
10416 WriteLineIndent("if ((fbeCurrentSize + this." + *field->name + ".fbeSize) <= fbeStructSize) {");
+
10417 Indent(1);
+
10418 if (field->array || field->vector || field->list || field->set || field->map || field->hash)
+
10419 WriteLineIndent("this." + *field->name + ".get(fbeValue." + *field->name + ")");
+
10420 else
+
10421 WriteLineIndent("fbeValue." + *field->name + " = this." + *field->name + ".get(" + (field->value ? ConvertConstant(*field->type, *field->value, field->optional) : "") + ")");
+
10422 Indent(-1);
+
10423 WriteLineIndent("} else {");
+
10424 Indent(1);
+
10425 if (field->array || field->vector || field->list)
+
10426 WriteLineIndent("fbeValue." + *field->name + ".length = 0");
+
10427 else if (field->set || field->map || field->hash)
+
10428 WriteLineIndent("fbeValue." + *field->name + ".clear()");
+
10429 else
+
10430 WriteLineIndent("fbeValue." + *field->name + " = " + ConvertDefault(*field));
+
10431 Indent(-1);
+
10432 WriteLineIndent("}");
+
10433 WriteLineIndent("// noinspection JSUnusedAssignment");
+
10434 WriteLineIndent("fbeCurrentSize += this." + *field->name + ".fbeSize");
+
10435 }
+
10436 }
+
10437 }
+
10438 Indent(-1);
+
10439 WriteLineIndent("}");
+
10440
+
10441 // Generate struct field model setBegin() method
+
10442 WriteLine();
+
10443 WriteLineIndent("/**");
+
10444 WriteLineIndent(" * Set the struct value (begin phase)");
+
10445 WriteLineIndent(" * @this {!FieldModel" + *s->name + "}");
+
10446 WriteLineIndent(" * @returns {!number} Field model begin offset");
+
10447 WriteLineIndent(" */");
+
10448 WriteLineIndent("setBegin () {");
+
10449 Indent(1);
+
10450 WriteLineIndent("console.assert(((this._buffer.offset + this.fbeOffset + this.fbeSize) <= this._buffer.size), 'Model is broken!')");
+
10451 WriteLineIndent("if ((this._buffer.offset + this.fbeOffset + this.fbeSize) > this._buffer.size) {");
+
10452 Indent(1);
+
10453 WriteLineIndent("return 0");
+
10454 Indent(-1);
+
10455 WriteLineIndent("}");
+
10456 WriteLine();
+
10457 WriteLineIndent("let fbeStructSize = this.fbeBody");
+
10458 WriteLineIndent("let fbeStructOffset = this._buffer.allocate(fbeStructSize) - this._buffer.offset");
+
10459 WriteLineIndent("console.assert((fbeStructOffset > 0) && ((this._buffer.offset + fbeStructOffset + fbeStructSize) <= this._buffer.size), 'Model is broken!')");
+
10460 WriteLineIndent("if ((fbeStructOffset <= 0) || ((this._buffer.offset + fbeStructOffset + fbeStructSize) > this._buffer.size)) {");
+
10461 Indent(1);
+
10462 WriteLineIndent("return 0");
+
10463 Indent(-1);
+
10464 WriteLineIndent("}");
+
10465 WriteLine();
+
10466 WriteLineIndent("this.writeUInt32(this.fbeOffset, fbeStructOffset)");
+
10467 WriteLineIndent("this.writeUInt32(fbeStructOffset, fbeStructSize)");
+
10468 WriteLineIndent("this.writeUInt32(fbeStructOffset + 4, this.fbeType)");
+
10469 WriteLine();
+
10470 WriteLineIndent("this._buffer.shift(fbeStructOffset)");
+
10471 WriteLineIndent("return fbeStructOffset");
+
10472 Indent(-1);
+
10473 WriteLineIndent("}");
+
10474
+
10475 // Generate struct field model setEnd() method
+
10476 WriteLine();
+
10477 WriteLineIndent("/**");
+
10478 WriteLineIndent(" * Set the struct value (end phase)");
+
10479 WriteLineIndent(" * @this {!FieldModel" + *s->name + "}");
+
10480 WriteLineIndent(" * @param {!number} fbeBegin Field model begin offset");
+
10481 WriteLineIndent(" */");
+
10482 WriteLineIndent("setEnd (fbeBegin) {");
+
10483 Indent(1);
+
10484 WriteLineIndent("this._buffer.unshift(fbeBegin)");
+
10485 Indent(-1);
+
10486 WriteLineIndent("}");
+
10487
+
10488 // Generate struct field model set() method
+
10489 WriteLine();
+
10490 WriteLineIndent("/**");
+
10491 WriteLineIndent(" * Set the struct value");
+
10492 WriteLineIndent(" * @this {!FieldModel" + *s->name + "}");
+
10493 WriteLineIndent(" * @param {!" + *s->name + "} fbeValue " + *s->name + " value");
+
10494 WriteLineIndent(" */");
+
10495 WriteLineIndent("set (fbeValue) {");
+
10496 Indent(1);
+
10497 WriteLineIndent("let fbeBegin = this.setBegin()");
+
10498 WriteLineIndent("if (fbeBegin === 0) {");
+
10499 Indent(1);
+
10500 WriteLineIndent("return");
+
10501 Indent(-1);
+
10502 WriteLineIndent("}");
+
10503 WriteLine();
+
10504 WriteLineIndent("this.setFields(fbeValue)");
+
10505 WriteLineIndent("this.setEnd(fbeBegin)");
+
10506 Indent(-1);
+
10507 WriteLineIndent("}");
+
10508
+
10509 // Generate struct field model setFields() method
+
10510 WriteLine();
+
10511 WriteLineIndent("/**");
+
10512 WriteLineIndent(" * Set the struct fields values");
+
10513 WriteLineIndent(" * @this {!FieldModel" + *s->name + "}");
+
10514 WriteLineIndent(" * @param {" + *s->name + "} fbeValue " + *s->name + " value");
+
10515 WriteLineIndent(" */");
+
10516 WriteLineIndent("setFields (fbeValue) {");
+
10517 Indent(1);
+
10518 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
10519 {
+
10520 if (s->base && !s->base->empty())
+
10521 WriteLineIndent("this.parent.setFields(fbeValue)");
+
10522 if (s->body)
+
10523 for (const auto& field : s->body->fields)
+
10524 WriteLineIndent("this." + *field->name + ".set(fbeValue." + *field->name + ")");
+
10525 }
+
10526 Indent(-1);
+
10527 WriteLineIndent("}");
+
10528
+
10529 // Generate struct field model end
+
10530 Indent(-1);
+
10531 WriteLineIndent("}");
+
10532
+
10533 // Generate struct field model exports
+
10534 WriteLine();
+
10535 WriteLineIndent("exports.FieldModel" + *s->name + " = FieldModel" + *s->name);
+
10536}
+
10537
+
10538void GeneratorJavaScript::GenerateStructModel(const std::shared_ptr<StructType>& s)
+
10539{
+
10540 // Generate struct model begin
+
10541 WriteLine();
+
10542 WriteLineIndent("/**");
+
10543 WriteLineIndent(" * Fast Binary Encoding " + *s->name + " model");
+
10544 WriteLineIndent(" */");
+
10545 WriteLineIndent("class " + *s->name + "Model extends fbe.Model {");
+
10546 Indent(1);
+
10547
+
10548 // Generate struct model constructor
+
10549 WriteLineIndent("/**");
+
10550 WriteLineIndent(" * Initialize model with the given buffer");
+
10551 WriteLineIndent(" * @param {!fbe.ReadBuffer|!fbe.WriteBuffer} buffer Read/Write buffer, defaults is new fbe.WriteBuffer()");
+
10552 WriteLineIndent(" * @constructor");
+
10553 WriteLineIndent(" */");
+
10554 WriteLineIndent("constructor (buffer = new fbe.WriteBuffer()) {");
+
10555 Indent(1);
+
10556 WriteLineIndent("super(buffer)");
+
10557 WriteLineIndent("this._model = new FieldModel" + *s->name + "(this.buffer, 4)");
+
10558 Indent(-1);
+
10559 WriteLineIndent("}");
+
10560
+
10561 // Generate struct model accessor
+
10562 WriteLine();
+
10563 WriteLineIndent("/**");
+
10564 WriteLineIndent(" * Get the " + *s->name + " model");
+
10565 WriteLineIndent(" * @this {!" + *s->name + "Model}");
+
10566 WriteLineIndent(" * @returns {!FieldModel" + *s->name + "} model " + *s->name + " model");
+
10567 WriteLineIndent(" */");
+
10568 WriteLineIndent("get model () {");
+
10569 Indent(1);
+
10570 WriteLineIndent("return this._model");
+
10571 Indent(-1);
+
10572 WriteLineIndent("}");
+
10573
+
10574 // Generate struct model FBE properties
+
10575 WriteLine();
+
10576 WriteLineIndent("/**");
+
10577 WriteLineIndent(" * Get the model size");
+
10578 WriteLineIndent(" * @this {!" + *s->name + "Model}");
+
10579 WriteLineIndent(" * @returns {!number} Model size");
+
10580 WriteLineIndent(" */");
+
10581 WriteLineIndent("get fbeSize () {");
+
10582 Indent(1);
+
10583 WriteLineIndent("return this.model.fbeSize + this.model.fbeExtra");
+
10584 Indent(-1);
+
10585 WriteLineIndent("}");
+
10586 WriteLine();
+
10587 WriteLineIndent("/**");
+
10588 WriteLineIndent(" * Get the model type");
+
10589 WriteLineIndent(" * @this {!" + *s->name + "Model}");
+
10590 WriteLineIndent(" * @returns {!number} Model type");
+
10591 WriteLineIndent(" */");
+
10592 WriteLineIndent("get fbeType () {");
+
10593 Indent(1);
+
10594 WriteLineIndent("return " + *s->name + "Model.fbeType");
+
10595 Indent(-1);
+
10596 WriteLineIndent("}");
+
10597 WriteLine();
+
10598 WriteLineIndent("/**");
+
10599 WriteLineIndent(" * Get the model type (static)");
+
10600 WriteLineIndent(" * @this {!" + *s->name + "Model}");
+
10601 WriteLineIndent(" * @returns {!number} Model type");
+
10602 WriteLineIndent(" */");
+
10603 WriteLineIndent("static get fbeType () {");
+
10604 Indent(1);
+
10605 WriteLineIndent("return FieldModel" + *s->name + ".fbeType");
+
10606 Indent(-1);
+
10607 WriteLineIndent("}");
+
10608
+
10609 // Generate struct model verify() method
+
10610 WriteLine();
+
10611 WriteLineIndent("/**");
+
10612 WriteLineIndent(" * Check if the struct value is valid");
+
10613 WriteLineIndent(" * @this {!" + *s->name + "Model}");
+
10614 WriteLineIndent(" * @returns {!boolean} Model valid state");
+
10615 WriteLineIndent(" */");
+
10616 WriteLineIndent("verify () {");
+
10617 Indent(1);
+
10618 WriteLineIndent("if ((this.buffer.offset + this.model.fbeOffset - 4) > this.buffer.size) {");
+
10619 Indent(1);
+
10620 WriteLineIndent("return false");
+
10621 Indent(-1);
+
10622 WriteLineIndent("}");
+
10623 WriteLine();
+
10624 WriteLineIndent("let fbeFullSize = this.readUInt32(this.model.fbeOffset - 4)");
+
10625 WriteLineIndent("if (fbeFullSize < this.model.fbeSize) {");
+
10626 Indent(1);
+
10627 WriteLineIndent("return false");
+
10628 Indent(-1);
+
10629 WriteLineIndent("}");
+
10630 WriteLine();
+
10631 WriteLineIndent("return this.model.verify()");
+
10632 Indent(-1);
+
10633 WriteLineIndent("}");
+
10634
+
10635 // Generate struct model createBegin() method
+
10636 WriteLine();
+
10637 WriteLineIndent("/**");
+
10638 WriteLineIndent(" * Create a new model (begin phase)");
+
10639 WriteLineIndent(" * @this {!" + *s->name + "Model}");
+
10640 WriteLineIndent(" * @returns {!number} Model begin offset");
+
10641 WriteLineIndent(" */");
+
10642 WriteLineIndent("createBegin () {");
+
10643 Indent(1);
+
10644 WriteLineIndent("return this.buffer.allocate(4 + this.model.fbeSize)");
+
10645 Indent(-1);
+
10646 WriteLineIndent("}");
+
10647
+
10648 // Generate struct model createEnd() method
+
10649 WriteLine();
+
10650 WriteLineIndent("/**");
+
10651 WriteLineIndent(" * Create a new model (end phase)");
+
10652 WriteLineIndent(" * @this {!" + *s->name + "Model}");
+
10653 WriteLineIndent(" * @param {!number} fbeBegin Model begin offset");
+
10654 WriteLineIndent(" */");
+
10655 WriteLineIndent("createEnd (fbeBegin) {");
+
10656 Indent(1);
+
10657 WriteLineIndent("let fbeEnd = this.buffer.size");
+
10658 WriteLineIndent("let fbeFullSize = fbeEnd - fbeBegin");
+
10659 WriteLineIndent("this.writeUInt32(this.model.fbeOffset - 4, fbeFullSize)");
+
10660 WriteLineIndent("return fbeFullSize");
+
10661 Indent(-1);
+
10662 WriteLineIndent("}");
+
10663
+
10664 // Generate struct model serialize() method
+
10665 WriteLine();
+
10666 WriteLineIndent("/**");
+
10667 WriteLineIndent(" * Serialize the struct value");
+
10668 WriteLineIndent(" * @this {!" + *s->name + "Model}");
+
10669 WriteLineIndent(" * @param {!" + *s->name + "} value " + *s->name + " value");
+
10670 WriteLineIndent(" * @return {!number} Model begin offset");
+
10671 WriteLineIndent(" */");
+
10672 WriteLineIndent("serialize (value) {");
+
10673 Indent(1);
+
10674 WriteLineIndent("let fbeBegin = this.createBegin()");
+
10675 WriteLineIndent("this.model.set(value)");
+
10676 WriteLineIndent("return this.createEnd(fbeBegin)");
+
10677 Indent(-1);
+
10678 WriteLineIndent("}");
+
10679
+
10680 // Generate struct model deserialize() methods
+
10681 WriteLine();
+
10682 WriteLineIndent("/**");
+
10683 WriteLineIndent(" * Deserialize the struct value");
+
10684 WriteLineIndent(" * @this {!" + *s->name + "Model}");
+
10685 WriteLineIndent(" * @param {!" + *s->name + "} value " + *s->name + " value, defaults is new " + *s->name + "()");
+
10686 WriteLineIndent(" * @return {!object} Deserialized " + *s->name + " value and its size");
+
10687 WriteLineIndent(" */");
+
10688 WriteLineIndent("deserialize (value = new " + *s->name + "()) {");
+
10689 Indent(1);
+
10690 WriteLineIndent("if ((this.buffer.offset + this.model.fbeOffset - 4) > this.buffer.size) {");
+
10691 Indent(1);
+
10692 WriteLineIndent("return { value: new " + *s->name + "(), size: 0 }");
+
10693 Indent(-1);
+
10694 WriteLineIndent("}");
+
10695 WriteLine();
+
10696 WriteLineIndent("let fbeFullSize = this.readUInt32(this.model.fbeOffset - 4)");
+
10697 WriteLineIndent("console.assert((fbeFullSize >= this.model.fbeSize), 'Model is broken!')");
+
10698 WriteLineIndent("if (fbeFullSize < this.model.fbeSize) {");
+
10699 Indent(1);
+
10700 WriteLineIndent("return { value: new " + *s->name + "(), size: 0 }");
+
10701 Indent(-1);
+
10702 WriteLineIndent("}");
+
10703 WriteLine();
+
10704 WriteLineIndent("this.model.get(value)");
+
10705 WriteLineIndent("return { value: value, size: fbeFullSize }");
+
10706 Indent(-1);
+
10707 WriteLineIndent("}");
+
10708
+
10709 // Generate struct model next() method
+
10710 WriteLine();
+
10711 WriteLineIndent("/**");
+
10712 WriteLineIndent(" * Move to the next struct value");
+
10713 WriteLineIndent(" * @this {!" + *s->name + "Model}");
+
10714 WriteLineIndent(" * @param {!number} prev Previous " + *s->name + " model size");
+
10715 WriteLineIndent(" */");
+
10716 WriteLineIndent("next (prev) {");
+
10717 Indent(1);
+
10718 WriteLineIndent("this.model.fbeShift(prev)");
+
10719 Indent(-1);
+
10720 WriteLineIndent("}");
+
10721
+
10722 // Generate struct model end
+
10723 Indent(-1);
+
10724 WriteLineIndent("}");
+
10725
+
10726 // Generate struct model exports
+
10727 WriteLine();
+
10728 WriteLineIndent("exports." + *s->name + "Model = " + *s->name + "Model");
+
10729}
+
10730
+
10731void GeneratorJavaScript::GenerateStructFinalModel(const std::shared_ptr<StructType>& s)
+
10732{
+
10733 // Generate struct final model begin
+
10734 WriteLine();
+
10735 WriteLineIndent("/**");
+
10736 WriteLineIndent(" * Fast Binary Encoding " + *s->name + " final model");
+
10737 WriteLineIndent(" */");
+
10738 WriteLineIndent("class FinalModel" + *s->name + " extends fbe.FinalModel {");
+
10739 Indent(1);
+
10740
+
10741 // Generate struct final model constructor
+
10742 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
10743 {
+
10744 WriteLineIndent("/**");
+
10745 WriteLineIndent(" * Initialize final model with the given buffer and offset");
+
10746 WriteLineIndent(" * @param {!fbe.ReadBuffer|!fbe.WriteBuffer} buffer Buffer");
+
10747 WriteLineIndent(" * @param {!number} offset Offset");
+
10748 WriteLineIndent(" * @constructor");
+
10749 WriteLineIndent(" */");
+
10750 WriteLineIndent("constructor (buffer, offset) {");
+
10751 Indent(1);
+
10752 WriteLineIndent("super(buffer, offset)");
+
10753 if (s->base && !s->base->empty())
+
10754 WriteLineIndent("this._parent = new " + ConvertTypeFieldName(*s->base, true) + "(buffer, 0)");
+
10755 if (s->body)
+
10756 for (const auto& field : s->body->fields)
+
10757 WriteLineIndent("this._" + *field->name + " = new " + ConvertTypeFieldInitialization(*field, "0", true));
+
10758 Indent(-1);
+
10759 WriteLineIndent("}");
+
10760 WriteLine();
+
10761 }
+
10762
+
10763 // Generate struct final model accessors
+
10764 if (s->base && !s->base->empty())
+
10765 {
+
10766 WriteLineIndent("/**");
+
10767 WriteLineIndent(" * Get the " + *s->base + " final model");
+
10768 WriteLineIndent(" * @this {!FinalModel" + *s->name + "}");
+
10769 WriteLineIndent(" * @returns {!" + ConvertTypeFieldName(*s->base, true) + "} " + *s->base + " field model");
+
10770 WriteLineIndent(" */");
+
10771 WriteLineIndent("get parent () {");
+
10772 Indent(1);
+
10773 WriteLineIndent("return this._parent");
+
10774 Indent(-1);
+
10775 WriteLineIndent("}");
+
10776 WriteLine();
+
10777 }
+
10778 if (s->body)
+
10779 {
+
10780 for (const auto& field : s->body->fields)
+
10781 {
+
10782 WriteLineIndent("/**");
+
10783 WriteLineIndent(" * Get the " + *field->name + " final model");
+
10784 WriteLineIndent(" * @this {!FinalModel" + *s->name + "}");
+
10785 WriteLineIndent(" * @returns {!" + ConvertTypeFieldDeclaration(*field, true) + "} " + *field->name + " final model");
+
10786 WriteLineIndent(" */");
+
10787 WriteLineIndent("get " + *field->name + " () {");
+
10788 Indent(1);
+
10789 WriteLineIndent("return this._" + *field->name);
+
10790 Indent(-1);
+
10791 WriteLineIndent("}");
+
10792 WriteLine();
+
10793 }
+
10794 }
+
10795
+
10796 // Generate struct final model FBE properties
+
10797 WriteLineIndent("/**");
+
10798 WriteLineIndent(" * Get the allocation size");
+
10799 WriteLineIndent(" * @this {!FinalModel" + *s->name + "}");
+
10800 WriteLineIndent(" * @param {!" + *s->name + "} fbeValue " + *s->name + " value");
+
10801 WriteLineIndent(" * @returns {!number} Allocation size");
+
10802 WriteLineIndent(" */");
+
10803 WriteLineIndent("fbeAllocationSize (fbeValue) {");
+
10804 Indent(1);
+
10805 WriteIndent("return 0");
+
10806 if (s->base && !s->base->empty())
+
10807 Write(" + this.parent.fbeAllocationSize(fbeValue)");
+
10808 if (s->body)
+
10809 for (const auto& field : s->body->fields)
+
10810 Write(" + this." + *field->name + ".fbeAllocationSize(fbeValue." + *field->name + ")");
+
10811 WriteLine();
+
10812 Indent(-1);
+
10813 WriteLineIndent("}");
+
10814 WriteLine();
+
10815 WriteLineIndent("/**");
+
10816 WriteLineIndent(" * Get the final type");
+
10817 WriteLineIndent(" * @this {!FinalModel" + *s->name + "}");
+
10818 WriteLineIndent(" * @returns {!number} Final type");
+
10819 WriteLineIndent(" */");
+
10820 WriteLineIndent("get fbeType () {");
+
10821 Indent(1);
+
10822 WriteLineIndent("return FinalModel" + *s->name + ".fbeType");
+
10823 Indent(-1);
+
10824 WriteLineIndent("}");
+
10825 WriteLine();
+
10826 WriteLineIndent("/**");
+
10827 WriteLineIndent(" * Get the final type (static)");
+
10828 WriteLineIndent(" * @this {!FinalModel" + *s->name + "}");
+
10829 WriteLineIndent(" * @returns {!number} Final type");
+
10830 WriteLineIndent(" */");
+
10831 WriteLineIndent("static get fbeType () {");
+
10832 Indent(1);
+
10833 if (s->base && !s->base->empty() && (s->type == 0))
+
10834 WriteLineIndent("return " + ConvertTypeFieldName(*s->base, true) + ".fbeType");
+
10835 else
+
10836 WriteLineIndent("return " + std::to_string(s->type));
+
10837 Indent(-1);
+
10838 WriteLineIndent("}");
+
10839
+
10840 // Generate struct final model verify() method
+
10841 WriteLine();
+
10842 WriteLineIndent("/**");
+
10843 WriteLineIndent(" * Check if the struct value is valid");
+
10844 WriteLineIndent(" * @this {!FinalModel" + *s->name + "}");
+
10845 WriteLineIndent(" * @returns {!number} Final model size or Number.MAX_SAFE_INTEGER in case of any error");
+
10846 WriteLineIndent(" */");
+
10847 WriteLineIndent("verify () {");
+
10848 Indent(1);
+
10849 WriteLineIndent("this._buffer.shift(this.fbeOffset)");
+
10850 WriteLineIndent("let fbeResult = this.verifyFields()");
+
10851 WriteLineIndent("this._buffer.unshift(this.fbeOffset)");
+
10852 WriteLineIndent("return fbeResult");
+
10853 Indent(-1);
+
10854 WriteLineIndent("}");
+
10855
+
10856 // Generate struct final model verifyFields() method
+
10857 WriteLine();
+
10858 WriteLineIndent("/**");
+
10859 WriteLineIndent(" * Check if the struct fields are valid");
+
10860 WriteLineIndent(" * @this {!FinalModel" + *s->name + "}");
+
10861 WriteLineIndent(" * @returns {!number} Final model size or Number.MAX_SAFE_INTEGER in case of any error");
+
10862 WriteLineIndent(" */");
+
10863 WriteLineIndent("verifyFields () {");
+
10864 Indent(1);
+
10865 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
10866 {
+
10867 WriteLineIndent("let fbeCurrentOffset = 0");
+
10868 WriteLineIndent("let fbeFieldSize");
+
10869 if (s->base && !s->base->empty())
+
10870 {
+
10871 WriteLine();
+
10872 WriteLineIndent("this.parent.fbeOffset = fbeCurrentOffset");
+
10873 WriteLineIndent("fbeFieldSize = this.parent.verifyFields()");
+
10874 WriteLineIndent("if (fbeFieldSize === Number.MAX_SAFE_INTEGER) {");
+
10875 Indent(1);
+
10876 WriteLineIndent("return Number.MAX_SAFE_INTEGER");
+
10877 Indent(-1);
+
10878 WriteLineIndent("}");
+
10879 WriteLineIndent("fbeCurrentOffset += fbeFieldSize");
+
10880 }
+
10881 if (s->body)
+
10882 {
+
10883 for (const auto& field : s->body->fields)
+
10884 {
+
10885 WriteLine();
+
10886 WriteLineIndent("this." + *field->name + ".fbeOffset = fbeCurrentOffset");
+
10887 WriteLineIndent("fbeFieldSize = this." + *field->name + ".verify()");
+
10888 WriteLineIndent("if (fbeFieldSize === Number.MAX_SAFE_INTEGER) {");
+
10889 Indent(1);
+
10890 WriteLineIndent("return Number.MAX_SAFE_INTEGER");
+
10891 Indent(-1);
+
10892 WriteLineIndent("}");
+
10893 WriteLineIndent("fbeCurrentOffset += fbeFieldSize");
+
10894 }
+
10895 }
+
10896 WriteLine();
+
10897 WriteLineIndent("return fbeCurrentOffset");
+
10898 }
+
10899 else
+
10900 WriteLineIndent("return 0");
+
10901 Indent(-1);
+
10902 WriteLineIndent("}");
+
10903
+
10904 // Generate struct final model get() method
+
10905 WriteLine();
+
10906 WriteLineIndent("/**");
+
10907 WriteLineIndent(" * Get the struct value");
+
10908 WriteLineIndent(" * @this {!FinalModel" + *s->name + "}");
+
10909 WriteLineIndent(" * @param {!" + *s->name + "} fbeValue " + *s->name + " value, defaults is new " + *s->name + "()");
+
10910 WriteLineIndent(" * @returns {!object} Result struct value and its size");
+
10911 WriteLineIndent(" */");
+
10912 WriteLineIndent("get (fbeValue = new " + *s->name + "()) {");
+
10913 Indent(1);
+
10914 WriteLineIndent("this._buffer.shift(this.fbeOffset)");
+
10915 WriteLineIndent("let fbeSize = this.getFields(fbeValue)");
+
10916 WriteLineIndent("this._buffer.unshift(this.fbeOffset)");
+
10917 WriteLineIndent("return { value: fbeValue, size: fbeSize }");
+
10918 Indent(-1);
+
10919 WriteLineIndent("}");
+
10920
+
10921 // Generate struct final model getFields() method
+
10922 WriteLine();
+
10923 WriteLineIndent("/**");
+
10924 WriteLineIndent(" * Get the struct fields values");
+
10925 WriteLineIndent(" * @this {!FinalModel" + *s->name + "}");
+
10926 WriteLineIndent(" * @param {!" + *s->name + "} fbeValue " + *s->name + " value");
+
10927 WriteLineIndent(" * @returns {!number} Struct size");
+
10928 WriteLineIndent(" */");
+
10929 WriteLineIndent("getFields (fbeValue) {");
+
10930 Indent(1);
+
10931 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
10932 {
+
10933 WriteLineIndent("let fbeCurrentOffset = 0");
+
10934 WriteLineIndent("let fbeCurrentSize = 0");
+
10935 WriteLineIndent("let fbeResult");
+
10936 if (s->base && !s->base->empty())
+
10937 {
+
10938 WriteLine();
+
10939 WriteLineIndent("this.parent.fbeOffset = fbeCurrentOffset");
+
10940 WriteLineIndent("fbeResult = this.parent.getFields(fbeValue)");
+
10941 WriteLineIndent("// noinspection JSUnusedAssignment");
+
10942 WriteLineIndent("fbeCurrentOffset += fbeResult");
+
10943 WriteLineIndent("fbeCurrentSize += fbeResult");
+
10944 }
+
10945 if (s->body)
+
10946 {
+
10947 for (const auto& field : s->body->fields)
+
10948 {
+
10949 WriteLine();
+
10950 WriteLineIndent("this." + *field->name + ".fbeOffset = fbeCurrentOffset");
+
10951 if (field->array || field->vector || field->list || field->set || field->map || field->hash)
+
10952 WriteLineIndent("fbeResult = this." + *field->name + ".get(fbeValue." + *field->name + ")");
+
10953 else
+
10954 {
+
10955 WriteLineIndent("fbeResult = this." + *field->name + ".get()");
+
10956 WriteLineIndent("fbeValue." + *field->name + " = fbeResult.value");
+
10957 }
+
10958 WriteLineIndent("// noinspection JSUnusedAssignment");
+
10959 WriteLineIndent("fbeCurrentOffset += fbeResult.size");
+
10960 WriteLineIndent("fbeCurrentSize += fbeResult.size");
+
10961 }
+
10962 }
+
10963 WriteLine();
+
10964 WriteLineIndent("return fbeCurrentSize");
+
10965 }
+
10966 else
+
10967 WriteLineIndent("return 0");
+
10968 Indent(-1);
+
10969 WriteLineIndent("}");
+
10970
+
10971 // Generate struct final model set() method
+
10972 WriteLine();
+
10973 WriteLineIndent("/**");
+
10974 WriteLineIndent(" * Set the struct value");
+
10975 WriteLineIndent(" * @this {!FinalModel" + *s->name + "}");
+
10976 WriteLineIndent(" * @param {!" + *s->name + "} fbeValue " + *s->name + " value");
+
10977 WriteLineIndent(" * @returns {!number} Final model size");
+
10978 WriteLineIndent(" */");
+
10979 WriteLineIndent("set (fbeValue) {");
+
10980 Indent(1);
+
10981 WriteLineIndent("this._buffer.shift(this.fbeOffset)");
+
10982 WriteLineIndent("let fbeSize = this.setFields(fbeValue)");
+
10983 WriteLineIndent("this._buffer.unshift(this.fbeOffset)");
+
10984 WriteLineIndent("return fbeSize");
+
10985 Indent(-1);
+
10986 WriteLineIndent("}");
+
10987
+
10988 // Generate struct final model setFields() method
+
10989 WriteLine();
+
10990 WriteLineIndent("/**");
+
10991 WriteLineIndent(" * Set the struct fields values");
+
10992 WriteLineIndent(" * @this {!FinalModel" + *s->name + "}");
+
10993 WriteLineIndent(" * @param {" + *s->name + "} fbeValue " + *s->name + " value");
+
10994 WriteLineIndent(" * @returns {!number} Final model size");
+
10995 WriteLineIndent(" */");
+
10996 WriteLineIndent("setFields (fbeValue) {");
+
10997 Indent(1);
+
10998 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
10999 {
+
11000 WriteLineIndent("let fbeCurrentOffset = 0");
+
11001 WriteLineIndent("let fbeCurrentSize = 0");
+
11002 WriteLineIndent("let fbeFieldSize");
+
11003 if (s->base && !s->base->empty())
+
11004 {
+
11005 WriteLine();
+
11006 WriteLineIndent("this.parent.fbeOffset = fbeCurrentOffset");
+
11007 WriteLineIndent("fbeFieldSize = this.parent.setFields(fbeValue)");
+
11008 WriteLineIndent("// noinspection JSUnusedAssignment");
+
11009 WriteLineIndent("fbeCurrentOffset += fbeFieldSize");
+
11010 WriteLineIndent("fbeCurrentSize += fbeFieldSize");
+
11011 }
+
11012 if (s->body)
+
11013 {
+
11014 for (const auto& field : s->body->fields)
+
11015 {
+
11016 WriteLine();
+
11017 WriteLineIndent("this." + *field->name + ".fbeOffset = fbeCurrentOffset");
+
11018 WriteLineIndent("fbeFieldSize = this." + *field->name + ".set(fbeValue." + *field->name + ")");
+
11019 WriteLineIndent("// noinspection JSUnusedAssignment");
+
11020 WriteLineIndent("fbeCurrentOffset += fbeFieldSize");
+
11021 WriteLineIndent("fbeCurrentSize += fbeFieldSize");
+
11022 }
+
11023 }
+
11024 WriteLine();
+
11025 WriteLineIndent("return fbeCurrentSize");
+
11026 }
+
11027 else
+
11028 WriteLineIndent("return 0");
+
11029 Indent(-1);
+
11030 WriteLineIndent("}");
+
11031
+
11032 // Generate struct final model end
+
11033 Indent(-1);
+
11034 WriteLineIndent("}");
+
11035
+
11036 // Generate struct final model exports
+
11037 WriteLine();
+
11038 WriteLineIndent("exports.FinalModel" + *s->name + " = FinalModel" + *s->name);
+
11039}
+
11040
+
11041void GeneratorJavaScript::GenerateStructModelFinal(const std::shared_ptr<StructType>& s)
+
11042{
+
11043 // Generate struct model final begin
+
11044 WriteLine();
+
11045 WriteLineIndent("/**");
+
11046 WriteLineIndent(" * Fast Binary Encoding " + *s->name + " final model");
+
11047 WriteLineIndent(" */");
+
11048 WriteLineIndent("class " + *s->name + "FinalModel extends fbe.Model {");
+
11049 Indent(1);
+
11050
+
11051 // Generate struct model final constructor
+
11052 WriteLineIndent("/**");
+
11053 WriteLineIndent(" * Initialize final model with the given buffer");
+
11054 WriteLineIndent(" * @param {!fbe.ReadBuffer|!fbe.WriteBuffer} buffer Read/Write buffer, defaults is new fbe.WriteBuffer()");
+
11055 WriteLineIndent(" * @constructor");
+
11056 WriteLineIndent(" */");
+
11057 WriteLineIndent("constructor (buffer = new fbe.WriteBuffer()) {");
+
11058 Indent(1);
+
11059 WriteLineIndent("super(buffer)");
+
11060 WriteLineIndent("this._model = new FinalModel" + *s->name + "(this.buffer, 8)");
+
11061 Indent(-1);
+
11062 WriteLineIndent("}");
+
11063
+
11064 // Generate struct model final FBE properties
+
11065 WriteLine();
+
11066 WriteLineIndent("/**");
+
11067 WriteLineIndent(" * Get the model type");
+
11068 WriteLineIndent(" * @this {!" + *s->name + "FinalModel}");
+
11069 WriteLineIndent(" * @returns {!number} Model type");
+
11070 WriteLineIndent(" */");
+
11071 WriteLineIndent("get fbeType () {");
+
11072 Indent(1);
+
11073 WriteLineIndent("return " + *s->name + "FinalModel.fbeType");
+
11074 Indent(-1);
+
11075 WriteLineIndent("}");
+
11076 WriteLine();
+
11077 WriteLineIndent("/**");
+
11078 WriteLineIndent(" * Get the model type (static)");
+
11079 WriteLineIndent(" * @this {!" + *s->name + "FinalModel}");
+
11080 WriteLineIndent(" * @returns {!number} Model type");
+
11081 WriteLineIndent(" */");
+
11082 WriteLineIndent("static get fbeType () {");
+
11083 Indent(1);
+
11084 WriteLineIndent("return FinalModel" + *s->name + ".fbeType");
+
11085 Indent(-1);
+
11086 WriteLineIndent("}");
+
11087
+
11088 // Generate struct model final verify() method
+
11089 WriteLine();
+
11090 WriteLineIndent("/**");
+
11091 WriteLineIndent(" * Check if the struct value is valid");
+
11092 WriteLineIndent(" * @this {!" + *s->name + "FinalModel}");
+
11093 WriteLineIndent(" * @returns {!boolean} Model valid state");
+
11094 WriteLineIndent(" */");
+
11095 WriteLineIndent("verify () {");
+
11096 Indent(1);
+
11097 WriteLineIndent("if ((this.buffer.offset + this._model.fbeOffset) > this.buffer.size) {");
+
11098 Indent(1);
+
11099 WriteLineIndent("return false");
+
11100 Indent(-1);
+
11101 WriteLineIndent("}");
+
11102 WriteLine();
+
11103 WriteLineIndent("let fbeStructSize = this.readUInt32(this._model.fbeOffset - 8)");
+
11104 WriteLineIndent("let fbeStructType = this.readUInt32(this._model.fbeOffset - 4)");
+
11105 WriteLineIndent("if ((fbeStructSize <= 0) || (fbeStructType !== this.fbeType)) {");
+
11106 Indent(1);
+
11107 WriteLineIndent("return false");
+
11108 Indent(-1);
+
11109 WriteLineIndent("}");
+
11110 WriteLine();
+
11111 WriteLineIndent("return ((8 + this._model.verify()) === fbeStructSize)");
+
11112 Indent(-1);
+
11113 WriteLineIndent("}");
+
11114
+
11115 // Generate struct model final serialize() method
+
11116 WriteLine();
+
11117 WriteLineIndent("/**");
+
11118 WriteLineIndent(" * Serialize the struct value");
+
11119 WriteLineIndent(" * @this {!" + *s->name + "FinalModel}");
+
11120 WriteLineIndent(" * @param {!" + *s->name + "} value " + *s->name + " value");
+
11121 WriteLineIndent(" * @return {!number} Struct size");
+
11122 WriteLineIndent(" */");
+
11123 WriteLineIndent("serialize (value) {");
+
11124 Indent(1);
+
11125 WriteLineIndent("let fbeInitialSize = this.buffer.size");
+
11126 WriteLine();
+
11127 WriteLineIndent("let fbeStructType = this.fbeType");
+
11128 WriteLineIndent("let fbeStructSize = 8 + this._model.fbeAllocationSize(value)");
+
11129 WriteLineIndent("let fbeStructOffset = this.buffer.allocate(fbeStructSize) - this.buffer.offset");
+
11130 WriteLineIndent("console.assert(((this.buffer.offset + fbeStructOffset + fbeStructSize) <= this.buffer.size), 'Model is broken!')");
+
11131 WriteLineIndent("if ((this.buffer.offset + fbeStructOffset + fbeStructSize) > this.buffer.size) {");
+
11132 Indent(1);
+
11133 WriteLineIndent("return 0");
+
11134 Indent(-1);
+
11135 WriteLineIndent("}");
+
11136 WriteLine();
+
11137 WriteLineIndent("fbeStructSize = 8 + this._model.set(value)");
+
11138 WriteLineIndent("this.buffer.resize(fbeInitialSize + fbeStructSize)");
+
11139 WriteLine();
+
11140 WriteLineIndent("this.writeUInt32(this._model.fbeOffset - 8, fbeStructSize)");
+
11141 WriteLineIndent("this.writeUInt32(this._model.fbeOffset - 4, fbeStructType)");
+
11142 WriteLine();
+
11143 WriteLineIndent("return fbeStructSize");
+
11144 Indent(-1);
+
11145 WriteLineIndent("}");
+
11146
+
11147 // Generate struct model final deserialize() methods
+
11148 WriteLine();
+
11149 WriteLineIndent("/**");
+
11150 WriteLineIndent(" * Deserialize the struct value");
+
11151 WriteLineIndent(" * @this {!" + *s->name + "FinalModel}");
+
11152 WriteLineIndent(" * @param {!" + *s->name + "} value " + *s->name + " value, defaults is new " + *s->name + "()");
+
11153 WriteLineIndent(" * @return {!object} Deserialized " + *s->name + " value and its size");
+
11154 WriteLineIndent(" */");
+
11155 WriteLineIndent("deserialize (value = new " + *s->name + "()) {");
+
11156 Indent(1);
+
11157 WriteLineIndent("console.assert(((this.buffer.offset + this._model.fbeOffset) <= this.buffer.size), 'Model is broken!')");
+
11158 WriteLineIndent("if ((this.buffer.offset + this._model.fbeOffset) > this.buffer.size) {");
+
11159 Indent(1);
+
11160 WriteLineIndent("return { value: new " + *s->name + "(), size: 0 }");
+
11161 Indent(-1);
+
11162 WriteLineIndent("}");
+
11163 WriteLine();
+
11164 WriteLineIndent("let fbeStructSize = this.readUInt32(this._model.fbeOffset - 8)");
+
11165 WriteLineIndent("let fbeStructType = this.readUInt32(this._model.fbeOffset - 4)");
+
11166 WriteLineIndent("console.assert(((fbeStructSize > 0) && (fbeStructType === this.fbeType)), 'Model is broken!')");
+
11167 WriteLineIndent("if ((fbeStructSize <= 0) || (fbeStructType !== this.fbeType)) {");
+
11168 Indent(1);
+
11169 WriteLineIndent("return { value: new " + *s->name + "(), size: 8 }");
+
11170 Indent(-1);
+
11171 WriteLineIndent("}");
+
11172 WriteLine();
+
11173 WriteLineIndent("let fbeResult = this._model.get(value)");
+
11174 WriteLineIndent("return { value: fbeResult.value, size: (8 + fbeResult.size) }");
+
11175 Indent(-1);
+
11176 WriteLineIndent("}");
+
11177
+
11178 // Generate struct model final next() method
+
11179 WriteLine();
+
11180 WriteLineIndent("/**");
+
11181 WriteLineIndent(" * Move to the next struct value");
+
11182 WriteLineIndent(" * @this {!" + *s->name + "FinalModel}");
+
11183 WriteLineIndent(" * @param {!number} prev Previous " + *s->name + " model size");
+
11184 WriteLineIndent(" */");
+
11185 WriteLineIndent("next (prev) {");
+
11186 Indent(1);
+
11187 WriteLineIndent("this._model.fbeShift(prev)");
+
11188 Indent(-1);
+
11189 WriteLineIndent("}");
+
11190
+
11191 // Generate struct model final end
+
11192 Indent(-1);
+
11193 WriteLineIndent("}");
+
11194
+
11195 // Generate struct model final exports
+
11196 WriteLine();
+
11197 WriteLineIndent("exports." + *s->name + "FinalModel = " + *s->name + "FinalModel");
+
11198}
+
11199
+
11200void GeneratorJavaScript::GenerateProtocolVersion(const std::shared_ptr<Package>& p)
+
11201{
+
11202 // Generate protocol version constants
+
11203 WriteLine();
+
11204 WriteLineIndent("// Protocol major version");
+
11205 WriteLineIndent("const ProtocolVersionMajor = " + std::to_string(p->version->major));
+
11206 WriteLineIndent("// Protocol minor version");
+
11207 WriteLineIndent("const ProtocolVersionMinor = " + std::to_string(p->version->minor));
+
11208
+
11209 // Generate sender exports
+
11210 WriteLine();
+
11211 WriteLineIndent("exports.ProtocolVersionMajor = ProtocolVersionMajor");
+
11212 WriteLineIndent("exports.ProtocolVersionMinor = ProtocolVersionMinor");
+
11213}
+
11214
+
11215void GeneratorJavaScript::GenerateSender(const std::shared_ptr<Package>& p, bool final)
+
11216{
+
11217 std::string sender = (final ? "FinalSender" : "Sender");
+
11218 std::string model = (final ? "FinalModel" : "Model");
+
11219
+
11220 // Generate sender begin
+
11221 WriteLine();
+
11222 WriteLineIndent("/**");
+
11223 if (final)
+
11224 WriteLineIndent(" * Fast Binary Encoding " + *p->name + " final sender");
+
11225 else
+
11226 WriteLineIndent(" * Fast Binary Encoding " + *p->name + " sender");
+
11227 WriteLineIndent(" */");
+
11228 WriteLineIndent("class " + sender + " extends fbe.Sender {");
+
11229 Indent(1);
+
11230
+
11231 // Generate sender constructor
+
11232 WriteLineIndent("/**");
+
11233 WriteLineIndent(" * Initialize " + *p->name + " sender with the given buffer");
+
11234 WriteLineIndent(" * @param {!fbe.WriteBuffer} buffer Write buffer, defaults is new fbe.WriteBuffer()");
+
11235 WriteLineIndent(" * @constructor");
+
11236 WriteLineIndent(" */");
+
11237 WriteLineIndent("constructor (buffer = new fbe.WriteBuffer()) {");
+
11238 Indent(1);
+
11239 WriteLineIndent("super(buffer, " + std::string(final ? "true" : "false") + ")");
+
11240 if (p->import)
+
11241 {
+
11242 for (const auto& import : p->import->imports)
+
11243 WriteLineIndent("this._" + *import + "Sender = new " + *import + "." + sender + "(this.buffer)");
+
11244 }
+
11245 if (p->body)
+
11246 {
+
11247 for (const auto& s : p->body->structs)
+
11248 if (s->message)
+
11249 WriteLineIndent("this._" + *s->name + "Model = new " + *s->name + "" + model + "(this.buffer)");
+
11250 }
+
11251 WriteLineIndent("this.onSendHandler = this.onSend");
+
11252 WriteLineIndent("this.onSendLogHandler = this.onSendLog");
+
11253 Indent(-1);
+
11254 WriteLineIndent("}");
+
11255
+
11256 // Generate imported senders accessors
+
11257 if (p->import)
+
11258 {
+
11259 WriteLine();
+
11260 WriteLineIndent("// Imported senders");
+
11261 for (const auto& import : p->import->imports)
+
11262 {
+
11263 WriteLine();
+
11264 WriteLineIndent("/**");
+
11265 WriteLineIndent(" * Get imported " + *import + " sender");
+
11266 WriteLineIndent(" * @this {!" + sender + "}");
+
11267 WriteLineIndent(" * @returns {!" + *import + "." + sender + "} " + *import + " sender");
+
11268 WriteLineIndent(" */");
+
11269 WriteLineIndent("get " + *import + "Sender () {");
+
11270 Indent(1);
+
11271 WriteLineIndent("return this._" + *import + "Sender");
+
11272 Indent(-1);
+
11273 WriteLineIndent("}");
+
11274 }
+
11275 }
+
11276
+
11277 // Generate sender models accessors
+
11278 if (p->body)
+
11279 {
+
11280 WriteLine();
+
11281 WriteLineIndent("// Sender models accessors");
+
11282 for (const auto& s : p->body->structs)
+
11283 {
+
11284 if (s->message)
+
11285 {
+
11286 WriteLine();
+
11287 WriteLineIndent("/**");
+
11288 WriteLineIndent(" * Get " + *s->name + " model");
+
11289 WriteLineIndent(" * @this {!" + sender + "}");
+
11290 WriteLineIndent(" * @returns {!" + *s->name + "Model} " + *s->name + " model");
+
11291 WriteLineIndent(" */");
+
11292 WriteLineIndent("get " + *s->name + "Model () {");
+
11293 Indent(1);
+
11294 WriteLineIndent("return this._" + *s->name + "Model");
+
11295 Indent(-1);
+
11296 WriteLineIndent("}");
+
11297 }
+
11298 }
+
11299 }
+
11300
+
11301 // Generate sender methods
+
11302 WriteLine();
+
11303 WriteLineIndent("// Send methods");
+
11304 WriteLine();
+
11305 WriteLineIndent("/**");
+
11306 WriteLineIndent(" * Send value");
+
11307 WriteLineIndent(" * @this {!" + sender + "}");
+
11308 WriteLineIndent(" * @param {!object} value Value to send");
+
11309 WriteLineIndent(" * @returns {!number} Sent bytes");
+
11310 WriteLineIndent(" */");
+
11311 WriteLineIndent("send (value) {");
+
11312 Indent(1);
+
11313 if (p->body)
+
11314 {
+
11315 for (const auto& s : p->body->structs)
+
11316 {
+
11317 if (s->message)
+
11318 {
+
11319 WriteLineIndent("if ((value instanceof " + *s->name + ") && (value.fbeType === this." + *s->name + "Model.fbeType)) {");
+
11320 Indent(1);
+
11321 WriteLineIndent("return this.send_" + *s->name + "(value)");
+
11322 Indent(-1);
+
11323 WriteLineIndent("}");
+
11324 }
+
11325 }
+
11326 }
+
11327 if (p->import)
+
11328 {
+
11329 WriteLineIndent("let result = 0");
+
11330 for (const auto& import : p->import->imports)
+
11331 {
+
11332 WriteLineIndent("result = this._" + *import + "Sender.send(value)");
+
11333 WriteLineIndent("if (result > 0) {");
+
11334 Indent(1);
+
11335 WriteLineIndent("return result");
+
11336 Indent(-1);
+
11337 WriteLineIndent("}");
+
11338 }
+
11339 }
+
11340 WriteLineIndent("return 0");
+
11341 Indent(-1);
+
11342 WriteLineIndent("}");
+
11343 if (p->body)
+
11344 {
+
11345 for (const auto& s : p->body->structs)
+
11346 {
+
11347 if (s->message)
+
11348 {
+
11349 WriteLine();
+
11350 WriteLineIndent("/**");
+
11351 WriteLineIndent(" * Send " + *s->name + " value");
+
11352 WriteLineIndent(" * @this {!" + sender + "}");
+
11353 WriteLineIndent(" * @param {!" + *s->name + "} value " + *s->name + " value to send");
+
11354 WriteLineIndent(" * @returns {!number} Sent bytes");
+
11355 WriteLineIndent(" */");
+
11356 WriteLineIndent("send_" + *s->name + " (value) { // eslint-disable-line");
+
11357 Indent(1);
+
11358 WriteLineIndent("// Serialize the value into the FBE stream");
+
11359 WriteLineIndent("let serialized = this." + *s->name + "Model.serialize(value)");
+
11360 WriteLineIndent("console.assert((serialized > 0), '" + *p->name + "." + *s->name + " serialization failed!')");
+
11361 WriteLineIndent("console.assert(this." + *s->name + "Model.verify(), '" + *p->name + "." + *s->name + " validation failed!')");
+
11362 WriteLine();
+
11363 WriteLineIndent("// Log the value");
+
11364 WriteLineIndent("if (this.logging) {");
+
11365 Indent(1);
+
11366 WriteLineIndent("this.onSendLog(value.toString())");
+
11367 Indent(-1);
+
11368 WriteLineIndent("}");
+
11369 WriteLine();
+
11370 WriteLineIndent("// Send the serialized value");
+
11371 WriteLineIndent("return this.sendSerialized(serialized)");
+
11372 Indent(-1);
+
11373 WriteLineIndent("}");
+
11374 }
+
11375 }
+
11376 }
+
11377
+
11378 // Generate sender message handler
+
11379 WriteLine();
+
11380 WriteLineIndent("/**");
+
11381 WriteLineIndent(" * Send message handler");
+
11382 WriteLineIndent(" * @this {!" + sender + "}");
+
11383 WriteLineIndent(" * @param {!Uint8Array} buffer Buffer to send");
+
11384 WriteLineIndent(" * @param {!number} offset Buffer offset");
+
11385 WriteLineIndent(" * @param {!number} size Buffer size");
+
11386 WriteLineIndent(" */");
+
11387 WriteLineIndent("onSend (buffer, offset, size) {");
+
11388 Indent(1);
+
11389 WriteLineIndent("console.assert(true, '" + *p->name + ".Sender.onSend() not implemented!')");
+
11390 WriteLineIndent("debugger // eslint-disable-line");
+
11391 WriteLineIndent("return 0");
+
11392 Indent(-1);
+
11393 WriteLineIndent("}");
+
11394
+
11395 // Generate setup send message handler
+
11396 WriteLine();
+
11397 WriteLineIndent("/**");
+
11398 WriteLineIndent(" * Setup send message handler");
+
11399 WriteLineIndent(" * @this {!" + sender + "}");
+
11400 WriteLineIndent(" * @param {!function} handler Send message handler");
+
11401 WriteLineIndent(" */");
+
11402 WriteLineIndent("set onSendHandler (handler) { // eslint-disable-line");
+
11403 Indent(1);
+
11404 WriteLineIndent("this.onSend = handler");
+
11405 if (p->import)
+
11406 {
+
11407 for (const auto& import : p->import->imports)
+
11408 WriteLineIndent("this._" + *import + "Sender.onSendHandler = handler");
+
11409 }
+
11410 Indent(-1);
+
11411 WriteLineIndent("}");
+
11412
+
11413 // Generate setup send log message handler
+
11414 WriteLine();
+
11415 WriteLineIndent("/**");
+
11416 WriteLineIndent(" * Setup send log message handler");
+
11417 WriteLineIndent(" * @this {!" + sender + "}");
+
11418 WriteLineIndent(" * @param {!function} handler Send log message handler");
+
11419 WriteLineIndent(" */");
+
11420 WriteLineIndent("set onSendLogHandler (handler) { // eslint-disable-line");
+
11421 Indent(1);
+
11422 WriteLineIndent("this.onSendLog = handler");
+
11423 if (p->import)
+
11424 {
+
11425 for (const auto& import : p->import->imports)
+
11426 WriteLineIndent("this._" + *import + "Sender.onSendLogHandler = handler");
+
11427 }
+
11428 Indent(-1);
+
11429 WriteLineIndent("}");
+
11430
+
11431 // Generate sender end
+
11432 Indent(-1);
+
11433 WriteLineIndent("}");
+
11434
+
11435 // Generate sender exports
+
11436 WriteLine();
+
11437 WriteLineIndent("exports." + sender + " = " + sender);
+
11438}
+
11439
+
11440void GeneratorJavaScript::GenerateReceiver(const std::shared_ptr<Package>& p, bool final)
+
11441{
+
11442 std::string receiver = (final ? "FinalReceiver" : "Receiver");
+
11443 std::string model = (final ? "FinalModel" : "Model");
+
11444
+
11445 // Generate receiver begin
+
11446 WriteLine();
+
11447 WriteLineIndent("/**");
+
11448 if (final)
+
11449 WriteLineIndent(" * Fast Binary Encoding " + *p->name + " final receiver");
+
11450 else
+
11451 WriteLineIndent(" * Fast Binary Encoding " + *p->name + " receiver");
+
11452 WriteLineIndent(" */");
+
11453 WriteLineIndent("class " + receiver + " extends fbe.Receiver {");
+
11454 Indent(1);
+
11455
+
11456 // Generate receiver constructor
+
11457 WriteLineIndent("/**");
+
11458 WriteLineIndent(" * Initialize " + *p->name + " receiver with the given buffer");
+
11459 WriteLineIndent(" * @param {!fbe.WriteBuffer} buffer Write buffer, defaults is new WriteBuffer()");
+
11460 WriteLineIndent(" * @constructor");
+
11461 WriteLineIndent(" */");
+
11462 WriteLineIndent("constructor (buffer = new fbe.WriteBuffer()) {");
+
11463 Indent(1);
+
11464 WriteLineIndent("super(buffer, " + std::string(final ? "true" : "false") + ")");
+
11465 if (p->import)
+
11466 {
+
11467 for (const auto& import : p->import->imports)
+
11468 WriteLineIndent("this._" + *import + "Receiver = new " + *import + "." + receiver + "(this.buffer)");
+
11469 }
+
11470 if (p->body)
+
11471 {
+
11472 for (const auto& s : p->body->structs)
+
11473 {
+
11474 if (s->message)
+
11475 {
+
11476 WriteLineIndent("this._" + *s->name + "Value = new " + *s->name + "()");
+
11477 WriteLineIndent("this._" + *s->name + "Model = new " + *s->name + model + "()");
+
11478 }
+
11479 }
+
11480 }
+
11481 WriteLineIndent("this.onReceiveLogHandler = this.onReceiveLog");
+
11482 Indent(-1);
+
11483 WriteLineIndent("}");
+
11484
+
11485 // Generate imported receiver accessors
+
11486 if (p->import)
+
11487 {
+
11488 WriteLine();
+
11489 WriteLineIndent("// Imported receivers");
+
11490 for (const auto& import : p->import->imports)
+
11491 {
+
11492 WriteLine();
+
11493 WriteLineIndent("/**");
+
11494 WriteLineIndent(" * Get imported " + *import + " receiver");
+
11495 WriteLineIndent(" * @this {!" + receiver + "}");
+
11496 WriteLineIndent(" * @returns {" + receiver + "} " + *import + " receiver");
+
11497 WriteLineIndent(" */");
+
11498 WriteLineIndent("get " + *import + "Receiver () {");
+
11499 Indent(1);
+
11500 WriteLineIndent("return this._" + *import + "Receiver");
+
11501 Indent(-1);
+
11502 WriteLineIndent("}");
+
11503 WriteLine();
+
11504 WriteLineIndent("/**");
+
11505 WriteLineIndent(" * Set imported " + *import + " receiver");
+
11506 WriteLineIndent(" * @this {!" + receiver + "}");
+
11507 WriteLineIndent(" * @param {" + receiver + "} receiver " + *import + " receiver");
+
11508 WriteLineIndent(" */");
+
11509 WriteLineIndent("set " + *import + "Receiver (receiver) {");
+
11510 Indent(1);
+
11511 WriteLineIndent("this._" + *import + "Receiver = receiver");
+
11512 Indent(-1);
+
11513 WriteLineIndent("}");
+
11514 }
+
11515 }
+
11516
+
11517 // Generate receiver handlers
+
11518 if (p->body)
+
11519 {
+
11520 WriteLine();
+
11521 WriteLineIndent("// Receive handlers");
+
11522 for (const auto& s : p->body->structs)
+
11523 {
+
11524 if (s->message)
+
11525 {
+
11526 WriteLine();
+
11527 WriteLineIndent("/**");
+
11528 WriteLineIndent(" * " + *s->name + " receive handler");
+
11529 WriteLineIndent(" * @this {!" + receiver + "}");
+
11530 WriteLineIndent(" * @param {!" + *s->name + "} value " + *s->name + " received value");
+
11531 WriteLineIndent(" */");
+
11532 WriteLineIndent("onReceive_" + *s->name + " (value) {} // eslint-disable-line");
+
11533 }
+
11534 }
+
11535 WriteLine();
+
11536 }
+
11537
+
11538 // Generate receiver message handler
+
11539 WriteLineIndent("/**");
+
11540 WriteLineIndent(" * " + *p->name + " receive message handler");
+
11541 WriteLineIndent(" * @this {!" + receiver + "}");
+
11542 WriteLineIndent(" * @param {!number} type Message type");
+
11543 WriteLineIndent(" * @param {!Uint8Array} buffer Buffer to send");
+
11544 WriteLineIndent(" * @param {!number} offset Buffer offset");
+
11545 WriteLineIndent(" * @param {!number} size Buffer size");
+
11546 WriteLineIndent(" * @returns {!boolean} Success flag");
+
11547 WriteLineIndent(" */");
+
11548 WriteLineIndent("onReceive (type, buffer, offset, size) {");
+
11549 Indent(1);
+
11550 if (p->body)
+
11551 {
+
11552 WriteLineIndent("switch (type) {");
+
11553 Indent(1);
+
11554 for (const auto& s : p->body->structs)
+
11555 {
+
11556 if (s->message)
+
11557 {
+
11558 WriteLineIndent("case " + *s->name + model + ".fbeType: {");
+
11559 Indent(1);
+
11560 WriteLineIndent("// Deserialize the value from the FBE stream");
+
11561 WriteLineIndent("this._" + *s->name + "Model.attachBuffer(buffer, offset)");
+
11562 WriteLineIndent("console.assert(this._" + *s->name + "Model.verify(), '" + *p->name + "." + *s->name + " validation failed!')");
+
11563 WriteLineIndent("let deserialized = this._" + *s->name + "Model.deserialize(this._" + *s->name + "Value)");
+
11564 WriteLineIndent("console.assert((deserialized.size > 0), '" + *p->name + "." + *s->name + " deserialization failed!')");
+
11565 WriteLine();
+
11566 WriteLineIndent("// Log the value");
+
11567 WriteLineIndent("if (this.logging) {");
+
11568 Indent(1);
+
11569 WriteLineIndent("this.onReceiveLog(this._" + *s->name + "Value.toString())");
+
11570 Indent(-1);
+
11571 WriteLineIndent("}");
+
11572 WriteLine();
+
11573 WriteLineIndent("// Call receive handler with deserialized value");
+
11574 WriteLineIndent("this.onReceive_" + *s->name + "(this._" + *s->name + "Value)");
+
11575 WriteLineIndent("return true");
+
11576 Indent(-1);
+
11577 WriteLineIndent("}");
+
11578 }
+
11579 }
+
11580 WriteLineIndent("default: break");
+
11581 Indent(-1);
+
11582 WriteLineIndent("}");
+
11583 }
+
11584 if (p->import)
+
11585 {
+
11586 WriteLine();
+
11587 for (const auto& import : p->import->imports)
+
11588 {
+
11589 WriteLineIndent("// noinspection RedundantIfStatementJS");
+
11590 WriteLineIndent("if ((this." + *import + "Receiver != null) && this." + *import + "Receiver.onReceive(type, buffer, offset, size)) {");
+
11591 Indent(1);
+
11592 WriteLineIndent("return true");
+
11593 Indent(-1);
+
11594 WriteLineIndent("}");
+
11595 }
+
11596 WriteLine();
+
11597 }
+
11598 WriteLineIndent("return false");
+
11599 Indent(-1);
+
11600 WriteLineIndent("}");
+
11601
+
11602 // Generate setup receive log message handler
+
11603 WriteLine();
+
11604 WriteLineIndent("/**");
+
11605 WriteLineIndent(" * Setup receive log message handler");
+
11606 WriteLineIndent(" * @this {!" + receiver + "}");
+
11607 WriteLineIndent(" * @param {!function} handler Receive log message handler");
+
11608 WriteLineIndent(" */");
+
11609 WriteLineIndent("set onReceiveLogHandler (handler) { // eslint-disable-line");
+
11610 Indent(1);
+
11611 WriteLineIndent("this.onReceiveLog = handler");
+
11612 if (p->import)
+
11613 {
+
11614 for (const auto& import : p->import->imports)
+
11615 WriteLineIndent("this._" + *import + "Receiver.onReceiveLogHandler = handler");
+
11616 }
+
11617 Indent(-1);
+
11618 WriteLineIndent("}");
+
11619
+
11620 // Generate receiver end
+
11621 Indent(-1);
+
11622 WriteLineIndent("}");
+
11623
+
11624 // Generate receiver exports
+
11625 WriteLine();
+
11626 WriteLineIndent("exports." + receiver + " = " + receiver + "");
+
11627}
+
11628
+
11629void GeneratorJavaScript::GenerateProxy(const std::shared_ptr<Package>& p, bool final)
+
11630{
+
11631 std::string proxy = (final ? "FinalProxy" : "Proxy");
+
11632 std::string model = (final ? "FinalModel" : "Model");
+
11633
+
11634 // Generate proxy begin
+
11635 WriteLine();
+
11636 WriteLineIndent("/**");
+
11637 if (final)
+
11638 WriteLineIndent(" * Fast Binary Encoding " + *p->name + " final proxy");
+
11639 else
+
11640 WriteLineIndent(" * Fast Binary Encoding " + *p->name + " proxy");
+
11641 WriteLineIndent(" */");
+
11642 WriteLineIndent("class " + proxy + " extends fbe.Receiver {");
+
11643 Indent(1);
+
11644
+
11645 // Generate proxy constructor
+
11646 WriteLineIndent("/**");
+
11647 WriteLineIndent(" * Initialize " + *p->name + " proxy with the given buffer");
+
11648 WriteLineIndent(" * @param {!fbe.WriteBuffer} buffer Write buffer, defaults is new WriteBuffer()");
+
11649 WriteLineIndent(" * @constructor");
+
11650 WriteLineIndent(" */");
+
11651 WriteLineIndent("constructor (buffer = new fbe.WriteBuffer()) {");
+
11652 Indent(1);
+
11653 WriteLineIndent("super(buffer, " + std::string(final ? "true" : "false") + ")");
+
11654 if (p->import)
+
11655 {
+
11656 for (const auto& import : p->import->imports)
+
11657 WriteLineIndent("this._" + *import + "Proxy = new " + *import + "." + proxy + "(this.buffer)");
+
11658 }
+
11659 if (p->body)
+
11660 {
+
11661 for (const auto& s : p->body->structs)
+
11662 if (s->message)
+
11663 WriteLineIndent("this._" + *s->name + "Model = new " + *s->name + model + "()");
+
11664 }
+
11665 Indent(-1);
+
11666 WriteLineIndent("}");
+
11667
+
11668 // Generate imported proxy accessors
+
11669 if (p->import)
+
11670 {
+
11671 WriteLine();
+
11672 WriteLineIndent("// Imported proxy");
+
11673 for (const auto& import : p->import->imports)
+
11674 {
+
11675 WriteLine();
+
11676 WriteLineIndent("/**");
+
11677 WriteLineIndent(" * Get imported " + *import + " proxy");
+
11678 WriteLineIndent(" * @this {!" + proxy + "}");
+
11679 WriteLineIndent(" * @returns {" + proxy + "} " + *import + " proxy");
+
11680 WriteLineIndent(" */");
+
11681 WriteLineIndent("get " + *import + "Proxy () {");
+
11682 Indent(1);
+
11683 WriteLineIndent("return this._" + *import + "Proxy");
+
11684 Indent(-1);
+
11685 WriteLineIndent("}");
+
11686 WriteLine();
+
11687 WriteLineIndent("/**");
+
11688 WriteLineIndent(" * Set imported " + *import + " proxy");
+
11689 WriteLineIndent(" * @this {!" + proxy + "}");
+
11690 WriteLineIndent(" * @param {" + proxy + "} proxy " + *import + " proxy");
+
11691 WriteLineIndent(" */");
+
11692 WriteLineIndent("set " + *import + "Proxy (proxy) {");
+
11693 Indent(1);
+
11694 WriteLineIndent("this._" + *import + "Proxy = proxy");
+
11695 Indent(-1);
+
11696 WriteLineIndent("}");
+
11697 }
+
11698 }
+
11699
+
11700 // Generate proxy handlers
+
11701 if (p->body)
+
11702 {
+
11703 WriteLine();
+
11704 WriteLineIndent("// Proxy handlers");
+
11705 for (const auto& s : p->body->structs)
+
11706 {
+
11707 if (s->message)
+
11708 {
+
11709 WriteLine();
+
11710 WriteLineIndent("/**");
+
11711 WriteLineIndent(" * " + *s->name + " proxy handler");
+
11712 WriteLineIndent(" * @this {!" + proxy + "}");
+
11713 WriteLineIndent(" * @param {!" + *s->name + "} model " + *s->name + " model");
+
11714 WriteLineIndent(" * @param {!number} type Message type");
+
11715 WriteLineIndent(" * @param {!Uint8Array} buffer Buffer to send");
+
11716 WriteLineIndent(" * @param {!number} offset Buffer offset");
+
11717 WriteLineIndent(" * @param {!number} size Buffer size");
+
11718 WriteLineIndent(" */");
+
11719 WriteLineIndent("onProxy_" + *s->name + " (model, type, buffer, offset, size) {} // eslint-disable-line");
+
11720 }
+
11721 }
+
11722 WriteLine();
+
11723 }
+
11724
+
11725 // Generate proxy message handler
+
11726 WriteLineIndent("/**");
+
11727 WriteLineIndent(" * " + *p->name + " receive message handler");
+
11728 WriteLineIndent(" * @this {!" + proxy + "}");
+
11729 WriteLineIndent(" * @param {!number} type Message type");
+
11730 WriteLineIndent(" * @param {!Uint8Array} buffer Buffer to send");
+
11731 WriteLineIndent(" * @param {!number} offset Buffer offset");
+
11732 WriteLineIndent(" * @param {!number} size Buffer size");
+
11733 WriteLineIndent(" * @returns {!boolean} Success flag");
+
11734 WriteLineIndent(" */");
+
11735 WriteLineIndent("onReceive (type, buffer, offset, size) {");
+
11736 Indent(1);
+
11737 if (p->body)
+
11738 {
+
11739 WriteLineIndent("switch (type) {");
+
11740 Indent(1);
+
11741 for (const auto& s : p->body->structs)
+
11742 {
+
11743 if (s->message)
+
11744 {
+
11745 WriteLineIndent("case " + *s->name + model + ".fbeType: {");
+
11746 Indent(1);
+
11747 WriteLineIndent("// Attach the FBE stream to the proxy model");
+
11748 WriteLineIndent("this._" + *s->name + "Model.attachBuffer(buffer, offset)");
+
11749 WriteLineIndent("console.assert(this._" + *s->name + "Model.verify(), '" + *p->name + "." + *s->name + " validation failed!')");
+
11750 WriteLine();
+
11751 WriteLineIndent("let fbeBegin = this._" + *s->name + "Model.model.getBegin()");
+
11752 WriteLineIndent("if (fbeBegin === 0) {");
+
11753 Indent(1);
+
11754 WriteLineIndent("return false");
+
11755 Indent(-1);
+
11756 WriteLineIndent("}");
+
11757 WriteLineIndent("// Call proxy handler");
+
11758 WriteLineIndent("this.onProxy_" + *s->name + "(this._" + *s->name + "Model, type, buffer, offset, size)");
+
11759 WriteLineIndent("this._" + *s->name + "Model.model.getEnd(fbeBegin)");
+
11760 WriteLineIndent("return true");
+
11761 Indent(-1);
+
11762 WriteLineIndent("}");
+
11763 }
+
11764 }
+
11765 WriteLineIndent("default: break");
+
11766 Indent(-1);
+
11767 WriteLineIndent("}");
+
11768 }
+
11769 if (p->import)
+
11770 {
+
11771 WriteLine();
+
11772 for (const auto& import : p->import->imports)
+
11773 {
+
11774 WriteLineIndent("// noinspection RedundantIfStatementJS");
+
11775 WriteLineIndent("if ((this." + *import + "Proxy != null) && this." + *import + "Proxy.onReceive(type, buffer, offset, size)) {");
+
11776 Indent(1);
+
11777 WriteLineIndent("return true");
+
11778 Indent(-1);
+
11779 WriteLineIndent("}");
+
11780 }
+
11781 WriteLine();
+
11782 }
+
11783 WriteLineIndent("return false");
+
11784 Indent(-1);
+
11785 WriteLineIndent("}");
+
11786
+
11787 // Generate proxy end
+
11788 Indent(-1);
+
11789 WriteLineIndent("}");
+
11790
+
11791 // Generate proxy exports
+
11792 WriteLine();
+
11793 WriteLineIndent("exports." + proxy + " = " + proxy + "");
+
11794}
+
11795
+
11796void GeneratorJavaScript::GenerateClient(const std::shared_ptr<Package>& p, bool final)
+
11797{
+
11798 std::string client = (final ? "FinalClient" : "Client");
+
11799 std::string model = (final ? "FinalModel" : "Model");
+
11800
+
11801 // Generate client begin
+
11802 WriteLine();
+
11803 WriteLineIndent("/**");
+
11804 if (final)
+
11805 WriteLineIndent(" * Fast Binary Encoding " + *p->name + " final client");
+
11806 else
+
11807 WriteLineIndent(" * Fast Binary Encoding " + *p->name + " client");
+
11808 WriteLineIndent(" */");
+
11809 WriteLineIndent("class " + client + " extends fbe.Client {");
+
11810 Indent(1);
+
11811
+
11812 // Generate sender constructor
+
11813 WriteLineIndent("/**");
+
11814 WriteLineIndent(" * Initialize " + *p->name + " client with the given buffers");
+
11815 WriteLineIndent(" * @param {!fbe.WriteBuffer} sendBuffer Send buffer, defaults is new fbe.WriteBuffer()");
+
11816 WriteLineIndent(" * @param {!fbe.WriteBuffer} receiveBuffer Receive buffer, defaults is new fbe.WriteBuffer()");
+
11817 WriteLineIndent(" * @constructor");
+
11818 WriteLineIndent(" */");
+
11819 WriteLineIndent("constructor (sendBuffer = new fbe.WriteBuffer(), receiveBuffer = new fbe.WriteBuffer()) {");
+
11820 Indent(1);
+
11821 WriteLineIndent("super(sendBuffer, receiveBuffer, " + std::string(final ? "true" : "false") + ")");
+
11822 if (p->import)
+
11823 {
+
11824 for (const auto& import : p->import->imports)
+
11825 WriteLineIndent("this._" + *import + "Client = new " + *import + "." + client + "(this.sendBuffer, this.receiveBuffer)");
+
11826 }
+
11827 if (p->body)
+
11828 {
+
11829 for (const auto& s : p->body->structs)
+
11830 {
+
11831 if (s->message)
+
11832 {
+
11833 WriteLineIndent("this._" + *s->name + "SenderModel = new " + *s->name + "" + model + "(this.sendBuffer)");
+
11834 WriteLineIndent("this._" + *s->name + "ReceiverValue = new " + *s->name + "()");
+
11835 WriteLineIndent("this._" + *s->name + "ReceiverModel = new " + *s->name + model + "()");
+
11836 }
+
11837 }
+
11838 }
+
11839 WriteLineIndent("this.onSendHandler = this.onSend");
+
11840 WriteLineIndent("this.onSendLogHandler = this.onSendLog");
+
11841 WriteLineIndent("this.onReceiveLogHandler = this.onReceiveLog");
+
11842 WriteLineIndent("this._timestamp = 0");
+
11843 WriteLineIndent("this._requests_by_id = new Map()");
+
11844 WriteLineIndent("this._requests_by_timestamp = new Map()");
+
11845 Indent(-1);
+
11846 WriteLineIndent("}");
+
11847
+
11848 // Generate imported clients accessors
+
11849 if (p->import)
+
11850 {
+
11851 WriteLine();
+
11852 WriteLineIndent("// Imported clients");
+
11853 for (const auto& import : p->import->imports)
+
11854 {
+
11855 WriteLine();
+
11856 WriteLineIndent("/**");
+
11857 WriteLineIndent(" * Get imported " + *import + " client");
+
11858 WriteLineIndent(" * @this {!" + client + "}");
+
11859 WriteLineIndent(" * @returns {!" + *import + "." + client + "} " + *import + " client");
+
11860 WriteLineIndent(" */");
+
11861 WriteLineIndent("get " + *import + "Client () {");
+
11862 Indent(1);
+
11863 WriteLineIndent("return this._" + *import + "Client");
+
11864 Indent(-1);
+
11865 WriteLineIndent("}");
+
11866 }
+
11867 }
+
11868
+
11869 // Generate sender models accessors
+
11870 if (p->body)
+
11871 {
+
11872 WriteLine();
+
11873 WriteLineIndent("// Sender models accessors");
+
11874 for (const auto& s : p->body->structs)
+
11875 {
+
11876 if (s->message)
+
11877 {
+
11878 WriteLine();
+
11879 WriteLineIndent("/**");
+
11880 WriteLineIndent(" * Get " + *s->name + " model");
+
11881 WriteLineIndent(" * @this {!" + client + "}");
+
11882 WriteLineIndent(" * @returns {!" + *s->name + "Model} " + *s->name + " sender model");
+
11883 WriteLineIndent(" */");
+
11884 WriteLineIndent("get " + *s->name + "SenderModel () {");
+
11885 Indent(1);
+
11886 WriteLineIndent("return this._" + *s->name + "SenderModel");
+
11887 Indent(-1);
+
11888 WriteLineIndent("}");
+
11889 }
+
11890 }
+
11891 }
+
11892
+
11893 // Generate reset and watchdog methods
+
11894 WriteLine();
+
11895 WriteLineIndent("// Reset and watchdog methods");
+
11896 WriteLine();
+
11897 WriteLineIndent("/**");
+
11898 WriteLineIndent(" * Reset the client");
+
11899 WriteLineIndent(" * @this {!" + client + "}");
+
11900 WriteLineIndent(" */");
+
11901 WriteLineIndent("reset () {");
+
11902 Indent(1);
+
11903 WriteLineIndent("super.reset()");
+
11904 WriteLineIndent("this.resetRequests()");
+
11905 Indent(-1);
+
11906 WriteLineIndent("}");
+
11907 WriteLine();
+
11908 WriteLineIndent("/**");
+
11909 WriteLineIndent(" * Watchdog for timeouts");
+
11910 WriteLineIndent(" * @this {!" + client + "}");
+
11911 WriteLineIndent(" * @param {!number} utc UTC timestamp");
+
11912 WriteLineIndent(" */");
+
11913 WriteLineIndent("watchdog (utc) {");
+
11914 Indent(1);
+
11915 WriteLineIndent("this.watchdogRequests(utc)");
+
11916 Indent(-1);
+
11917 WriteLineIndent("}");
+
11918
+
11919 // Generate sender methods
+
11920 WriteLine();
+
11921 WriteLineIndent("// Send methods");
+
11922 WriteLine();
+
11923 WriteLineIndent("/**");
+
11924 WriteLineIndent(" * Send value");
+
11925 WriteLineIndent(" * @this {!" + client + "}");
+
11926 WriteLineIndent(" * @param {!object} value Value to send");
+
11927 WriteLineIndent(" * @returns {!number} Sent bytes");
+
11928 WriteLineIndent(" */");
+
11929 WriteLineIndent("send (value) {");
+
11930 Indent(1);
+
11931 if (p->body)
+
11932 {
+
11933 for (const auto& s : p->body->structs)
+
11934 {
+
11935 if (s->message)
+
11936 {
+
11937 WriteLineIndent("if ((value instanceof " + *s->name + ") && (value.fbeType === this." + *s->name + "SenderModel.fbeType)) {");
+
11938 Indent(1);
+
11939 WriteLineIndent("return this.send_" + *s->name + "(value)");
+
11940 Indent(-1);
+
11941 WriteLineIndent("}");
+
11942 }
+
11943 }
+
11944 }
+
11945 if (p->import)
+
11946 {
+
11947 WriteLineIndent("let result = 0");
+
11948 for (const auto& import : p->import->imports)
+
11949 {
+
11950 WriteLineIndent("result = this._" + *import + "Client.send(value)");
+
11951 WriteLineIndent("if (result > 0) {");
+
11952 Indent(1);
+
11953 WriteLineIndent("return result");
+
11954 Indent(-1);
+
11955 WriteLineIndent("}");
+
11956 }
+
11957 }
+
11958 WriteLineIndent("return 0");
+
11959 Indent(-1);
+
11960 WriteLineIndent("}");
+
11961 if (p->body)
+
11962 {
+
11963 for (const auto& s : p->body->structs)
+
11964 {
+
11965 if (s->message)
+
11966 {
+
11967 WriteLine();
+
11968 WriteLineIndent("/**");
+
11969 WriteLineIndent(" * Send " + *s->name + " value");
+
11970 WriteLineIndent(" * @this {!" + client + "}");
+
11971 WriteLineIndent(" * @param {!" + *s->name + "} value " + *s->name + " value to send");
+
11972 WriteLineIndent(" * @returns {!number} Sent bytes");
+
11973 WriteLineIndent(" */");
+
11974 WriteLineIndent("send_" + *s->name + " (value) { // eslint-disable-line");
+
11975 Indent(1);
+
11976 WriteLineIndent("// Serialize the value into the FBE stream");
+
11977 WriteLineIndent("let serialized = this." + *s->name + "SenderModel.serialize(value)");
+
11978 WriteLineIndent("console.assert((serialized > 0), '" + *p->name + "." + *s->name + " serialization failed!')");
+
11979 WriteLineIndent("console.assert(this." + *s->name + "SenderModel.verify(), '" + *p->name + "." + *s->name + " validation failed!')");
+
11980 WriteLine();
+
11981 WriteLineIndent("// Log the value");
+
11982 WriteLineIndent("if (this.logging) {");
+
11983 Indent(1);
+
11984 WriteLineIndent("this.onSendLog(value.toString())");
+
11985 Indent(-1);
+
11986 WriteLineIndent("}");
+
11987 WriteLine();
+
11988 WriteLineIndent("// Send the serialized value");
+
11989 WriteLineIndent("return this.sendSerialized(serialized)");
+
11990 Indent(-1);
+
11991 WriteLineIndent("}");
+
11992 }
+
11993 }
+
11994 }
+
11995
+
11996 // Generate sender message handler
+
11997 WriteLine();
+
11998 WriteLineIndent("/**");
+
11999 WriteLineIndent(" * Send message handler");
+
12000 WriteLineIndent(" * @this {!" + client + "}");
+
12001 WriteLineIndent(" * @param {!Uint8Array} buffer Buffer to send");
+
12002 WriteLineIndent(" * @param {!number} offset Buffer offset");
+
12003 WriteLineIndent(" * @param {!number} size Buffer size");
+
12004 WriteLineIndent(" */");
+
12005 WriteLineIndent("onSend (buffer, offset, size) {");
+
12006 Indent(1);
+
12007 WriteLineIndent("console.assert(true, '" + *p->name + ".Client.onSend() not implemented!')");
+
12008 WriteLineIndent("debugger // eslint-disable-line");
+
12009 WriteLineIndent("return 0");
+
12010 Indent(-1);
+
12011 WriteLineIndent("}");
+
12012
+
12013 // Generate setup send message handler
+
12014 WriteLine();
+
12015 WriteLineIndent("/**");
+
12016 WriteLineIndent(" * Setup send message handler");
+
12017 WriteLineIndent(" * @this {!" + client + "}");
+
12018 WriteLineIndent(" * @param {!function} handler Send message handler");
+
12019 WriteLineIndent(" */");
+
12020 WriteLineIndent("set onSendHandler (handler) { // eslint-disable-line");
+
12021 Indent(1);
+
12022 WriteLineIndent("this.onSend = handler");
+
12023 if (p->import)
+
12024 {
+
12025 for (const auto& import : p->import->imports)
+
12026 WriteLineIndent("this._" + *import + "Client.onSendHandler = handler");
+
12027 }
+
12028 Indent(-1);
+
12029 WriteLineIndent("}");
+
12030
+
12031 // Generate setup send log message handler
+
12032 WriteLine();
+
12033 WriteLineIndent("/**");
+
12034 WriteLineIndent(" * Setup send log message handler");
+
12035 WriteLineIndent(" * @this {!" + client + "}");
+
12036 WriteLineIndent(" * @param {!function} handler Send log message handler");
+
12037 WriteLineIndent(" */");
+
12038 WriteLineIndent("set onSendLogHandler (handler) { // eslint-disable-line");
+
12039 Indent(1);
+
12040 WriteLineIndent("this.onSendLog = handler");
+
12041 if (p->import)
+
12042 {
+
12043 for (const auto& import : p->import->imports)
+
12044 WriteLineIndent("this._" + *import + "Client.onSendLogHandler = handler");
+
12045 }
+
12046 Indent(-1);
+
12047 WriteLineIndent("}");
+
12048
+
12049 // Generate receiver handlers
+
12050 if (p->body)
+
12051 {
+
12052 WriteLine();
+
12053 WriteLineIndent("// Receive handlers");
+
12054 for (const auto& s : p->body->structs)
+
12055 {
+
12056 if (s->message)
+
12057 {
+
12058 WriteLine();
+
12059 WriteLineIndent("/**");
+
12060 WriteLineIndent(" * " + *s->name + " receive handler");
+
12061 WriteLineIndent(" * @this {!" + client + "}");
+
12062 WriteLineIndent(" * @param {!" + *s->name + "} value " + *s->name + " received value");
+
12063 WriteLineIndent(" */");
+
12064 WriteLineIndent("onReceive_" + *s->name + " (value) {} // eslint-disable-line");
+
12065 }
+
12066 }
+
12067 WriteLine();
+
12068 }
+
12069
+
12070 // Generate receiver message handler
+
12071 WriteLineIndent("/**");
+
12072 WriteLineIndent(" * " + *p->name + " receive message handler");
+
12073 WriteLineIndent(" * @this {!" + client + "}");
+
12074 WriteLineIndent(" * @param {!number} type Message type");
+
12075 WriteLineIndent(" * @param {!Uint8Array} buffer Buffer to send");
+
12076 WriteLineIndent(" * @param {!number} offset Buffer offset");
+
12077 WriteLineIndent(" * @param {!number} size Buffer size");
+
12078 WriteLineIndent(" * @returns {!boolean} Success flag");
+
12079 WriteLineIndent(" */");
+
12080 WriteLineIndent("onReceive (type, buffer, offset, size) {");
+
12081 Indent(1);
+
12082 if (p->body)
+
12083 {
+
12084 WriteLineIndent("switch (type) {");
+
12085 Indent(1);
+
12086 for (const auto& s : p->body->structs)
+
12087 {
+
12088 if (s->message)
+
12089 {
+
12090 WriteLineIndent("case " + *s->name + model + ".fbeType: {");
+
12091 Indent(1);
+
12092 WriteLineIndent("// Deserialize the value from the FBE stream");
+
12093 WriteLineIndent("this._" + *s->name + "ReceiverModel.attachBuffer(buffer, offset)");
+
12094 WriteLineIndent("console.assert(this._" + *s->name + "ReceiverModel.verify(), '" + *p->name + "." + *s->name + " validation failed!')");
+
12095 WriteLineIndent("let deserialized = this._" + *s->name + "ReceiverModel.deserialize(this._" + *s->name + "ReceiverValue)");
+
12096 WriteLineIndent("console.assert((deserialized.size > 0), '" + *p->name + "." + *s->name + " deserialization failed!')");
+
12097 WriteLine();
+
12098 WriteLineIndent("// Log the value");
+
12099 WriteLineIndent("if (this.logging) {");
+
12100 Indent(1);
+
12101 WriteLineIndent("this.onReceiveLog(this._" + *s->name + "ReceiverValue.toString())");
+
12102 Indent(-1);
+
12103 WriteLineIndent("}");
+
12104 WriteLine();
+
12105 WriteLineIndent("// Call receive handler with deserialized value");
+
12106 WriteLineIndent("this.onReceive_" + *s->name + "(this._" + *s->name + "ReceiverValue)");
+
12107 WriteLineIndent("return true");
+
12108 Indent(-1);
+
12109 WriteLineIndent("}");
+
12110 }
+
12111 }
+
12112 WriteLineIndent("default: break");
+
12113 Indent(-1);
+
12114 WriteLineIndent("}");
+
12115 }
+
12116 if (p->import)
+
12117 {
+
12118 WriteLine();
+
12119 for (const auto& import : p->import->imports)
+
12120 {
+
12121 WriteLineIndent("// noinspection RedundantIfStatementJS");
+
12122 WriteLineIndent("if ((this." + *import + "Client != null) && this." + *import + "Client.onReceive(type, buffer, offset, size)) {");
+
12123 Indent(1);
+
12124 WriteLineIndent("return true");
+
12125 Indent(-1);
+
12126 WriteLineIndent("}");
+
12127 }
+
12128 WriteLine();
+
12129 }
+
12130 WriteLineIndent("return false");
+
12131 Indent(-1);
+
12132 WriteLineIndent("}");
+
12133
+
12134 // Generate setup receive log message handler
+
12135 WriteLine();
+
12136 WriteLineIndent("/**");
+
12137 WriteLineIndent(" * Setup receive log message handler");
+
12138 WriteLineIndent(" * @this {!" + client + "}");
+
12139 WriteLineIndent(" * @param {!function} handler Receive log message handler");
+
12140 WriteLineIndent(" */");
+
12141 WriteLineIndent("set onReceiveLogHandler (handler) { // eslint-disable-line");
+
12142 Indent(1);
+
12143 WriteLineIndent("this.onReceiveLog = handler");
+
12144 if (p->import)
+
12145 {
+
12146 for (const auto& import : p->import->imports)
+
12147 WriteLineIndent("this._" + *import + "Client.onReceiveLogHandler = handler");
+
12148 }
+
12149 Indent(-1);
+
12150 WriteLineIndent("}");
+
12151
+
12152 // Generate request methods
+
12153 WriteLine();
+
12154 WriteLineIndent("// Request methods");
+
12155
+
12156 // Generate request value method
+
12157 WriteLine();
+
12158 WriteLineIndent("/**");
+
12159 WriteLineIndent(" * Request value");
+
12160 WriteLineIndent(" * @this {!" + client + "}");
+
12161 WriteLineIndent(" * @param {!object} value Value to request");
+
12162 WriteLineIndent(" * @param {!number} timeout Timeout in milliseconds (default is 0)");
+
12163 WriteLineIndent(" * @returns {Promise} Response promise");
+
12164 WriteLineIndent(" */");
+
12165 WriteLineIndent("request (value, timeout = 0) {");
+
12166 Indent(1);
+
12167 WriteLineIndent("let promise = new fbe.DeferredPromise()");
+
12168 WriteLineIndent("let current = Date.now()");
+
12169 WriteLine();
+
12170 WriteLineIndent("// Send the request message");
+
12171 WriteLineIndent("let serialized = this.send(value)");
+
12172 WriteLineIndent("if (serialized > 0) {");
+
12173 Indent(1);
+
12174 WriteLineIndent("// Calculate the unique timestamp");
+
12175 WriteLineIndent("this._timestamp = (current <= this._timestamp) ? this._timestamp + 1 : current");
+
12176 WriteLine();
+
12177 WriteLineIndent("// Register the request");
+
12178 WriteLineIndent("this._requests_by_id.set(value.id, [this._timestamp, timeout, promise])");
+
12179 WriteLineIndent("if (timeout > 0) {");
+
12180 Indent(1);
+
12181 WriteLineIndent("this._requests_by_timestamp.set(this._timestamp, value.id)");
+
12182 Indent(-1);
+
12183 WriteLineIndent("}");
+
12184 Indent(-1);
+
12185 WriteLineIndent("} else {");
+
12186 Indent(1);
+
12187 WriteLineIndent("promise.reject(new Error('Send request failed!'))");
+
12188 Indent(-1);
+
12189 WriteLineIndent("}");
+
12190 WriteLine();
+
12191 WriteLineIndent("return promise");
+
12192 Indent(-1);
+
12193 WriteLineIndent("}");
+
12194
+
12195 // Generate response value method
+
12196 WriteLine();
+
12197 WriteLineIndent("/**");
+
12198 WriteLineIndent(" * Response value");
+
12199 WriteLineIndent(" * @this {!" + client + "}");
+
12200 WriteLineIndent(" * @param {!object} value Value to response");
+
12201 WriteLineIndent(" * @returns {!boolean} Response handle flag");
+
12202 WriteLineIndent(" */");
+
12203 WriteLineIndent("response (value) {");
+
12204 Indent(1);
+
12205 WriteLineIndent("let item = this._requests_by_id.get(value.id)");
+
12206 WriteLineIndent("if (item != null) {");
+
12207 Indent(1);
+
12208 WriteLineIndent("let timestamp = item[0]");
+
12209 WriteLineIndent("let promise = item[2]");
+
12210 WriteLineIndent("promise.resolve(value)");
+
12211 WriteLineIndent("this._requests_by_id.delete(value.id)");
+
12212 WriteLineIndent("this._requests_by_timestamp.delete(timestamp)");
+
12213 WriteLineIndent("return true");
+
12214 Indent(-1);
+
12215 WriteLineIndent("}");
+
12216 if (p->import)
+
12217 {
+
12218 WriteLine();
+
12219 for (const auto& import : p->import->imports)
+
12220 {
+
12221 WriteLineIndent("// noinspection RedundantIfStatementJS");
+
12222 WriteLineIndent("if (this._" + *import + "Client.response(value)) {");
+
12223 Indent(1);
+
12224 WriteLineIndent("return true");
+
12225 Indent(-1);
+
12226 WriteLineIndent("}");
+
12227 }
+
12228 WriteLine();
+
12229 }
+
12230 WriteLineIndent("return false");
+
12231 Indent(-1);
+
12232 WriteLineIndent("}");
+
12233
+
12234 // Generate reject value method
+
12235 WriteLine();
+
12236 WriteLineIndent("/**");
+
12237 WriteLineIndent(" * Reject value");
+
12238 WriteLineIndent(" * @this {!" + client + "}");
+
12239 WriteLineIndent(" * @param {!object} value Value to reject");
+
12240 WriteLineIndent(" * @returns {!boolean} Reject handle flag");
+
12241 WriteLineIndent(" */");
+
12242 WriteLineIndent("reject (value) {");
+
12243 Indent(1);
+
12244 WriteLineIndent("let item = this._requests_by_id.get(value.id)");
+
12245 WriteLineIndent("if (item != null) {");
+
12246 Indent(1);
+
12247 WriteLineIndent("let timestamp = item[0]");
+
12248 WriteLineIndent("let promise = item[2]");
+
12249 WriteLineIndent("promise.reject(value)");
+
12250 WriteLineIndent("this._requests_by_id.delete(value.id)");
+
12251 WriteLineIndent("this._requests_by_timestamp.delete(timestamp)");
+
12252 WriteLineIndent("return true");
+
12253 Indent(-1);
+
12254 WriteLineIndent("}");
+
12255 if (p->import)
+
12256 {
+
12257 WriteLine();
+
12258 for (const auto& import : p->import->imports)
+
12259 {
+
12260 WriteLineIndent("// noinspection RedundantIfStatementJS");
+
12261 WriteLineIndent("if (this._" + *import + "Client.reject(value)) {");
+
12262 Indent(1);
+
12263 WriteLineIndent("return true");
+
12264 Indent(-1);
+
12265 WriteLineIndent("}");
+
12266 }
+
12267 WriteLine();
+
12268 }
+
12269 WriteLineIndent("return false");
+
12270 Indent(-1);
+
12271 WriteLineIndent("}");
+
12272
+
12273 // Generate reset client requests method
+
12274 WriteLine();
+
12275 WriteLineIndent("/**");
+
12276 WriteLineIndent(" * Reset client requests");
+
12277 WriteLineIndent(" * @this {!" + client + "}");
+
12278 WriteLineIndent(" */");
+
12279 WriteLineIndent("resetRequests () {");
+
12280 Indent(1);
+
12281 if (p->import)
+
12282 {
+
12283 for (const auto& import : p->import->imports)
+
12284 WriteLineIndent("this._" + *import + "Client.resetRequests()");
+
12285 WriteLine();
+
12286 }
+
12287 WriteLineIndent("for (let [, value] of this._requests_by_id) {");
+
12288 Indent(1);
+
12289 WriteLineIndent("value[2].reject(new Error('Reset client!'))");
+
12290 Indent(-1);
+
12291 WriteLineIndent("}");
+
12292 WriteLineIndent("this._requests_by_id.clear()");
+
12293 WriteLineIndent("this._requests_by_timestamp.clear()");
+
12294 Indent(-1);
+
12295 WriteLineIndent("}");
+
12296
+
12297 // Generate watchdog client requests method
+
12298 WriteLine();
+
12299 WriteLineIndent("/**");
+
12300 WriteLineIndent(" * Watchdog client requests for timeouts");
+
12301 WriteLineIndent(" * @this {!" + client + "}");
+
12302 WriteLineIndent(" * @param {!number} utc UTC timestamp in milliseconds");
+
12303 WriteLineIndent(" */");
+
12304 WriteLineIndent("watchdogRequests (utc) {");
+
12305 Indent(1);
+
12306 if (p->import)
+
12307 {
+
12308 for (const auto& import : p->import->imports)
+
12309 WriteLineIndent("this._" + *import + "Client.watchdogRequests(utc)");
+
12310 WriteLine();
+
12311 }
+
12312 WriteLineIndent("for (let [, value] of this._requests_by_timestamp) {");
+
12313 Indent(1);
+
12314 WriteLineIndent("let item = this._requests_by_id.get(value)");
+
12315 WriteLineIndent("let id = value");
+
12316 WriteLineIndent("let timestamp = item[0]");
+
12317 WriteLineIndent("let timespan = item[1]");
+
12318 WriteLineIndent("if ((timestamp + timespan) <= utc) {");
+
12319 Indent(1);
+
12320 WriteLineIndent("let promise = item[2]");
+
12321 WriteLineIndent("promise.reject(new Error('Timeout!'))");
+
12322 WriteLineIndent("this._requests_by_id.delete(id)");
+
12323 WriteLineIndent("this._requests_by_timestamp.delete(timestamp)");
+
12324 Indent(-1);
+
12325 WriteLineIndent("}");
+
12326 Indent(-1);
+
12327 WriteLineIndent("}");
+
12328 Indent(-1);
+
12329 WriteLineIndent("}");
+
12330
+
12331 // Generate client end
+
12332 Indent(-1);
+
12333 WriteLineIndent("}");
+
12334
+
12335 // Generate client exports
+
12336 WriteLine();
+
12337 WriteLineIndent("exports." + client + " = " + client);
+
12338}
+
12339
+
12340bool GeneratorJavaScript::IsPrimitiveType(const std::string& type)
+
12341{
+
12342 return ((type == "bool") || (type == "byte") ||
+
12343 (type == "char") || (type == "wchar") ||
+
12344 (type == "int8") || (type == "uint8") ||
+
12345 (type == "int16") || (type == "uint16") ||
+
12346 (type == "int32") || (type == "uint32") ||
+
12347 (type == "int64") || (type == "uint64") ||
+
12348 (type == "float") || (type == "double"));
+
12349}
+
12350
+
12351bool GeneratorJavaScript::IsJavaScriptType(const std::string& type)
+
12352{
+
12353 return IsPrimitiveType(type) || (type == "bytes") || (type == "string") || (type == "timestamp");
+
12354}
+
12355
+
12356std::string GeneratorJavaScript::ConvertEnumSize(const std::string& type)
+
12357{
+
12358 if (type == "byte")
+
12359 return "1";
+
12360 else if (type == "char")
+
12361 return "1";
+
12362 else if (type == "wchar")
+
12363 return "4";
+
12364 else if (type == "int8")
+
12365 return "1";
+
12366 else if (type == "uint8")
+
12367 return "1";
+
12368 else if (type == "int16")
+
12369 return "2";
+
12370 else if (type == "uint16")
+
12371 return "2";
+
12372 else if (type == "int32")
+
12373 return "4";
+
12374 else if (type == "uint32")
+
12375 return "4";
+
12376 else if (type == "int64")
+
12377 return "8";
+
12378 else if (type == "uint64")
+
12379 return "8";
+
12380
+
12381 yyerror("Unsupported enum base type - " + type);
+
12382 return "";
+
12383}
+
12384
+
12385std::string GeneratorJavaScript::ConvertEnumType(const std::string& type)
+
12386{
+
12387 if (type == "byte")
+
12388 return "Byte";
+
12389 else if (type == "char")
+
12390 return "UInt8";
+
12391 else if (type == "wchar")
+
12392 return "UInt32";
+
12393 else if (type == "int8")
+
12394 return "Int8";
+
12395 else if (type == "uint8")
+
12396 return "UInt8";
+
12397 else if (type == "int16")
+
12398 return "Int16";
+
12399 else if (type == "uint16")
+
12400 return "UInt16";
+
12401 else if (type == "int32")
+
12402 return "Int32";
+
12403 else if (type == "uint32")
+
12404 return "UInt32";
+
12405 else if (type == "int64")
+
12406 return "Int64";
+
12407 else if (type == "uint64")
+
12408 return "UInt64";
+
12409
+
12410 yyerror("Unsupported enum base type - " + type);
+
12411 return "";
+
12412}
+
12413
+
12414std::string GeneratorJavaScript::ConvertEnumConstant(const std::string& name, const std::string& type, const std::string& value)
+
12415{
+
12416 if (((type == "char") || (type == "wchar")) && CppCommon::StringUtils::StartsWith(value, "'"))
+
12417 return value + ".charCodeAt(0)";
+
12418 else if (type == "int64")
+
12419 return ConvertConstantInt64(value);
+
12420 else if (type == "uint64")
+
12421 return ConvertConstantUInt64(value);
+
12422 else if (type.empty())
+
12423 {
+
12424 // Fill flags values
+
12425 std::vector<std::string> flags = CppCommon::StringUtils::Split(value, '|', true);
+
12426
+
12427 // Generate flags combination
+
12428 if (!flags.empty())
+
12429 {
+
12430 std::string result = "";
+
12431 bool first = true;
+
12432 for (const auto& it : flags)
+
12433 {
+
12434 result += (first ? "" : " | ") + name + "." + CppCommon::StringUtils::ToTrim(it);
+
12435 first = false;
+
12436 }
+
12437 return result;
+
12438 }
+
12439 }
+
12440
+
12441 return value;
+
12442}
+
12443
+
12444std::string GeneratorJavaScript::ConvertTypeName(const std::string& type, bool optional)
+
12445{
+
12446 if (type == "bool")
+
12447 return "boolean";
+
12448 else if ((type == "byte") || (type == "int8") || (type == "uint8") || (type == "int16") || (type == "uint16") || (type == "int32") || (type == "uint32") || (type == "int64") || (type == "uint64") || (type == "float") || (type == "double"))
+
12449 return "number";
+
12450 else if (type == "decimal")
+
12451 return "Big";
+
12452 else if (type == "bytes")
+
12453 return "Uint8Array";
+
12454 else if (type == "timestamp")
+
12455 return "Date";
+
12456 else if ((type == "char") || (type == "wchar") || (type == "string"))
+
12457 return "string";
+
12458 else if (type == "uuid")
+
12459 return "UUID";
+
12460
+
12461 return type;
+
12462}
+
12463
+
12464std::string GeneratorJavaScript::ConvertTypeName(const StructField& field)
+
12465{
+
12466 if (field.array)
+
12467 return "Array";
+
12468 else if (field.vector)
+
12469 return "Array";
+
12470 else if (field.list)
+
12471 return "Array";
+
12472 else if (field.set)
+
12473 return "Set";
+
12474 else if (field.map)
+
12475 return "Map";
+
12476 else if (field.hash)
+
12477 return "Map";
+
12478
+
12479 return ConvertTypeName(*field.type, field.optional);
+
12480}
+
12481
+
12482std::string GeneratorJavaScript::ConvertTypeFieldName(const std::string& type, bool final)
+
12483{
+
12484 std::string modelType = final ? "Final" : "Field";
+
12485
+
12486 if (type == "bool")
+
12487 return "fbe." + modelType + "ModelBool";
+
12488 else if (type == "byte")
+
12489 return "fbe." + modelType + "ModelByte";
+
12490 else if (type == "char")
+
12491 return "fbe." + modelType + "ModelChar";
+
12492 else if (type == "wchar")
+
12493 return "fbe." + modelType + "ModelWChar";
+
12494 else if (type == "int8")
+
12495 return "fbe." + modelType + "ModelInt8";
+
12496 else if (type == "uint8")
+
12497 return "fbe." + modelType + "ModelUInt8";
+
12498 else if (type == "int16")
+
12499 return "fbe." + modelType + "ModelInt16";
+
12500 else if (type == "uint16")
+
12501 return "fbe." + modelType + "ModelUInt16";
+
12502 else if (type == "int32")
+
12503 return "fbe." + modelType + "ModelInt32";
+
12504 else if (type == "uint32")
+
12505 return "fbe." + modelType + "ModelUInt32";
+
12506 else if (type == "int64")
+
12507 return "fbe." + modelType + "ModelInt64";
+
12508 else if (type == "uint64")
+
12509 return "fbe." + modelType + "ModelUInt64";
+
12510 else if (type == "float")
+
12511 return "fbe." + modelType + "ModelFloat";
+
12512 else if (type == "double")
+
12513 return "fbe." + modelType + "ModelDouble";
+
12514 else if (type == "decimal")
+
12515 return "fbe." + modelType + "ModelDecimal";
+
12516 else if (type == "timestamp")
+
12517 return "fbe." + modelType + "ModelTimestamp";
+
12518 else if (type == "uuid")
+
12519 return "fbe." + modelType + "ModelUUID";
+
12520 else if (type == "bytes")
+
12521 return "fbe." + modelType + "ModelBytes";
+
12522 else if (type == "string")
+
12523 return "fbe." + modelType + "ModelString";
+
12524
+
12525 std::string ns = "";
+
12526 std::string t = type;
+
12527
+
12528 size_t pos = type.find_last_of('.');
+
12529 if (pos != std::string::npos)
+
12530 {
+
12531 ns.assign(type, 0, pos + 1);
+
12532 t.assign(type, pos + 1, type.size() - pos);
+
12533 }
+
12534
+
12535 return ns + modelType + "Model" + ConvertTypeName(t, false);
+
12536}
+
12537
+
12538std::string GeneratorJavaScript::ConvertTypeFieldDeclaration(const StructField& field, bool final)
+
12539{
+
12540 std::string modelType = final ? "Final" : "Field";
+
12541
+
12542 if (field.array)
+
12543 return "fbe." + modelType + "ModelArray";
+
12544 else if (field.vector || field.list)
+
12545 return "fbe." + modelType + "ModelVector";
+
12546 else if (field.set)
+
12547 return "fbe." + modelType + "ModelSet";
+
12548 else if (field.map || field.hash)
+
12549 return "fbe." + modelType + "ModelMap";
+
12550 else if (field.optional)
+
12551 return "fbe." + modelType + "ModelOptional";
+
12552 else
+
12553 return ConvertTypeFieldName(*field.type, final);
+
12554}
+
12555
+
12556std::string GeneratorJavaScript::ConvertTypeFieldInitialization(const std::string& type, bool optional, const std::string& offset, bool final)
+
12557{
+
12558 std::string modelType = final ? "Final" : "Field";
+
12559
+
12560 if (optional)
+
12561 return "fbe." + modelType + "ModelOptional(new " + ConvertTypeFieldInitialization(type, false, offset, final)+ ", buffer, " + offset + ")";
+
12562 else
+
12563 return ConvertTypeFieldName(type, final) + "(buffer, " + offset + ")";
+
12564}
+
12565
+
12566std::string GeneratorJavaScript::ConvertTypeFieldInitialization(const StructField& field, const std::string& offset, bool final)
+
12567{
+
12568 std::string modelType = final ? "Final" : "Field";
+
12569
+
12570 if (field.array)
+
12571 return "fbe." + modelType + "ModelArray(new " + ConvertTypeFieldInitialization(*field.type, field.optional, offset, final) + ", buffer, " + offset + ", " + std::to_string(field.N) + ")";
+
12572 else if (field.vector || field.list)
+
12573 return "fbe." + modelType + "ModelVector(new " + ConvertTypeFieldInitialization(*field.type, field.optional, offset, final) + ", buffer, " + offset + ")";
+
12574 else if (field.set)
+
12575 return "fbe." + modelType + "ModelSet(new " + ConvertTypeFieldInitialization(*field.type, field.optional, offset, final) + ", buffer, " + offset + ")";
+
12576 else if (field.map || field.hash)
+
12577 return "fbe." + modelType + "ModelMap(new " + ConvertTypeFieldInitialization(*field.key, false, offset, final) + ", new " + ConvertTypeFieldInitialization(*field.type, field.optional, offset, final) + ", buffer, " + offset + ")";
+
12578 else
+
12579 return ConvertTypeFieldInitialization(*field.type, field.optional, offset, final);
+
12580}
+
12581
+
12582std::string GeneratorJavaScript::ConvertConstant(const std::string& type, const std::string& value, bool optional)
+
12583{
+
12584 if (value == "true")
+
12585 return "true";
+
12586 else if (value == "false")
+
12587 return "false";
+
12588 else if (value == "null")
+
12589 return "undefined";
+
12590 else if (value == "min")
+
12591 {
+
12592 if ((type == "byte") || (type == "uint8") || (type == "uint16") || (type == "uint32"))
+
12593 return "0";
+
12594 else if (type == "int8")
+
12595 return "-128";
+
12596 else if (type == "int16")
+
12597 return "-32768";
+
12598 else if (type == "int32")
+
12599 return "-2147483648";
+
12600 else if (type == "int64")
+
12601 return ConvertConstantInt64("-9223372036854775808");
+
12602 else if (type == "uint64")
+
12603 return ConvertConstantUInt64("0");
+
12604
+
12605 yyerror("Unsupported type " + type + " for 'min' constant");
+
12606 return "";
+
12607 }
+
12608 else if (value == "max")
+
12609 {
+
12610 if (type == "byte")
+
12611 return "255";
+
12612 else if (type == "int8")
+
12613 return "127";
+
12614 else if (type == "uint8")
+
12615 return "255";
+
12616 else if (type == "int16")
+
12617 return "32767";
+
12618 else if (type == "uint16")
+
12619 return "65535";
+
12620 else if (type == "int32")
+
12621 return "2147483647";
+
12622 else if (type == "uint32")
+
12623 return "4294967295";
+
12624 else if (type == "int64")
+
12625 return ConvertConstantInt64("9223372036854775807");
+
12626 else if (type == "uint64")
+
12627 return ConvertConstantUInt64("18446744073709551615");
+
12628
+
12629 yyerror("Unsupported type " + type + " for 'max' constant");
+
12630 return "";
+
12631 }
+
12632 else if (value == "epoch")
+
12633 return "new Date(0)";
+
12634 else if (value == "uuid0")
+
12635 return "UUID.nil()";
+
12636 else if (value == "uuid1")
+
12637 return "UUID.sequential()";
+
12638 else if (value == "uuid4")
+
12639 return "UUID.random()";
+
12640 else if (value == "utc")
+
12641 return "new Date(Date.now())";
+
12642
+
12643 if (((type == "char") || (type == "wchar")) && !CppCommon::StringUtils::StartsWith(value, "'"))
+
12644 return "String.fromCharCode(" + value + ")";
+
12645 else if (type == "int64")
+
12646 return ConvertConstantInt64(value);
+
12647 else if (type == "uint64")
+
12648 return ConvertConstantUInt64(value);
+
12649 else if (type == "decimal")
+
12650 return "new Big('" + value + "')";
+
12651 else if (type == "string")
+
12652 return ConvertString(value);
+
12653 else if (type == "uuid")
+
12654 return "new UUID(" + ConvertString(value) + ")";
+
12655
+
12656 if (IsJavaScriptType(type))
+
12657 return value;
+
12658 else
+
12659 return "new " + ConvertTypeName(type, false) + "(" + value + ")";
+
12660}
+
12661
+
12662std::string GeneratorJavaScript::ConvertConstantInt64(const std::string& value)
+
12663{
+
12664 int64_t full = std::strtoll(value.c_str(), nullptr, 0);
+
12665 int32_t high = (int32_t)(full >> 32);
+
12666 uint32_t low = (uint32_t)full;
+
12667 return "new Int64(" + std::to_string(low) + ", " + std::to_string(high) + ")";
+
12668}
+
12669
+
12670std::string GeneratorJavaScript::ConvertConstantUInt64(const std::string& value)
+
12671{
+
12672 uint64_t full = std::strtoull(value.c_str(), nullptr, 0);
+
12673 uint32_t high = (uint32_t)(full >> 32);
+
12674 uint32_t low = (uint32_t)full;
+
12675 return "new UInt64(" + std::to_string(low) + ", " + std::to_string(high) + ")";
+
12676}
+
12677
+
12678std::string GeneratorJavaScript::ConvertDefault(const std::string& type)
+
12679{
+
12680 if (type == "bool")
+
12681 return "false";
+
12682 else if (type == "byte")
+
12683 return "0";
+
12684 else if (type == "bytes")
+
12685 return "new Uint8Array(0)";
+
12686 else if ((type == "char") || (type == "wchar"))
+
12687 return "'\\0'";
+
12688 else if ((type == "int8") || (type == "uint8") || (type == "int16") || (type == "uint16") || (type == "int32") || (type == "uint32"))
+
12689 return "0";
+
12690 else if (type == "int64")
+
12691 return ConvertConstantInt64("0");
+
12692 else if (type == "uint64")
+
12693 return ConvertConstantUInt64("0");
+
12694 else if ((type == "float") || (type == "double"))
+
12695 return "0.0";
+
12696 else if (type == "decimal")
+
12697 return "new Big(0)";
+
12698 else if (type == "string")
+
12699 return "''";
+
12700 else if (type == "timestamp")
+
12701 return "new Date(0)";
+
12702 else if (type == "uuid")
+
12703 return "new UUID()";
+
12704
+
12705 return "new " + type + "()";
+
12706}
+
12707
+
12708std::string GeneratorJavaScript::ConvertDefault(const StructField& field)
+
12709{
+
12710 if (field.value)
+
12711 return ConvertConstant(*field.type, *field.value, field.optional);
+
12712
+
12713 if (field.array || field.vector || field.list)
+
12714 return "[]";
+
12715 else if (field.set)
+
12716 return "new Set()";
+
12717 else if (field.map || field.hash)
+
12718 return "new Map()";
+
12719 else if (field.optional)
+
12720 return "undefined";
+
12721
+
12722 return ConvertDefault(*field.type);
+
12723}
+
12724
+
12725std::string GeneratorJavaScript::ConvertString(const std::string& value)
+
12726{
+
12727 std::string result;
+
12728
+
12729 if (CppCommon::StringUtils::StartsWith(value, "\"") && CppCommon::StringUtils::EndsWith(value, "\"") && (value.size() >= 2))
+
12730 result = value.substr(1, value.size() - 2);
+
12731 else
+
12732 result = value;
+
12733
+
12734 return "'" + result + "'";
+
12735}
+
12736
+
12737std::string GeneratorJavaScript::ConvertVariable(const std::string& type, const std::string& name, bool optional)
+
12738{
+
12739 if ((type == "char") || (type == "wchar"))
+
12740 return "((" + name + " != null) ? " + name + ".charCodeAt(0) : null)";
+
12741 else if ((type == "int64") || (type == "uint64"))
+
12742 return "((" + name + " != null) ? " + name + ".toNumber() : null)";
+
12743 else if (type == "bytes")
+
12744 return "((" + name + " != null) ? Buffer.from(" + name + ").toString('base64') : null)";
+
12745 else if (type == "decimal")
+
12746 return "((" + name + " != null) ? " + name + ".toFixed() : null)";
+
12747 else if (type == "timestamp")
+
12748 return "((" + name + " != null) ? (" + name + ".getTime() * 1000000) : null)";
+
12749 else if (type == "uuid")
+
12750 return "((" + name + " != null) ? " + name + ".toString() : null)";
+
12751 else
+
12752 return "((" + name + " != null) ? " + name + " : null)";
+
12753}
+
12754
+
12755void GeneratorJavaScript::CopyValueToVariable(const std::string& type, const std::string& name, const std::string& variable, bool optional)
+
12756{
+
12757 if ((type == "char") || (type == "wchar"))
+
12758 {
+
12759 WriteLineIndent("if ((typeof " + name + " === 'string') || (" + name + " instanceof String)) {");
+
12760 Indent(1);
+
12761 WriteLineIndent(variable + " = " + name);
+
12762 Indent(-1);
+
12763 WriteLineIndent("} else {");
+
12764 Indent(1);
+
12765 WriteLineIndent(variable + " = String.fromCharCode(" + name + ")");
+
12766 Indent(-1);
+
12767 WriteLineIndent("}");
+
12768 }
+
12769 else if (type == "int64")
+
12770 WriteLineIndent(variable + " = Int64.fromNumber(" + name + ")");
+
12771 else if (type == "uint64")
+
12772 WriteLineIndent(variable + " = UInt64.fromNumber(" + name + ")");
+
12773 else if (type == "bytes")
+
12774 {
+
12775 WriteLineIndent("if (typeof " + name + " === 'string') {");
+
12776 Indent(1);
+
12777 WriteLineIndent("// noinspection JSUnresolvedFunction");
+
12778 WriteLineIndent(variable + " = Uint8Array.from(Buffer.from(" + name + ", 'base64'))");
+
12779 Indent(-1);
+
12780 WriteLineIndent("} else {");
+
12781 Indent(1);
+
12782 WriteLineIndent(variable + " = Uint8Array.from(" + name + ")");
+
12783 Indent(-1);
+
12784 WriteLineIndent("}");
+
12785 }
+
12786 else if (type == "decimal")
+
12787 WriteLineIndent(variable + " = new Big(" + name + ")");
+
12788 else if (type == "timestamp")
+
12789 {
+
12790 WriteLineIndent("if (" + name + " instanceof Date) {");
+
12791 Indent(1);
+
12792 WriteLineIndent(variable + " = new Date(" + name + ".getTime())");
+
12793 Indent(-1);
+
12794 WriteLineIndent("} else {");
+
12795 Indent(1);
+
12796 WriteLineIndent(variable + " = new Date(Math.round(" + name + " / 1000000))");
+
12797 Indent(-1);
+
12798 WriteLineIndent("}");
+
12799 }
+
12800 else if (type == "uuid")
+
12801 WriteLineIndent(variable + " = new UUID(" + name + ")");
+
12802 else if (IsJavaScriptType(type))
+
12803 WriteLineIndent(variable + " = " + name);
+
12804 else
+
12805 WriteLineIndent(variable + " = " + ConvertTypeName(type, false) + ".fromObject(" + name + ")");
+
12806}
+
12807
+
12808void GeneratorJavaScript::WriteOutputStreamType(const std::string& type, const std::string& name, bool optional)
+
12809{
+
12810 if (type == "bool")
+
12811 WriteLineIndent("result += " + name + " ? 'true' : 'false'");
+
12812 else if (type == "bytes")
+
12813 WriteLineIndent("result += 'bytes[' + " + name + ".length + ']'");
+
12814 else if ((type == "char") || (type == "wchar"))
+
12815 WriteLineIndent("result += \"'\" + " + name + ".toString() + \"'\"");
+
12816 else if (type == "decimal")
+
12817 WriteLineIndent("result += " + name + ".toFixed()");
+
12818 else if ((type == "string") || (type == "uuid"))
+
12819 WriteLineIndent("result += '\"' + " + name + ".toString() + '\"'");
+
12820 else if (type == "timestamp")
+
12821 WriteLineIndent("result += " + name + ".getTime() * 1000000");
+
12822 else
+
12823 WriteLineIndent("result += " + name + ".toString()");
+
12824}
+
12825
+
12826void GeneratorJavaScript::WriteOutputStreamValue(const std::string& type, const std::string& name, bool optional, bool separate)
+
12827{
+
12828 if (optional || (type == "bytes") || (type == "decimal") || (type == "string") || (type == "timestamp") || (type == "uuid"))
+
12829 {
+
12830 WriteLineIndent("if (" + name + " != null) {");
+
12831 Indent(1);
+
12832 if (separate)
+
12833 WriteLineIndent("result += first ? '' : ','");
+
12834 WriteOutputStreamType(type, name, true);
+
12835 Indent(-1);
+
12836 WriteLineIndent("} else {");
+
12837 Indent(1);
+
12838 if (separate)
+
12839 WriteLineIndent("result += first ? '' : ','");
+
12840 WriteLineIndent("result += 'null'");
+
12841 Indent(-1);
+
12842 WriteLineIndent("}");
+
12843 }
+
12844 else
+
12845 {
+
12846 if (separate)
+
12847 WriteLineIndent("result += first ? '' : ','");
+
12848 WriteOutputStreamType(type, name, false);
+
12849 }
+
12850}
+
12851
+
12852} // namespace FBE
+
void WriteBegin()
Definition generator.inl:24
+
void Store(const CppCommon::Path &filename)
Definition generator.cpp:17
+
static std::string EndLine()
Definition generator.inl:68
+
std::string _input
Definition generator.h:25
+ +
std::string _output
Definition generator.h:26
+
void WriteLineIndent(const std::string &str)
Definition generator.inl:58
+
void Write(const std::string &str)
Definition generator.inl:29
+ +
void Indent(int count)
Definition generator.inl:19
+
void WriteIndent()
Definition generator.inl:34
+
bool Proto() const noexcept
+
void Generate(const std::shared_ptr< Package > &package) override
+
bool Final() const noexcept
+
bool JSON() const noexcept
+
int yyerror(const char *msg)
Definition fbe.l:163
+
Fast binary encoding JavaScript generator definition.
+
Definition fbe.h:33
+
const char version[]
Definition version.h:15
+ +
+ + +
+ + diff --git a/documents/html/generator__javascript_8h.html b/documents/html/generator__javascript_8h.html new file mode 100644 index 000000000..d3836b672 --- /dev/null +++ b/documents/html/generator__javascript_8h.html @@ -0,0 +1,114 @@ + + + + + + + +FastBinaryEncoding: include/generator_javascript.h File Reference + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+ +
generator_javascript.h File Reference
+
+
+ +

Fast binary encoding JavaScript generator definition. +More...

+
#include "generator.h"
+
+

Go to the source code of this file.

+ + + +

+Classes

class  FBE::GeneratorJavaScript
+ + +

+Namespaces

namespace  FBE
+

Detailed Description

+

Fast binary encoding JavaScript generator definition.

+
Author
Ivan Shynkarenka
+
Date
28.06.2018
+ + +

Definition in file generator_javascript.h.

+
+ + +
+ + diff --git a/documents/html/generator__javascript_8h_source.html b/documents/html/generator__javascript_8h_source.html new file mode 100644 index 000000000..a793452d5 --- /dev/null +++ b/documents/html/generator__javascript_8h_source.html @@ -0,0 +1,227 @@ + + + + + + + +FastBinaryEncoding: include/generator_javascript.h Source File + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+
generator_javascript.h
+
+
+Go to the documentation of this file.
1
+
8
+
9#ifndef GENERATOR_JAVASCRIPT_H
+
10#define GENERATOR_JAVASCRIPT_H
+
11
+
12#include "generator.h"
+
13
+
14namespace FBE {
+
15
+
+ +
17{
+
18public:
+ +
20
+
21 // Final protocol code generation
+
22 bool Final() const noexcept { return _final; }
+
23 GeneratorJavaScript& Final(bool final) noexcept { _final = final; return *this; }
+
24
+
25 // JSON protocol code generation
+
26 bool JSON() const noexcept { return _json; }
+
27 GeneratorJavaScript& JSON(bool json) noexcept { _json = json; return *this; }
+
28
+
29 // Sender/Receiver protocol code generation
+
30 bool Proto() const noexcept { return _proto; }
+
31 GeneratorJavaScript& Proto(bool proto) noexcept { _proto = proto; return *this; }
+
32
+
33 void Generate(const std::shared_ptr<Package>& package) override;
+
34
+
35private:
+
36 bool _final{false};
+
37 bool _json{false};
+
38 bool _proto{false};
+
39
+
40 void GenerateHeader(const std::string& source);
+
41 void GenerateFooter();
+
42 void GenerateBig(const CppCommon::Path& path);
+
43 void GenerateInt64(const CppCommon::Path& path);
+
44 void GenerateUUID(const CppCommon::Path& path);
+
45 void GenerateIEEE754(const CppCommon::Path& path);
+
46 void GenerateUTF8(const CppCommon::Path& path);
+
47 void GenerateFBE(const CppCommon::Path& path);
+
48 void GenerateFBEDeferredPromise();
+
49 void GenerateFBEBaseBuffer();
+
50 void GenerateFBEWriteBuffer();
+
51 void GenerateFBEReadBuffer();
+
52 void GenerateFBEModel();
+
53 void GenerateFBEFieldModelBase();
+
54 void GenerateFBEFieldModel();
+
55 void GenerateFBEFieldModel(const std::string& name, const std::string& type, const std::string& base, const std::string& size, const std::string& defaults);
+
56 void GenerateFBEFieldModelDecimal();
+
57 void GenerateFBEFieldModelTimestamp();
+
58 void GenerateFBEFieldModelUUID();
+
59 void GenerateFBEFieldModelBytes();
+
60 void GenerateFBEFieldModelString();
+
61 void GenerateFBEFieldModelOptional();
+
62 void GenerateFBEFieldModelArray();
+
63 void GenerateFBEFieldModelVector();
+
64 void GenerateFBEFieldModelSet();
+
65 void GenerateFBEFieldModelMap();
+
66 void GenerateFBEFinalModel();
+
67 void GenerateFBEFinalModel(const std::string& name, const std::string& type, const std::string& base, const std::string& size, const std::string& defaults);
+
68 void GenerateFBEFinalModelDecimal();
+
69 void GenerateFBEFinalModelTimestamp();
+
70 void GenerateFBEFinalModelUUID();
+
71 void GenerateFBEFinalModelBytes();
+
72 void GenerateFBEFinalModelString();
+
73 void GenerateFBEFinalModelOptional();
+
74 void GenerateFBEFinalModelArray();
+
75 void GenerateFBEFinalModelVector();
+
76 void GenerateFBEFinalModelSet();
+
77 void GenerateFBEFinalModelMap();
+
78 void GenerateFBESender();
+
79 void GenerateFBEReceiver();
+
80 void GenerateFBEClient();
+
81 void GenerateFBEJson();
+
82 void GenerateImports(const std::shared_ptr<Package>& p);
+
83
+
84 void GeneratePackage(const std::shared_ptr<Package>& p);
+
85 void GenerateEnum(const std::shared_ptr<EnumType>& e);
+
86 void GenerateEnumFieldModel(const std::shared_ptr<EnumType>& e);
+
87 void GenerateEnumFinalModel(const std::shared_ptr<EnumType>& e);
+
88 void GenerateFlags(const std::shared_ptr<FlagsType>& f);
+
89 void GenerateFlagsFieldModel(const std::shared_ptr<FlagsType>& f);
+
90 void GenerateFlagsFinalModel(const std::shared_ptr<FlagsType>& f);
+
91 void GenerateStruct(const std::shared_ptr<StructType>& s);
+
92 void GenerateStructFieldModel(const std::shared_ptr<StructType>& s);
+
93 void GenerateStructModel(const std::shared_ptr<StructType>& s);
+
94 void GenerateStructFinalModel(const std::shared_ptr<StructType>& s);
+
95 void GenerateStructModelFinal(const std::shared_ptr<StructType>& s);
+
96 void GenerateProtocolVersion(const std::shared_ptr<Package>& p);
+
97 void GenerateSender(const std::shared_ptr<Package>& p, bool final);
+
98 void GenerateReceiver(const std::shared_ptr<Package>& p, bool final);
+
99 void GenerateProxy(const std::shared_ptr<Package>& p, bool final);
+
100 void GenerateClient(const std::shared_ptr<Package>& p, bool final);
+
101
+
102 bool IsPrimitiveType(const std::string& type);
+
103 bool IsJavaScriptType(const std::string& type);
+
104
+
105 std::string ConvertEnumSize(const std::string& type);
+
106 std::string ConvertEnumType(const std::string& type);
+
107 std::string ConvertEnumConstant(const std::string& name, const std::string& type, const std::string& value);
+
108 std::string ConvertTypeName(const std::string& type, bool optional);
+
109 std::string ConvertTypeName(const StructField& field);
+
110 std::string ConvertTypeFieldName(const std::string& type, bool final);
+
111 std::string ConvertTypeFieldDeclaration(const StructField& field, bool final);
+
112 std::string ConvertTypeFieldInitialization(const std::string& type, bool optional, const std::string& offset, bool final);
+
113 std::string ConvertTypeFieldInitialization(const StructField& field, const std::string& offset, bool final);
+
114 std::string ConvertConstant(const std::string& type, const std::string& value, bool optional);
+
115 std::string ConvertConstantInt64(const std::string& value);
+
116 std::string ConvertConstantUInt64(const std::string& value);
+
117 std::string ConvertDefault(const std::string& type);
+
118 std::string ConvertDefault(const StructField& field);
+
119 std::string ConvertString(const std::string& value);
+
120 std::string ConvertVariable(const std::string& type, const std::string& name, bool optional);
+
121
+
122 void CopyValueToVariable(const std::string& type, const std::string& name, const std::string& variable, bool optional);
+
123
+
124 void WriteOutputStreamType(const std::string& type, const std::string& name, bool optional);
+
125 void WriteOutputStreamValue(const std::string& type, const std::string& name, bool optional, bool separate);
+
126};
+
+
127
+
128} // namespace FBE
+
129
+
130#endif // GENERATOR_JAVASCRIPT_H
+
Generator(const std::string &input, const std::string &output, int indent, char space)
Definition generator.inl:11
+ +
GeneratorJavaScript & JSON(bool json) noexcept
+
bool Proto() const noexcept
+
void Generate(const std::shared_ptr< Package > &package) override
+
bool Final() const noexcept
+
bool JSON() const noexcept
+
GeneratorJavaScript & Proto(bool proto) noexcept
+
Generator(const std::string &input, const std::string &output, int indent, char space)
Definition generator.inl:11
+
GeneratorJavaScript & Final(bool final) noexcept
+
Fast binary encoding generator definition.
+
Definition fbe.h:33
+
+ + +
+ + diff --git a/documents/html/generator__kotlin_8cpp.html b/documents/html/generator__kotlin_8cpp.html new file mode 100644 index 000000000..1c8835b20 --- /dev/null +++ b/documents/html/generator__kotlin_8cpp.html @@ -0,0 +1,109 @@ + + + + + + + +FastBinaryEncoding: source/generator_kotlin.cpp File Reference + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+ +
generator_kotlin.cpp File Reference
+
+
+ +

Fast binary encoding Kotlin generator implementation. +More...

+
#include "generator_kotlin.h"
+
+

Go to the source code of this file.

+ + + +

+Namespaces

namespace  FBE
+

Detailed Description

+

Fast binary encoding Kotlin generator implementation.

+
Author
Ivan Shynkarenka
+
Date
03.10.2018
+ + +

Definition in file generator_kotlin.cpp.

+
+ + +
+ + diff --git a/documents/html/generator__kotlin_8cpp_source.html b/documents/html/generator__kotlin_8cpp_source.html new file mode 100644 index 000000000..dcde5f10b --- /dev/null +++ b/documents/html/generator__kotlin_8cpp_source.html @@ -0,0 +1,9008 @@ + + + + + + + +FastBinaryEncoding: source/generator_kotlin.cpp Source File + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+
generator_kotlin.cpp
+
+
+Go to the documentation of this file.
1
+
8
+
9#include "generator_kotlin.h"
+
10
+
11namespace FBE {
+
12
+
+
13void GeneratorKotlin::Generate(const std::shared_ptr<Package>& package)
+
14{
+
15 std::string domain = (package->domain && !package->domain->empty()) ? (*package->domain + ".") : "";
+
16
+
17 GenerateFBEPackage(domain, "fbe");
+
18 GenerateFBEUUIDGenerator(domain, "fbe");
+
19 GenerateFBEBuffer(domain, "fbe");
+
20 GenerateFBEModel(domain, "fbe");
+
21 GenerateFBEFieldModel(domain, "fbe");
+
22 GenerateFBEFieldModel(domain, "fbe", "Boolean", "Boolean", "", "1", "false");
+
23 GenerateFBEFieldModel(domain, "fbe", "Byte", "Byte", "", "1", "0.toByte()");
+
24 GenerateFBEFieldModel(domain, "fbe", "Char", "Char", ".code", "1", "'\\u0000'");
+
25 GenerateFBEFieldModel(domain, "fbe", "WChar", "Char", ".code", "4", "'\\u0000'");
+
26 GenerateFBEFieldModel(domain, "fbe", "Int8", "Byte", "", "1", "0.toByte()");
+
27 GenerateFBEFieldModel(domain, "fbe", "UInt8", "UByte", "", "1", "0.toUByte()");
+
28 GenerateFBEFieldModel(domain, "fbe", "Int16", "Short", "", "2", "0.toShort()");
+
29 GenerateFBEFieldModel(domain, "fbe", "UInt16", "UShort", "", "2", "0.toUShort()");
+
30 GenerateFBEFieldModel(domain, "fbe", "Int32", "Int", "", "4", "0");
+
31 GenerateFBEFieldModel(domain, "fbe", "UInt32", "UInt", "", "4", "0u");
+
32 GenerateFBEFieldModel(domain, "fbe", "Int64", "Long", "", "8", "0L");
+
33 GenerateFBEFieldModel(domain, "fbe", "UInt64", "ULong", "", "8", "0uL");
+
34 GenerateFBEFieldModel(domain, "fbe", "Float", "Float", "", "4", "0.0f");
+
35 GenerateFBEFieldModel(domain, "fbe", "Double", "Double", "", "8", "0.0");
+
36 GenerateFBEFieldModel(domain, "fbe", "UUID", "java.util.UUID", "", "16", "UUIDGenerator.nil()");
+
37 GenerateFBEFieldModelDecimal(domain, "fbe");
+
38 if (Version() < 8)
+
39 GenerateFBEFieldModelDate(domain, "fbe");
+
40 else
+
41 GenerateFBEFieldModelTimestamp(domain, "fbe");
+
42 GenerateFBEFieldModelBytes(domain, "fbe");
+
43 GenerateFBEFieldModelString(domain, "fbe");
+
44 if (Final())
+
45 {
+
46 GenerateFBESize(domain, "fbe");
+
47 GenerateFBEFinalModel(domain, "fbe");
+
48 GenerateFBEFinalModel(domain, "fbe", "Boolean", "Boolean", "", "1", "false");
+
49 GenerateFBEFinalModel(domain, "fbe", "Byte", "Byte", "", "1", "0.toByte()");
+
50 GenerateFBEFinalModel(domain, "fbe", "Char", "Char", ".code", "1", "'\\u0000'");
+
51 GenerateFBEFinalModel(domain, "fbe", "WChar", "Char", ".code", "4", "'\\u0000'");
+
52 GenerateFBEFinalModel(domain, "fbe", "Int8", "Byte", "", "1", "0.toByte()");
+
53 GenerateFBEFinalModel(domain, "fbe", "UInt8", "UByte", "", "1", "0.toUByte()");
+
54 GenerateFBEFinalModel(domain, "fbe", "Int16", "Short", "", "2", "0.toShort()");
+
55 GenerateFBEFinalModel(domain, "fbe", "UInt16", "UShort", "", "2", "0.toUShort()");
+
56 GenerateFBEFinalModel(domain, "fbe", "Int32", "Int", "", "4", "0");
+
57 GenerateFBEFinalModel(domain, "fbe", "UInt32", "UInt", "", "4", "0u");
+
58 GenerateFBEFinalModel(domain, "fbe", "Int64", "Long", "", "8", "0L");
+
59 GenerateFBEFinalModel(domain, "fbe", "UInt64", "ULong", "", "8", "0uL");
+
60 GenerateFBEFinalModel(domain, "fbe", "Float", "Float", "", "4", "0.0f");
+
61 GenerateFBEFinalModel(domain, "fbe", "Double", "Double", "", "8", "0.0");
+
62 GenerateFBEFinalModel(domain, "fbe", "UUID", "java.util.UUID", "", "16", "UUIDGenerator.nil()");
+
63 GenerateFBEFinalModelDecimal(domain, "fbe");
+
64 if (Version() < 8)
+
65 GenerateFBEFinalModelDate(domain, "fbe");
+
66 else
+
67 GenerateFBEFinalModelTimestamp(domain, "fbe");
+
68 GenerateFBEFinalModelBytes(domain, "fbe");
+
69 GenerateFBEFinalModelString(domain, "fbe");
+
70 }
+
71 if (Proto())
+
72 {
+
73 GenerateFBESender(domain, "fbe");
+
74 GenerateFBESenderListener(domain, "fbe");
+
75 GenerateFBEReceiver(domain, "fbe");
+
76 GenerateFBEReceiverListener(domain, "fbe");
+
77 GenerateFBEClient(domain, "fbe");
+
78 GenerateFBEClientListener(domain, "fbe");
+
79 }
+
80 if (JSON())
+
81 GenerateFBEJson(domain, "fbe");
+
82
+
83 GeneratePackage(package);
+
84}
+
+
85
+
86void GeneratorKotlin::GenerateHeader(const std::string& source)
+
87{
+
88 std::string code = R"CODE(//------------------------------------------------------------------------------
+
89// Automatically generated by the Fast Binary Encoding compiler, do not modify!
+
90// https://github.com/chronoxor/FastBinaryEncoding
+
91// Source: _INPUT_
+
92// FBE version: _VERSION_
+
93//------------------------------------------------------------------------------
+
94
+
95@file:Suppress("UnusedImport", "unused")
+
96)CODE";
+
97
+
98 // Prepare code template
+
99 code = std::regex_replace(code, std::regex("_INPUT_"), source);
+
100 code = std::regex_replace(code, std::regex("_VERSION_"), version);
+
101 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
102
+
103 Write(code);
+
104}
+
105
+
106void GeneratorKotlin::GenerateFooter()
+
107{
+
108}
+
109
+
110void GeneratorKotlin::GenerateImports(const std::string& domain, const std::string& package)
+
111{
+
112 // Generate package name
+
113 WriteLine();
+
114 WriteLineIndent("package " + domain + package);
+
115}
+
116
+
117void GeneratorKotlin::GenerateImports(const std::shared_ptr<Package>& p)
+
118{
+
119 std::string domain = (p->domain && !p->domain->empty()) ? (*p->domain + ".") : "";
+
120
+
121 // Generate common import
+
122 GenerateImports(domain, *p->name);
+
123}
+
124
+
125void GeneratorKotlin::GenerateFBEPackage(const std::string& domain, const std::string& package)
+
126{
+
127 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
128
+
129 // Create FBE package path
+
130 CppCommon::Directory::CreateTree(path);
+
131}
+
132
+
133void GeneratorKotlin::GenerateFBEUUIDGenerator(const std::string& domain, const std::string& package)
+
134{
+
135 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
136
+
137 // Generate the file
+
138 CppCommon::Path file = path / "UUIDGenerator.kt";
+
139 WriteBegin();
+
140
+
141 // Generate headers
+
142 GenerateHeader("FBE");
+
143 GenerateImports(domain, package);
+
144
+
145 std::string code = R"CODE(
+
146// Fast Binary Encoding UUID generator
+
147object UUIDGenerator
+
148{
+
149 // Gregorian epoch
+
150 private const val GregorianEpoch = 0xFFFFF4E2F964AC00uL
+
151
+
152 // Kotlin constants workaround
+
153 private val Sign = java.lang.Long.parseUnsignedLong("8000000000000000", 16)
+
154 private val Low = java.lang.Long.parseUnsignedLong("00000000FFFFFFFF", 16)
+
155 private val Mid = java.lang.Long.parseUnsignedLong("0000FFFF00000000", 16)
+
156 private val High = java.lang.Long.parseUnsignedLong("FFFF000000000000", 16)
+
157
+
158 // Lock and random generator
+
159 private val lock = Object()
+
160 private val generator = java.util.Random()
+
161
+
162 // Node & clock sequence bytes
+
163 private val node = makeNode()
+
164 private var nodeAndClockSequence = makeNodeAndClockSequence()
+
165
+
166 // Last UUID generated timestamp
+
167 private var last = GregorianEpoch
+
168
+
169 private fun makeNode(): ULong = generator.nextLong().toULong() or 0x0000010000000000uL
+
170
+
171 private fun makeNodeAndClockSequence(): ULong
+
172 {
+
173 val clock = generator.nextLong().toULong()
+
174
+
175 var lsb: ULong = 0u
+
176 // Variant (2 bits)
+
177 lsb = lsb or 0x8000000000000000uL
+
178 // Clock sequence (14 bits)
+
179 lsb = lsb or ((clock and 0x0000000000003FFFuL) shl 48)
+
180 // 6 bytes
+
181 lsb = lsb or node
+
182 return lsb
+
183 }
+
184
+
185 // Generate nil UUID0 (all bits set to zero)
+
186 fun nil(): java.util.UUID = java.util.UUID(0, 0)
+
187
+
188 // Generate sequential UUID1 (time based version)
+
189 fun sequential(): java.util.UUID
+
190 {
+
191 val now = System.currentTimeMillis().toULong()
+
192
+
193 // Generate new clock sequence bytes to get rid of UUID duplicates
+
194 synchronized(lock)
+
195 {
+
196 if (now <= last)
+
197 nodeAndClockSequence = makeNodeAndClockSequence()
+
198 last = now
+
199 }
+
200
+
201 val nanosSince = (now - GregorianEpoch) * 10000u
+
202
+
203 var msb = 0uL
+
204 msb = msb or (0x00000000FFFFFFFFuL and nanosSince).shl(32)
+
205 msb = msb or (0x0000FFFF00000000uL and nanosSince).shr(16)
+
206 msb = msb or (0xFFFF000000000000uL and nanosSince).shr(48)
+
207 // Sets the version to 1
+
208 msb = msb or 0x0000000000001000uL
+
209
+
210 return java.util.UUID(msb.toLong(), nodeAndClockSequence.toLong())
+
211 }
+
212
+
213 // Generate random UUID4 (randomly or pseudo-randomly generated version)
+
214 fun random(): java.util.UUID = java.util.UUID.randomUUID()
+
215}
+
216)CODE";
+
217
+
218 // Prepare code template
+
219 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
220
+
221 Write(code);
+
222
+
223 // Generate footer
+
224 GenerateFooter();
+
225
+
226 // Store the file
+
227 WriteEnd();
+
228 Store(file);
+
229}
+
230
+
231void GeneratorKotlin::GenerateFBEBuffer(const std::string& domain, const std::string& package)
+
232{
+
233 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
234
+
235 // Generate the file
+
236 CppCommon::Path file = path / "Buffer.kt";
+
237 WriteBegin();
+
238
+
239 // Generate headers
+
240 GenerateHeader("FBE");
+
241 GenerateImports(domain, package);
+
242
+
243 std::string code = R"CODE(
+
244// Fast Binary Encoding buffer based on dynamic byte array
+
245class Buffer
+
246{
+
247 // Is the buffer empty?
+
248 val empty: Boolean
+
249 get() = size == 0L
+
250 // Get bytes memory buffer
+
251 var data = ByteArray(0)
+
252 private set
+
253 // Get bytes memory buffer capacity
+
254 val capacity: Long
+
255 get() = data.size.toLong()
+
256 // Get bytes memory buffer size
+
257 var size: Long = 0
+
258 private set
+
259 // Get bytes memory buffer offset
+
260 var offset: Long = 0
+
261 private set
+
262
+
263 // Initialize a new expandable buffer with zero capacity
+
264 constructor()
+
265 // Initialize a new expandable buffer with the given capacity
+
266 constructor(capacity: Long) { attach(capacity) }
+
267 // Initialize a new buffer based on the specified byte array
+
268 constructor(buffer: ByteArray) { attach(buffer) }
+
269 // Initialize a new buffer based on the specified region (offset) of a byte array
+
270 constructor(buffer: ByteArray, offset: Long) { attach(buffer, offset) }
+
271 // Initialize a new buffer based on the specified region (size and offset) of a byte array
+
272 constructor(buffer: ByteArray, size: Long, offset: Long) { attach(buffer, size, offset) }
+
273
+
274 // Attach memory buffer methods
+
275 fun attach() { data = ByteArray(0); size = 0; offset = 0 }
+
276 fun attach(capacity: Long) { data = ByteArray(capacity.toInt()); size = 0; offset = 0 }
+
277 fun attach(buffer: ByteArray) { data = buffer; size = buffer.size.toLong(); offset = 0 }
+
278 fun attach(buffer: ByteArray, offset: Long) { data = buffer; size = buffer.size.toLong(); this.offset = offset }
+
279 fun attach(buffer: ByteArray, size: Long, offset: Long) { data = buffer; this.size = size; this.offset = offset }
+
280
+
281 // Allocate memory in the current buffer and return offset to the allocated memory block
+
282 fun allocate(size: Long): Long
+
283 {
+
284 assert(size >= 0) { "Invalid allocation size!" }
+
285 if (size < 0)
+
286 throw IllegalArgumentException("Invalid allocation size!")
+
287
+
288 val offset = this.size
+
289
+
290 // Calculate a new buffer size
+
291 val total = this.size + size
+
292
+
293 if (total <= data.size)
+
294 {
+
295 this.size = total
+
296 return offset
+
297 }
+
298
+
299 val data = ByteArray(kotlin.math.max(total, 2L * this.data.size).toInt())
+
300 System.arraycopy(this.data, 0, data, 0, this.size.toInt())
+
301 this.data = data
+
302 this.size = total
+
303 return offset
+
304 }
+
305
+
306 // Remove some memory of the given size from the current buffer
+
307 fun remove(offset: Long, size: Long)
+
308 {
+
309 assert((offset + size) <= this.size) { "Invalid offset & size!" }
+
310 if ((offset + size) > this.size)
+
311 throw IllegalArgumentException("Invalid offset & size!")
+
312
+
313 System.arraycopy(data, (offset + size).toInt(), data, offset.toInt(), (this.size - size - offset).toInt())
+
314 this.size -= size
+
315 if (this.offset >= offset + size)
+
316 this.offset -= size
+
317 else if (this.offset >= offset)
+
318 {
+
319 this.offset -= this.offset - offset
+
320 if (this.offset > this.size)
+
321 this.offset = this.size
+
322 }
+
323 }
+
324
+
325 // Reserve memory of the given capacity in the current buffer
+
326 fun reserve(capacity: Long)
+
327 {
+
328 assert(capacity >= 0) { "Invalid reserve capacity!" }
+
329 if (capacity < 0)
+
330 throw IllegalArgumentException("Invalid reserve capacity!")
+
331
+
332 if (capacity > data.size)
+
333 {
+
334 val data = ByteArray(kotlin.math.max(capacity, 2L * this.data.size).toInt())
+
335 System.arraycopy(this.data, 0, data, 0, size.toInt())
+
336 this.data = data
+
337 }
+
338 }
+
339
+
340 // Resize the current buffer
+
341 fun resize(size: Long)
+
342 {
+
343 reserve(size)
+
344 this.size = size
+
345 if (offset > this.size)
+
346 offset = this.size
+
347 }
+
348
+
349 // Reset the current buffer and its offset
+
350 fun reset()
+
351 {
+
352 size = 0
+
353 offset = 0
+
354 }
+
355
+
356 // Shift the current buffer offset
+
357 fun shift(offset: Long) { this.offset += offset }
+
358 // Unshift the current buffer offset
+
359 fun unshift(offset: Long) { this.offset -= offset }
+
360
+
361 companion object
+
362 {
+
363 // Buffer I/O methods
+
364
+
365 fun readBoolean(buffer: ByteArray, offset: Long): Boolean
+
366 {
+
367 val index = offset.toInt()
+
368 return buffer[index].toInt() != 0
+
369 }
+
370
+
371 fun readByte(buffer: ByteArray, offset: Long): Byte
+
372 {
+
373 val index = offset.toInt()
+
374 return buffer[index]
+
375 }
+
376
+
377 fun readChar(buffer: ByteArray, offset: Long): Char
+
378 {
+
379 return readInt8(buffer, offset).toInt().toChar()
+
380 }
+
381
+
382 fun readWChar(buffer: ByteArray, offset: Long): Char
+
383 {
+
384 return readInt32(buffer, offset).toChar()
+
385 }
+
386
+
387 fun readInt8(buffer: ByteArray, offset: Long): Byte
+
388 {
+
389 val index = offset.toInt()
+
390 return buffer[index]
+
391 }
+
392
+
393 fun readUInt8(buffer: ByteArray, offset: Long): UByte
+
394 {
+
395 val index = offset.toInt()
+
396 return buffer[index].toUByte()
+
397 }
+
398
+
399 fun readInt16(buffer: ByteArray, offset: Long): Short
+
400 {
+
401 val index = offset.toInt()
+
402 return (((buffer[index + 0].toInt() and 0xFF) shl 0) or
+
403 ((buffer[index + 1].toInt() and 0xFF) shl 8)).toShort()
+
404 }
+
405
+
406 fun readUInt16(buffer: ByteArray, offset: Long): UShort
+
407 {
+
408 val index = offset.toInt()
+
409 return (((buffer[index + 0].toUInt() and 0xFFu) shl 0) or
+
410 ((buffer[index + 1].toUInt() and 0xFFu) shl 8)).toUShort()
+
411 }
+
412
+
413 fun readInt32(buffer: ByteArray, offset: Long): Int
+
414 {
+
415 val index = offset.toInt()
+
416 return ((buffer[index + 0].toInt() and 0xFF) shl 0) or
+
417 ((buffer[index + 1].toInt() and 0xFF) shl 8) or
+
418 ((buffer[index + 2].toInt() and 0xFF) shl 16) or
+
419 ((buffer[index + 3].toInt() and 0xFF) shl 24)
+
420 }
+
421
+
422 fun readUInt32(buffer: ByteArray, offset: Long): UInt
+
423 {
+
424 val index = offset.toInt()
+
425 return ((buffer[index + 0].toUInt() and 0xFFu) shl 0) or
+
426 ((buffer[index + 1].toUInt() and 0xFFu) shl 8) or
+
427 ((buffer[index + 2].toUInt() and 0xFFu) shl 16) or
+
428 ((buffer[index + 3].toUInt() and 0xFFu) shl 24)
+
429 }
+
430
+
431 fun readInt64(buffer: ByteArray, offset: Long): Long
+
432 {
+
433 val index = offset.toInt()
+
434 return ((buffer[index + 0].toLong() and 0xFF) shl 0) or
+
435 ((buffer[index + 1].toLong() and 0xFF) shl 8) or
+
436 ((buffer[index + 2].toLong() and 0xFF) shl 16) or
+
437 ((buffer[index + 3].toLong() and 0xFF) shl 24) or
+
438 ((buffer[index + 4].toLong() and 0xFF) shl 32) or
+
439 ((buffer[index + 5].toLong() and 0xFF) shl 40) or
+
440 ((buffer[index + 6].toLong() and 0xFF) shl 48) or
+
441 ((buffer[index + 7].toLong() and 0xFF) shl 56)
+
442 }
+
443
+
444 fun readUInt64(buffer: ByteArray, offset: Long): ULong
+
445 {
+
446 val index = offset.toInt()
+
447 return ((buffer[index + 0].toULong() and 0xFFu) shl 0) or
+
448 ((buffer[index + 1].toULong() and 0xFFu) shl 8) or
+
449 ((buffer[index + 2].toULong() and 0xFFu) shl 16) or
+
450 ((buffer[index + 3].toULong() and 0xFFu) shl 24) or
+
451 ((buffer[index + 4].toULong() and 0xFFu) shl 32) or
+
452 ((buffer[index + 5].toULong() and 0xFFu) shl 40) or
+
453 ((buffer[index + 6].toULong() and 0xFFu) shl 48) or
+
454 ((buffer[index + 7].toULong() and 0xFFu) shl 56)
+
455 }
+
456
+
457 private fun readInt64BE(buffer: ByteArray, offset: Long): Long
+
458 {
+
459 val index = offset.toInt()
+
460 return ((buffer[index + 0].toLong() and 0xFF) shl 56) or
+
461 ((buffer[index + 1].toLong() and 0xFF) shl 48) or
+
462 ((buffer[index + 2].toLong() and 0xFF) shl 40) or
+
463 ((buffer[index + 3].toLong() and 0xFF) shl 32) or
+
464 ((buffer[index + 4].toLong() and 0xFF) shl 24) or
+
465 ((buffer[index + 5].toLong() and 0xFF) shl 16) or
+
466 ((buffer[index + 6].toLong() and 0xFF) shl 8) or
+
467 ((buffer[index + 7].toLong() and 0xFF) shl 0)
+
468 }
+
469
+
470 fun readFloat(buffer: ByteArray, offset: Long): Float
+
471 {
+
472 val bits = readInt32(buffer, offset)
+
473 return java.lang.Float.intBitsToFloat(bits)
+
474 }
+
475
+
476 fun readDouble(buffer: ByteArray, offset: Long): Double
+
477 {
+
478 val bits = readInt64(buffer, offset)
+
479 return java.lang.Double.longBitsToDouble(bits)
+
480 }
+
481
+
482 fun readBytes(buffer: ByteArray, offset: Long, size: Long): ByteArray
+
483 {
+
484 val result = ByteArray(size.toInt())
+
485 System.arraycopy(buffer, offset.toInt(), result, 0, size.toInt())
+
486 return result
+
487 }
+
488
+
489 fun readString(buffer: ByteArray, offset: Long, size: Long): String
+
490 {
+
491 return String(buffer, offset.toInt(), size.toInt(), java.nio.charset.StandardCharsets.UTF_8)
+
492 }
+
493
+
494 fun readUUID(buffer: ByteArray, offset: Long): java.util.UUID
+
495 {
+
496 return java.util.UUID(readInt64BE(buffer, offset), readInt64BE(buffer, offset + 8))
+
497 }
+
498
+
499 fun write(buffer: ByteArray, offset: Long, value: Boolean)
+
500 {
+
501 buffer[offset.toInt()] = (if (value) 1 else 0).toByte()
+
502 }
+
503
+
504 fun write(buffer: ByteArray, offset: Long, value: Byte)
+
505 {
+
506 buffer[offset.toInt()] = value
+
507 }
+
508
+
509 fun write(buffer: ByteArray, offset: Long, value: UByte)
+
510 {
+
511 buffer[offset.toInt()] = value.toByte()
+
512 }
+
513
+
514 fun write(buffer: ByteArray, offset: Long, value: Short)
+
515 {
+
516 buffer[offset.toInt() + 0] = (value.toInt() shr 0).toByte()
+
517 buffer[offset.toInt() + 1] = (value.toInt() shr 8).toByte()
+
518 }
+
519
+
520 fun write(buffer: ByteArray, offset: Long, value: UShort)
+
521 {
+
522 buffer[offset.toInt() + 0] = (value.toUInt() shr 0).toByte()
+
523 buffer[offset.toInt() + 1] = (value.toUInt() shr 8).toByte()
+
524 }
+
525
+
526 fun write(buffer: ByteArray, offset: Long, value: Int)
+
527 {
+
528 buffer[offset.toInt() + 0] = (value shr 0).toByte()
+
529 buffer[offset.toInt() + 1] = (value shr 8).toByte()
+
530 buffer[offset.toInt() + 2] = (value shr 16).toByte()
+
531 buffer[offset.toInt() + 3] = (value shr 24).toByte()
+
532 }
+
533
+
534 fun write(buffer: ByteArray, offset: Long, value: UInt)
+
535 {
+
536 buffer[offset.toInt() + 0] = (value shr 0).toByte()
+
537 buffer[offset.toInt() + 1] = (value shr 8).toByte()
+
538 buffer[offset.toInt() + 2] = (value shr 16).toByte()
+
539 buffer[offset.toInt() + 3] = (value shr 24).toByte()
+
540 }
+
541
+
542 fun write(buffer: ByteArray, offset: Long, value: Long)
+
543 {
+
544 buffer[offset.toInt() + 0] = (value shr 0).toByte()
+
545 buffer[offset.toInt() + 1] = (value shr 8).toByte()
+
546 buffer[offset.toInt() + 2] = (value shr 16).toByte()
+
547 buffer[offset.toInt() + 3] = (value shr 24).toByte()
+
548 buffer[offset.toInt() + 4] = (value shr 32).toByte()
+
549 buffer[offset.toInt() + 5] = (value shr 40).toByte()
+
550 buffer[offset.toInt() + 6] = (value shr 48).toByte()
+
551 buffer[offset.toInt() + 7] = (value shr 56).toByte()
+
552 }
+
553
+
554 fun write(buffer: ByteArray, offset: Long, value: ULong)
+
555 {
+
556 buffer[offset.toInt() + 0] = (value shr 0).toByte()
+
557 buffer[offset.toInt() + 1] = (value shr 8).toByte()
+
558 buffer[offset.toInt() + 2] = (value shr 16).toByte()
+
559 buffer[offset.toInt() + 3] = (value shr 24).toByte()
+
560 buffer[offset.toInt() + 4] = (value shr 32).toByte()
+
561 buffer[offset.toInt() + 5] = (value shr 40).toByte()
+
562 buffer[offset.toInt() + 6] = (value shr 48).toByte()
+
563 buffer[offset.toInt() + 7] = (value shr 56).toByte()
+
564 }
+
565
+
566 private fun writeBE(buffer: ByteArray, offset: Long, value: Long)
+
567 {
+
568 buffer[offset.toInt() + 0] = (value shr 56).toByte()
+
569 buffer[offset.toInt() + 1] = (value shr 48).toByte()
+
570 buffer[offset.toInt() + 2] = (value shr 40).toByte()
+
571 buffer[offset.toInt() + 3] = (value shr 32).toByte()
+
572 buffer[offset.toInt() + 4] = (value shr 24).toByte()
+
573 buffer[offset.toInt() + 5] = (value shr 16).toByte()
+
574 buffer[offset.toInt() + 6] = (value shr 8).toByte()
+
575 buffer[offset.toInt() + 7] = (value shr 0).toByte()
+
576 }
+
577
+
578 fun write(buffer: ByteArray, offset: Long, value: Float)
+
579 {
+
580 val bits = java.lang.Float.floatToIntBits(value)
+
581 write(buffer, offset, bits)
+
582 }
+
583
+
584 fun write(buffer: ByteArray, offset: Long, value: Double)
+
585 {
+
586 val bits = java.lang.Double.doubleToLongBits(value)
+
587 write(buffer, offset, bits)
+
588 }
+
589
+
590 fun write(buffer: ByteArray, offset: Long, value: ByteArray)
+
591 {
+
592 System.arraycopy(value, 0, buffer, offset.toInt(), value.size)
+
593 }
+
594
+
595 fun write(buffer: ByteArray, offset: Long, value: ByteArray, valueOffset: Long, valueSize: Long)
+
596 {
+
597 System.arraycopy(value, valueOffset.toInt(), buffer, offset.toInt(), valueSize.toInt())
+
598 }
+
599
+
600 fun write(buffer: ByteArray, offset: Long, value: Byte, valueCount: Long)
+
601 {
+
602 for (i in 0 until valueCount)
+
603 buffer[(offset + i).toInt()] = value
+
604 }
+
605
+
606 fun write(buffer: ByteArray, offset: Long, value: java.util.UUID)
+
607 {
+
608 writeBE(buffer, offset, value.mostSignificantBits)
+
609 writeBE(buffer, offset + 8, value.leastSignificantBits)
+
610 }
+
611 }
+
612}
+
613)CODE";
+
614
+
615 // Prepare code template
+
616 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
617
+
618 Write(code);
+
619
+
620 // Generate footer
+
621 GenerateFooter();
+
622
+
623 // Store the file
+
624 WriteEnd();
+
625 Store(file);
+
626}
+
627
+
628void GeneratorKotlin::GenerateFBEModel(const std::string& domain, const std::string& package)
+
629{
+
630 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
631
+
632 // Generate the file
+
633 CppCommon::Path file = path / "Model.kt";
+
634 WriteBegin();
+
635
+
636 // Generate headers
+
637 GenerateHeader("FBE");
+
638 GenerateImports(domain, package);
+
639
+
640 std::string code = R"CODE(
+
641// Fast Binary Encoding base model
+
642open class Model
+
643{
+
644 // Get bytes buffer
+
645 var buffer = Buffer()
+
646 private set
+
647
+
648 // Initialize a new model
+
649 protected constructor()
+
650 protected constructor(buffer: Buffer) { this.buffer = buffer }
+
651
+
652 // Attach memory buffer methods
+
653 fun attach() { buffer.attach() }
+
654 fun attach(capacity: Long) { buffer.attach(capacity) }
+
655 fun attach(buffer: ByteArray) { this.buffer.attach(buffer) }
+
656 fun attach(buffer: ByteArray, offset: Long) { this.buffer.attach(buffer, offset) }
+
657 fun attach(buffer: ByteArray, size: Long, offset: Long) { this.buffer.attach(buffer, size, offset) }
+
658 fun attach(buffer: Buffer) { this.buffer.attach(buffer.data, buffer.size, buffer.offset) }
+
659 fun attach(buffer: Buffer, offset: Long) { this.buffer.attach(buffer.data, buffer.size, offset) }
+
660
+
661 // Model buffer operations
+
662 fun allocate(size: Long): Long { return buffer.allocate(size) }
+
663 fun remove(offset: Long, size: Long) { buffer.remove(offset, size) }
+
664 fun reserve(capacity: Long) { buffer.reserve(capacity) }
+
665 fun resize(size: Long) { buffer.resize(size) }
+
666 fun reset() { buffer.reset() }
+
667 fun shift(offset: Long) { buffer.shift(offset) }
+
668 fun unshift(offset: Long) { buffer.unshift(offset) }
+
669
+
670 // Buffer I/O methods
+
671 protected fun readUInt32(offset: Long): UInt { return Buffer.readUInt32(buffer.data, buffer.offset + offset) }
+
672 protected fun write(offset: Long, value: UInt) { Buffer.write(buffer.data, buffer.offset + offset, value) }
+
673}
+
674)CODE";
+
675
+
676 // Prepare code template
+
677 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
678
+
679 Write(code);
+
680
+
681 // Generate footer
+
682 GenerateFooter();
+
683
+
684 // Store the file
+
685 WriteEnd();
+
686 Store(file);
+
687}
+
688
+
689void GeneratorKotlin::GenerateFBEFieldModel(const std::string& domain, const std::string& package)
+
690{
+
691 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
692
+
693 // Generate the file
+
694 CppCommon::Path file = path / "FieldModel.kt";
+
695 WriteBegin();
+
696
+
697 // Generate headers
+
698 GenerateHeader("FBE");
+
699 GenerateImports(domain, package);
+
700
+
701 std::string code = R"CODE(
+
702// Fast Binary Encoding base field model
+
703@Suppress("MemberVisibilityCanBePrivate")
+
704abstract class FieldModel protected constructor(protected var _buffer: Buffer, protected var _offset: Long)
+
705{
+
706 // Field offset
+
707 var fbeOffset: Long
+
708 get() = _offset
+
709 set(value) { _offset = value }
+
710 // Field size
+
711 open val fbeSize: Long = 0
+
712 // Field extra size
+
713 open val fbeExtra: Long = 0
+
714
+
715 // Shift the current field offset
+
716 fun fbeShift(size: Long) { _offset += size }
+
717 // Unshift the current field offset
+
718 fun fbeUnshift(size: Long) { _offset -= size }
+
719
+
720 // Check if the value is valid
+
721 open fun verify(): Boolean = true
+
722
+
723 // Buffer I/O methods
+
724 protected fun readBoolean(offset: Long): Boolean { return Buffer.readBoolean(_buffer.data, _buffer.offset + offset) }
+
725 protected fun readByte(offset: Long): Byte { return Buffer.readByte(_buffer.data, _buffer.offset + offset) }
+
726 protected fun readChar(offset: Long): Char { return Buffer.readChar(_buffer.data, _buffer.offset + offset) }
+
727 protected fun readWChar(offset: Long): Char { return Buffer.readWChar(_buffer.data, _buffer.offset + offset) }
+
728 protected fun readInt8(offset: Long): Byte { return Buffer.readInt8(_buffer.data, _buffer.offset + offset) }
+
729 protected fun readUInt8(offset: Long): UByte { return Buffer.readUInt8(_buffer.data, _buffer.offset + offset) }
+
730 protected fun readInt16(offset: Long): Short { return Buffer.readInt16(_buffer.data, _buffer.offset + offset) }
+
731 protected fun readUInt16(offset: Long): UShort { return Buffer.readUInt16(_buffer.data, _buffer.offset + offset) }
+
732 protected fun readInt32(offset: Long): Int { return Buffer.readInt32(_buffer.data, _buffer.offset + offset) }
+
733 protected fun readUInt32(offset: Long): UInt { return Buffer.readUInt32(_buffer.data, _buffer.offset + offset) }
+
734 protected fun readInt64(offset: Long): Long { return Buffer.readInt64(_buffer.data, _buffer.offset + offset) }
+
735 protected fun readUInt64(offset: Long): ULong { return Buffer.readUInt64(_buffer.data, _buffer.offset + offset) }
+
736 protected fun readFloat(offset: Long): Float { return Buffer.readFloat(_buffer.data, _buffer.offset + offset) }
+
737 protected fun readDouble(offset: Long): Double { return Buffer.readDouble(_buffer.data, _buffer.offset + offset) }
+
738 protected fun readBytes(offset: Long, size: Long): ByteArray { return Buffer.readBytes(_buffer.data, _buffer.offset + offset, size) }
+
739 protected fun readString(offset: Long, size: Long): String { return Buffer.readString(_buffer.data, _buffer.offset + offset, size) }
+
740 protected fun readUUID(offset: Long): java.util.UUID { return Buffer.readUUID(_buffer.data, _buffer.offset + offset) }
+
741 protected fun write(offset: Long, value: Boolean) { Buffer.write(_buffer.data, _buffer.offset + offset, value) }
+
742 protected fun write(offset: Long, value: Byte) { Buffer.write(_buffer.data, _buffer.offset + offset, value) }
+
743 protected fun write(offset: Long, value: UByte) { Buffer.write(_buffer.data, _buffer.offset + offset, value) }
+
744 protected fun write(offset: Long, value: Short) { Buffer.write(_buffer.data, _buffer.offset + offset, value) }
+
745 protected fun write(offset: Long, value: UShort) { Buffer.write(_buffer.data, _buffer.offset + offset, value) }
+
746 protected fun write(offset: Long, value: Int) { Buffer.write(_buffer.data, _buffer.offset + offset, value) }
+
747 protected fun write(offset: Long, value: UInt) { Buffer.write(_buffer.data, _buffer.offset + offset, value) }
+
748 protected fun write(offset: Long, value: Long) { Buffer.write(_buffer.data, _buffer.offset + offset, value) }
+
749 protected fun write(offset: Long, value: ULong) { Buffer.write(_buffer.data, _buffer.offset + offset, value) }
+
750 protected fun write(offset: Long, value: Float) { Buffer.write(_buffer.data, _buffer.offset + offset, value) }
+
751 protected fun write(offset: Long, value: Double) { Buffer.write(_buffer.data, _buffer.offset + offset, value) }
+
752 protected fun write(offset: Long, value: ByteArray) { Buffer.write(_buffer.data, _buffer.offset + offset, value) }
+
753 protected fun write(offset: Long, value: ByteArray, valueOffset: Long, valueSize: Long) { Buffer.write(_buffer.data, _buffer.offset + offset, value, valueOffset, valueSize) }
+
754 protected fun write(offset: Long, value: Byte, valueCount: Long) { Buffer.write(_buffer.data, _buffer.offset + offset, value, valueCount) }
+
755 protected fun write(offset: Long, value: java.util.UUID) { Buffer.write(_buffer.data, _buffer.offset + offset, value) }
+
756}
+
757)CODE";
+
758
+
759 // Prepare code template
+
760 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
761
+
762 Write(code);
+
763
+
764 // Generate footer
+
765 GenerateFooter();
+
766
+
767 // Store the file
+
768 WriteEnd();
+
769 Store(file);
+
770}
+
771
+
772void GeneratorKotlin::GenerateFBEFieldModel(const std::string& domain, const std::string& package, const std::string& name, const std::string& type, const std::string& base, const std::string& size, const std::string& defaults)
+
773{
+
774 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
775
+
776 // Generate the file
+
777 CppCommon::Path file = path / ("FieldModel" + name + ".kt");
+
778 WriteBegin();
+
779
+
780 // Generate headers
+
781 GenerateHeader("FBE");
+
782 GenerateImports(domain, package);
+
783
+
784 std::string code = R"CODE(
+
785// Fast Binary Encoding _TYPE_ field model
+
786class FieldModel_NAME_(buffer: Buffer, offset: Long) : FieldModel(buffer, offset)
+
787{
+
788 // Field size
+
789 override val fbeSize: Long = _SIZE_
+
790
+
791 // Get the value
+
792 fun get(defaults: _TYPE_ = _DEFAULTS_): _TYPE_
+
793 {
+
794 if ((_buffer.offset + fbeOffset + fbeSize) > _buffer.size)
+
795 return defaults
+
796
+
797 return read_NAME_(fbeOffset)
+
798 }
+
799
+
800 // Set the value
+
801 fun set(value: _TYPE_)
+
802 {
+
803 assert((_buffer.offset + fbeOffset + fbeSize) <= _buffer.size) { "Model is broken!" }
+
804 if ((_buffer.offset + fbeOffset + fbeSize) > _buffer.size)
+
805 return
+
806
+
807 write(fbeOffset, value_BASE_)
+
808 }
+
809}
+
810)CODE";
+
811
+
812 // Prepare code template
+
813 code = std::regex_replace(code, std::regex("_NAME_"), name);
+
814 code = std::regex_replace(code, std::regex("_TYPE_"), type);
+
815 code = std::regex_replace(code, std::regex("_BASE_"), base);
+
816 code = std::regex_replace(code, std::regex("_SIZE_"), size);
+
817 code = std::regex_replace(code, std::regex("_DEFAULTS_"), defaults);
+
818 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
819
+
820 Write(code);
+
821
+
822 // Generate footer
+
823 GenerateFooter();
+
824
+
825 // Store the file
+
826 WriteEnd();
+
827 Store(file);
+
828}
+
829
+
830void GeneratorKotlin::GenerateFBEFieldModelDecimal(const std::string& domain, const std::string& package)
+
831{
+
832 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
833
+
834 // Generate the file
+
835 CppCommon::Path file = path / "FieldModelDecimal.kt";
+
836 WriteBegin();
+
837
+
838 // Generate headers
+
839 GenerateHeader("FBE");
+
840 GenerateImports(domain, package);
+
841
+
842 std::string code = R"CODE(
+
843// Fast Binary Encoding decimal field model
+
844class FieldModelDecimal(buffer: Buffer, offset: Long) : FieldModel(buffer, offset)
+
845{
+
846 // Field size
+
847 override val fbeSize: Long = 16
+
848
+
849 // Get the decimal value
+
850 fun get(defaults: java.math.BigDecimal = java.math.BigDecimal.valueOf(0L)): java.math.BigDecimal
+
851 {
+
852 if ((_buffer.offset + fbeOffset + fbeSize) > _buffer.size)
+
853 return defaults
+
854
+
855 val magnitude = readBytes(fbeOffset, 12)
+
856 val scale = readByte(fbeOffset + 14).toInt()
+
857 val signum = if (readByte(fbeOffset + 15) < 0) -1 else 1
+
858
+
859 // Reverse magnitude
+
860 for (i in 0 until (magnitude.size / 2))
+
861 {
+
862 val temp = magnitude[i]
+
863 magnitude[i] = magnitude[magnitude.size - i - 1]
+
864 magnitude[magnitude.size - i - 1] = temp
+
865 }
+
866
+
867 val unscaled = java.math.BigInteger(signum, magnitude)
+
868
+
869 return java.math.BigDecimal(unscaled, scale)
+
870 }
+
871
+
872 // Set the decimal value
+
873 fun set(value: java.math.BigDecimal)
+
874 {
+
875 assert((_buffer.offset + fbeOffset + fbeSize) <= _buffer.size) { "Model is broken!" }
+
876 if ((_buffer.offset + fbeOffset + fbeSize) > _buffer.size)
+
877 return
+
878
+
879 // Get unscaled absolute value
+
880 val unscaled = value.abs().unscaledValue()
+
881 val bitLength = unscaled.bitLength()
+
882 if ((bitLength < 0) || (bitLength > 96))
+
883 {
+
884 // Value too big for .NET Decimal (bit length is limited to [0, 96])
+
885 write(fbeOffset, 0.toByte(), fbeSize)
+
886 return
+
887 }
+
888
+
889 // Get byte array
+
890 val unscaledBytes = unscaled.toByteArray()
+
891
+
892 // Get scale
+
893 val scale = value.scale()
+
894 if ((scale < 0) || (scale > 28))
+
895 {
+
896 // Value scale exceeds .NET Decimal limit of [0, 28]
+
897 write(fbeOffset, 0.toByte(), fbeSize)
+
898 return
+
899 }
+
900
+
901 // Write unscaled value to bytes 0-11
+
902 var index = 0
+
903 var i = unscaledBytes.size - 1
+
904 while ((i >= 0) && (index < 12))
+
905 {
+
906 write(fbeOffset + index, unscaledBytes[i])
+
907 i--
+
908 index++
+
909 }
+
910
+
911 // Fill remaining bytes with zeros
+
912 while (index < 14)
+
913 {
+
914 write(fbeOffset + index, 0.toByte())
+
915 index++
+
916 }
+
917
+
918 // Write scale at byte 14
+
919 write(fbeOffset + 14, scale.toByte())
+
920
+
921 // Write signum at byte 15
+
922 write(fbeOffset + 15, (if (value.signum() < 0) -128 else 0).toByte())
+
923 }
+
924}
+
925)CODE";
+
926
+
927 // Prepare code template
+
928 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
929
+
930 Write(code);
+
931
+
932 // Generate footer
+
933 GenerateFooter();
+
934
+
935 // Store the file
+
936 WriteEnd();
+
937 Store(file);
+
938}
+
939
+
940void GeneratorKotlin::GenerateFBEFieldModelDate(const std::string& domain, const std::string& package)
+
941{
+
942 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
943
+
944 // Generate the file
+
945 CppCommon::Path file = path / "FieldModelDate.kt";
+
946 WriteBegin();
+
947
+
948 // Generate headers
+
949 GenerateHeader("FBE");
+
950 GenerateImports(domain, package);
+
951
+
952 std::string code = R"CODE(
+
953// Fast Binary Encoding date field model
+
954class FieldModelDate(buffer: Buffer, offset: Long) : FieldModel(buffer, offset)
+
955{
+
956 // Field size
+
957 override val fbeSize: Long = 8
+
958
+
959 // Get the date value
+
960 fun get(defaults: java.util.Date = java.util.Date(0)): java.util.Date
+
961 {
+
962 if ((_buffer.offset + fbeOffset + fbeSize) > _buffer.size)
+
963 return defaults
+
964
+
965 val nanoseconds = readInt64(fbeOffset)
+
966 return java.util.Date(nanoseconds / 1000000)
+
967 }
+
968
+
969 // Set the date value
+
970 fun set(value: java.util.Date)
+
971 {
+
972 assert((_buffer.offset + fbeOffset + fbeSize) <= _buffer.size) { "Model is broken!" }
+
973 if ((_buffer.offset + fbeOffset + fbeSize) > _buffer.size)
+
974 return
+
975
+
976 val nanoseconds = value.time * 1000000
+
977 write(fbeOffset, nanoseconds.toULong())
+
978 }
+
979}
+
980)CODE";
+
981
+
982 // Prepare code template
+
983 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
984
+
985 Write(code);
+
986
+
987 // Generate footer
+
988 GenerateFooter();
+
989
+
990 // Store the file
+
991 WriteEnd();
+
992 Store(file);
+
993}
+
994
+
995void GeneratorKotlin::GenerateFBEFieldModelTimestamp(const std::string& domain, const std::string& package)
+
996{
+
997 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
998
+
999 // Generate the file
+
1000 CppCommon::Path file = path / "FieldModelTimestamp.kt";
+
1001 WriteBegin();
+
1002
+
1003 // Generate headers
+
1004 GenerateHeader("FBE");
+
1005 GenerateImports(domain, package);
+
1006
+
1007 std::string code = R"CODE(
+
1008// Fast Binary Encoding timestamp field model
+
1009class FieldModelTimestamp(buffer: Buffer, offset: Long) : FieldModel(buffer, offset)
+
1010{
+
1011 // Field size
+
1012 override val fbeSize: Long = 8
+
1013
+
1014 // Get the timestamp value
+
1015 fun get(defaults: java.time.Instant = java.time.Instant.EPOCH): java.time.Instant
+
1016 {
+
1017 if ((_buffer.offset + fbeOffset + fbeSize) > _buffer.size)
+
1018 return defaults
+
1019
+
1020 val nanoseconds = readInt64(fbeOffset)
+
1021 return java.time.Instant.ofEpochSecond(nanoseconds / 1000000000, nanoseconds % 1000000000)
+
1022 }
+
1023
+
1024 // Set the timestamp value
+
1025 fun set(value: java.time.Instant)
+
1026 {
+
1027 assert((_buffer.offset + fbeOffset + fbeSize) <= _buffer.size) { "Model is broken!" }
+
1028 if ((_buffer.offset + fbeOffset + fbeSize) > _buffer.size)
+
1029 return
+
1030
+
1031 val nanoseconds = value.epochSecond * 1000000000 + value.nano
+
1032 write(fbeOffset, nanoseconds.toULong())
+
1033 }
+
1034}
+
1035)CODE";
+
1036
+
1037 // Prepare code template
+
1038 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
1039
+
1040 Write(code);
+
1041
+
1042 // Generate footer
+
1043 GenerateFooter();
+
1044
+
1045 // Store the file
+
1046 WriteEnd();
+
1047 Store(file);
+
1048}
+
1049
+
1050void GeneratorKotlin::GenerateFBEFieldModelBytes(const std::string& domain, const std::string& package)
+
1051{
+
1052 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
1053
+
1054 // Generate the file
+
1055 CppCommon::Path file = path / "FieldModelBytes.kt";
+
1056 WriteBegin();
+
1057
+
1058 // Generate headers
+
1059 GenerateHeader("FBE");
+
1060 GenerateImports(domain, package);
+
1061
+
1062 std::string code = R"CODE(
+
1063// Fast Binary Encoding bytes field model
+
1064class FieldModelBytes(buffer: Buffer, offset: Long) : FieldModel(buffer, offset)
+
1065{
+
1066 // Field size
+
1067 override val fbeSize: Long = 4
+
1068
+
1069 // Field extra size
+
1070 override val fbeExtra: Long get()
+
1071 {
+
1072 if ((_buffer.offset + fbeOffset + fbeSize) > _buffer.size)
+
1073 return 0
+
1074
+
1075 val fbeBytesOffset = readUInt32(fbeOffset).toLong()
+
1076 if ((fbeBytesOffset == 0L) || ((_buffer.offset + fbeBytesOffset + 4) > _buffer.size))
+
1077 return 0
+
1078
+
1079 val fbeBytesSize = readUInt32(fbeBytesOffset).toLong()
+
1080 return 4 + fbeBytesSize
+
1081 }
+
1082
+
1083 // Check if the bytes value is valid
+
1084 override fun verify(): Boolean
+
1085 {
+
1086 if ((_buffer.offset + fbeOffset + fbeSize) > _buffer.size)
+
1087 return true
+
1088
+
1089 val fbeBytesOffset = readUInt32(fbeOffset).toLong()
+
1090 if (fbeBytesOffset == 0L)
+
1091 return true
+
1092
+
1093 if ((_buffer.offset + fbeBytesOffset + 4) > _buffer.size)
+
1094 return false
+
1095
+
1096 val fbeBytesSize = readUInt32(fbeBytesOffset).toLong()
+
1097 if ((_buffer.offset + fbeBytesOffset + 4 + fbeBytesSize) > _buffer.size)
+
1098 return false
+
1099
+
1100 return true
+
1101 }
+
1102
+
1103 // Get the bytes value
+
1104 fun get(defaults: ByteArray = ByteArray(0)): ByteArray
+
1105 {
+
1106 if ((_buffer.offset + fbeOffset + fbeSize) > _buffer.size)
+
1107 return defaults
+
1108
+
1109 val fbeBytesOffset = readUInt32(fbeOffset).toLong()
+
1110 if (fbeBytesOffset == 0L)
+
1111 return defaults
+
1112
+
1113 assert((_buffer.offset + fbeBytesOffset + 4) <= _buffer.size) { "Model is broken!" }
+
1114 if ((_buffer.offset + fbeBytesOffset + 4) > _buffer.size)
+
1115 return defaults
+
1116
+
1117 val fbeBytesSize = readUInt32(fbeBytesOffset).toLong()
+
1118 assert((_buffer.offset + fbeBytesOffset + 4 + fbeBytesSize) <= _buffer.size) { "Model is broken!" }
+
1119 if ((_buffer.offset + fbeBytesOffset + 4 + fbeBytesSize) > _buffer.size)
+
1120 return defaults
+
1121
+
1122 return readBytes(fbeBytesOffset + 4, fbeBytesSize)
+
1123 }
+
1124
+
1125 // Set the bytes value
+
1126 fun set(value: ByteArray)
+
1127 {
+
1128 assert((_buffer.offset + fbeOffset + fbeSize) <= _buffer.size) { "Model is broken!" }
+
1129 if ((_buffer.offset + fbeOffset + fbeSize) > _buffer.size)
+
1130 return
+
1131
+
1132 val fbeBytesSize = value.size.toLong()
+
1133 val fbeBytesOffset = _buffer.allocate(4 + fbeBytesSize) - _buffer.offset
+
1134 assert((fbeBytesOffset > 0) && ((_buffer.offset + fbeBytesOffset + 4 + fbeBytesSize) <= _buffer.size)) { "Model is broken!" }
+
1135 if ((fbeBytesOffset <= 0) || ((_buffer.offset + fbeBytesOffset + 4 + fbeBytesSize) > _buffer.size))
+
1136 return
+
1137
+
1138 write(fbeOffset, fbeBytesOffset.toUInt())
+
1139 write(fbeBytesOffset, fbeBytesSize.toUInt())
+
1140 write(fbeBytesOffset + 4, value)
+
1141 }
+
1142}
+
1143)CODE";
+
1144
+
1145 // Prepare code template
+
1146 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
1147
+
1148 Write(code);
+
1149
+
1150 // Generate footer
+
1151 GenerateFooter();
+
1152
+
1153 // Store the file
+
1154 WriteEnd();
+
1155 Store(file);
+
1156}
+
1157
+
1158void GeneratorKotlin::GenerateFBEFieldModelString(const std::string& domain, const std::string& package)
+
1159{
+
1160 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
1161
+
1162 // Generate the file
+
1163 CppCommon::Path file = path / "FieldModelString.kt";
+
1164 WriteBegin();
+
1165
+
1166 // Generate headers
+
1167 GenerateHeader("FBE");
+
1168 GenerateImports(domain, package);
+
1169
+
1170 std::string code = R"CODE(
+
1171// Fast Binary Encoding string field model
+
1172class FieldModelString(buffer: Buffer, offset: Long) : FieldModel(buffer, offset)
+
1173{
+
1174 // Field size
+
1175 override val fbeSize: Long = 4
+
1176
+
1177 // Field extra size
+
1178 override val fbeExtra: Long get()
+
1179 {
+
1180 if ((_buffer.offset + fbeOffset + fbeSize) > _buffer.size)
+
1181 return 0
+
1182
+
1183 val fbeStringOffset = readUInt32(fbeOffset).toLong()
+
1184 if ((fbeStringOffset == 0L) || ((_buffer.offset + fbeStringOffset + 4) > _buffer.size))
+
1185 return 0
+
1186
+
1187 val fbeStringSize = readUInt32(fbeStringOffset).toLong()
+
1188 return 4 + fbeStringSize
+
1189 }
+
1190
+
1191 // Check if the string value is valid
+
1192 override fun verify(): Boolean
+
1193 {
+
1194 if ((_buffer.offset + fbeOffset + fbeSize) > _buffer.size)
+
1195 return true
+
1196
+
1197 val fbeStringOffset = readUInt32(fbeOffset).toLong()
+
1198 if (fbeStringOffset == 0L)
+
1199 return true
+
1200
+
1201 if ((_buffer.offset + fbeStringOffset + 4) > _buffer.size)
+
1202 return false
+
1203
+
1204 val fbeStringSize = readUInt32(fbeStringOffset).toLong()
+
1205 if ((_buffer.offset + fbeStringOffset + 4 + fbeStringSize) > _buffer.size)
+
1206 return false
+
1207
+
1208 return true
+
1209 }
+
1210
+
1211 // Get the string value
+
1212 fun get(defaults: String = ""): String
+
1213 {
+
1214 if ((_buffer.offset + fbeOffset + fbeSize) > _buffer.size)
+
1215 return defaults
+
1216
+
1217 val fbeStringOffset = readUInt32(fbeOffset).toLong()
+
1218 if (fbeStringOffset == 0L)
+
1219 return defaults
+
1220
+
1221 assert((_buffer.offset + fbeStringOffset + 4) <= _buffer.size) { "Model is broken!" }
+
1222 if ((_buffer.offset + fbeStringOffset + 4) > _buffer.size)
+
1223 return defaults
+
1224
+
1225 val fbeStringSize = readUInt32(fbeStringOffset).toLong()
+
1226 assert((_buffer.offset + fbeStringOffset + 4 + fbeStringSize) <= _buffer.size) { "Model is broken!" }
+
1227 if ((_buffer.offset + fbeStringOffset + 4 + fbeStringSize) > _buffer.size)
+
1228 return defaults
+
1229
+
1230 return readString(fbeStringOffset + 4, fbeStringSize)
+
1231 }
+
1232
+
1233 // Set the string value
+
1234 fun set(value: String)
+
1235 {
+
1236 assert((_buffer.offset + fbeOffset + fbeSize) <= _buffer.size) { "Model is broken!" }
+
1237 if ((_buffer.offset + fbeOffset + fbeSize) > _buffer.size)
+
1238 return
+
1239
+
1240 val bytes = value.toByteArray(java.nio.charset.StandardCharsets.UTF_8)
+
1241
+
1242 val fbeStringSize = bytes.size.toLong()
+
1243 val fbeStringOffset = _buffer.allocate(4 + fbeStringSize) - _buffer.offset
+
1244 assert((fbeStringOffset > 0) && ((_buffer.offset + fbeStringOffset + 4 + fbeStringSize) <= _buffer.size)) { "Model is broken!" }
+
1245 if ((fbeStringOffset <= 0) || ((_buffer.offset + fbeStringOffset + 4 + fbeStringSize) > _buffer.size))
+
1246 return
+
1247
+
1248 write(fbeOffset, fbeStringOffset.toUInt())
+
1249 write(fbeStringOffset, fbeStringSize.toUInt())
+
1250 write(fbeStringOffset + 4, bytes)
+
1251 }
+
1252}
+
1253)CODE";
+
1254
+
1255 // Prepare code template
+
1256 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
1257
+
1258 Write(code);
+
1259
+
1260 // Generate footer
+
1261 GenerateFooter();
+
1262
+
1263 // Store the file
+
1264 WriteEnd();
+
1265 Store(file);
+
1266}
+
1267
+
1268void GeneratorKotlin::GenerateFBEFieldModelOptional(const std::string& domain, const std::string& package, const std::string& name, const std::string& type, const std::string& model)
+
1269{
+
1270 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "fbe";
+
1271
+
1272 // Create package path
+
1273 CppCommon::Directory::CreateTree(path);
+
1274
+
1275 // Generate the file
+
1276 CppCommon::Path file = path / ("FieldModelOptional" + name + ".kt");
+
1277 WriteBegin();
+
1278
+
1279 // Generate headers
+
1280 GenerateHeader(CppCommon::Path(_input).filename().string());
+
1281 GenerateImports(domain, package + ".fbe");
+
1282
+
1283 std::string code = R"CODE(
+
1284// Fast Binary Encoding optional _NAME_ field model
+
1285class FieldModelOptional_NAME_(buffer: _DOMAIN_fbe.Buffer, offset: Long) : _DOMAIN_fbe.FieldModel(buffer, offset)
+
1286{
+
1287 // Field size
+
1288 override val fbeSize: Long = 1 + 4
+
1289
+
1290 // Field extra size
+
1291 override val fbeExtra: Long get()
+
1292 {
+
1293 if (!hasValue())
+
1294 return 0
+
1295
+
1296 val fbeOptionalOffset = readUInt32(fbeOffset + 1).toLong()
+
1297 if ((fbeOptionalOffset == 0L) || ((_buffer.offset + fbeOptionalOffset + 4) > _buffer.size))
+
1298 return 0
+
1299
+
1300 _buffer.shift(fbeOptionalOffset)
+
1301 val fbeResult = value.fbeSize + value.fbeExtra
+
1302 _buffer.unshift(fbeOptionalOffset)
+
1303 return fbeResult
+
1304 }
+
1305
+
1306 // Checks if the object contains a value
+
1307 fun hasValue(): Boolean
+
1308 {
+
1309 if ((_buffer.offset + fbeOffset + fbeSize) > _buffer.size)
+
1310 return false
+
1311
+
1312 val fbeHasValue = readInt8(fbeOffset).toInt()
+
1313 return fbeHasValue != 0
+
1314 }
+
1315
+
1316 // Base field model value
+
1317 val value = _MODEL_(buffer, 0)
+
1318
+
1319 // Check if the optional value is valid
+
1320 override fun verify(): Boolean
+
1321 {
+
1322 if ((_buffer.offset + fbeOffset + fbeSize) > _buffer.size)
+
1323 return true
+
1324
+
1325 val fbeHasValue = readInt8(fbeOffset).toInt()
+
1326 if (fbeHasValue == 0)
+
1327 return true
+
1328
+
1329 val fbeOptionalOffset = readUInt32(fbeOffset + 1).toLong()
+
1330 if (fbeOptionalOffset == 0L)
+
1331 return false
+
1332
+
1333 _buffer.shift(fbeOptionalOffset)
+
1334 val fbeResult = value.verify()
+
1335 _buffer.unshift(fbeOptionalOffset)
+
1336 return fbeResult
+
1337 }
+
1338
+
1339 // Get the optional value (being phase)
+
1340 fun getBegin(): Long
+
1341 {
+
1342 if (!hasValue())
+
1343 return 0
+
1344
+
1345 val fbeOptionalOffset = readUInt32(fbeOffset + 1).toLong()
+
1346 assert(fbeOptionalOffset > 0) { "Model is broken!" }
+
1347 if (fbeOptionalOffset <= 0)
+
1348 return 0
+
1349
+
1350 _buffer.shift(fbeOptionalOffset)
+
1351 return fbeOptionalOffset
+
1352 }
+
1353
+
1354 // Get the optional value (end phase)
+
1355 fun getEnd(fbeBegin: Long)
+
1356 {
+
1357 _buffer.unshift(fbeBegin)
+
1358 }
+
1359
+
1360 // Get the optional value
+
1361 fun get(defaults: _TYPE_ = null): _TYPE_
+
1362 {
+
1363 val fbeBegin = getBegin()
+
1364 if (fbeBegin == 0L)
+
1365 return defaults
+
1366
+
1367 val optional = value.get()
+
1368 getEnd(fbeBegin)
+
1369 return optional
+
1370 }
+
1371
+
1372 // Set the optional value (begin phase)
+
1373 fun setBegin(hasValue: Boolean): Long
+
1374 {
+
1375 assert((_buffer.offset + fbeOffset + fbeSize) <= _buffer.size) { "Model is broken!" }
+
1376 if ((_buffer.offset + fbeOffset + fbeSize) > _buffer.size)
+
1377 return 0
+
1378
+
1379 val fbeHasValue = if (hasValue) 1 else 0
+
1380 write(fbeOffset, fbeHasValue.toByte())
+
1381 if (fbeHasValue == 0)
+
1382 return 0
+
1383
+
1384 val fbeOptionalSize = value.fbeSize
+
1385 val fbeOptionalOffset = _buffer.allocate(fbeOptionalSize) - _buffer.offset
+
1386 assert((fbeOptionalOffset > 0) && ((_buffer.offset + fbeOptionalOffset + fbeOptionalSize) <= _buffer.size)) { "Model is broken!" }
+
1387 if ((fbeOptionalOffset <= 0) || ((_buffer.offset + fbeOptionalOffset + fbeOptionalSize) > _buffer.size))
+
1388 return 0
+
1389
+
1390 write(fbeOffset + 1, fbeOptionalOffset.toUInt())
+
1391
+
1392 _buffer.shift(fbeOptionalOffset)
+
1393 return fbeOptionalOffset
+
1394 }
+
1395
+
1396 // Set the optional value (end phase)
+
1397 fun setEnd(fbeBegin: Long)
+
1398 {
+
1399 _buffer.unshift(fbeBegin)
+
1400 }
+
1401
+
1402 // Set the optional value
+
1403 fun set(optional: _TYPE_)
+
1404 {
+
1405 val fbeBegin = setBegin(optional != null)
+
1406 if (fbeBegin == 0L)
+
1407 return
+
1408
+
1409 value.set(optional!!)
+
1410 setEnd(fbeBegin)
+
1411 }
+
1412}
+
1413)CODE";
+
1414
+
1415 std::string type_name = IsPackageType(type) ? type : (domain + package + "." + type);
+
1416
+
1417 // Prepare code template
+
1418 code = std::regex_replace(code, std::regex("_DOMAIN_"), domain);
+
1419 code = std::regex_replace(code, std::regex("_NAME_"), name);
+
1420 code = std::regex_replace(code, std::regex("_TYPE_"), type_name);
+
1421 code = std::regex_replace(code, std::regex("_MODEL_"), model);
+
1422 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
1423
+
1424 Write(code);
+
1425
+
1426 // Generate footer
+
1427 GenerateFooter();
+
1428
+
1429 // Store the file
+
1430 WriteEnd();
+
1431 Store(file);
+
1432}
+
1433
+
1434void GeneratorKotlin::GenerateFBEFieldModelArray(const std::string& domain, const std::string& package, const std::string& name, const std::string& type, const std::string& base, bool optional, const std::string& model)
+
1435{
+
1436 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "fbe";
+
1437
+
1438 // Create package path
+
1439 CppCommon::Directory::CreateTree(path);
+
1440
+
1441 // Generate the file
+
1442 CppCommon::Path file = path / ("FieldModelArray" + name + ".kt");
+
1443 WriteBegin();
+
1444
+
1445 // Generate headers
+
1446 GenerateHeader(CppCommon::Path(_input).filename().string());
+
1447 GenerateImports(domain, package + ".fbe");
+
1448
+
1449 std::string code = R"CODE(
+
1450// Fast Binary Encoding _NAME_ array field model
+
1451class FieldModelArray_NAME_(buffer: _DOMAIN_fbe.Buffer, offset: Long, val size: Long) : _DOMAIN_fbe.FieldModel(buffer, offset)
+
1452{
+
1453 private val _model = _MODEL_(buffer, offset)
+
1454
+
1455 // Field size
+
1456 override val fbeSize: Long = size * _model.fbeSize
+
1457
+
1458 // Field extra size
+
1459 override val fbeExtra: Long = 0
+
1460
+
1461 // Get the array offset
+
1462 val offset: Long get() = 0
+
1463
+
1464 // Array index operator
+
1465 fun getItem(index: Long): _MODEL_
+
1466 {
+
1467 assert((_buffer.offset + fbeOffset + fbeSize) <= _buffer.size) { "Model is broken!" }
+
1468 assert(index < size) { "Index is out of bounds!" }
+
1469
+
1470 _model.fbeOffset = fbeOffset
+
1471 _model.fbeShift(index * _model.fbeSize)
+
1472 return _model
+
1473 }
+
1474
+
1475 // Check if the array is valid
+
1476 override fun verify(): Boolean
+
1477 {
+
1478 if ((_buffer.offset + fbeOffset + fbeSize) > _buffer.size)
+
1479 return false
+
1480
+
1481 _model.fbeOffset = fbeOffset
+
1482 var i = size
+
1483 while (i-- > 0)
+
1484 {
+
1485 if (!_model.verify())
+
1486 return false
+
1487 _model.fbeShift(_model.fbeSize)
+
1488 }
+
1489
+
1490 return true
+
1491 }
+
1492
+
1493 // Get the array
+
1494 fun get(): _ARRAY_
+
1495 {
+
1496 val values = _INIT_
+
1497
+
1498 val fbeModel = getItem(0)
+
1499 for (i in 0 until size)
+
1500 {
+
1501 values[i.toInt()] = fbeModel.get()
+
1502 fbeModel.fbeShift(fbeModel.fbeSize)
+
1503 }
+
1504 return values
+
1505 }
+
1506
+
1507 // Get the array
+
1508 fun get(values: _ARRAY_)
+
1509 {
+
1510 val fbeModel = getItem(0)
+
1511 var i: Long = 0
+
1512 while ((i < values.size) && (i < size))
+
1513 {
+
1514 values[i.toInt()] = fbeModel.get()
+
1515 fbeModel.fbeShift(fbeModel.fbeSize)
+
1516 i++
+
1517 }
+
1518 }
+
1519
+
1520 // Get the array as java.util.ArrayList
+
1521 fun get(values: java.util.ArrayList<_TYPE_>)
+
1522 {
+
1523 values.clear()
+
1524 values.ensureCapacity(size.toInt())
+
1525
+
1526 val fbeModel = getItem(0)
+
1527 var i = size
+
1528 while (i-- > 0)
+
1529 {
+
1530 val value = fbeModel.get()
+
1531 values.add(value)
+
1532 fbeModel.fbeShift(fbeModel.fbeSize)
+
1533 }
+
1534 }
+
1535
+
1536 // Set the array
+
1537 fun set(values: _ARRAY_)
+
1538 {
+
1539 assert((_buffer.offset + fbeOffset + fbeSize) <= _buffer.size) { "Model is broken!" }
+
1540 if ((_buffer.offset + fbeOffset + fbeSize) > _buffer.size)
+
1541 return
+
1542
+
1543 val fbeModel = getItem(0)
+
1544 var i: Long = 0
+
1545 while ((i < values.size) && (i < size))
+
1546 {
+
1547 fbeModel.set(values[i.toInt()])
+
1548 fbeModel.fbeShift(fbeModel.fbeSize)
+
1549 i++
+
1550 }
+
1551 }
+
1552
+
1553 // Set the array as java.util.ArrayList
+
1554 fun set(values: java.util.ArrayList<_TYPE_>)
+
1555 {
+
1556 assert((_buffer.offset + fbeOffset + fbeSize) <= _buffer.size) { "Model is broken!" }
+
1557 if ((_buffer.offset + fbeOffset + fbeSize) > _buffer.size)
+
1558 return
+
1559
+
1560 val fbeModel = getItem(0)
+
1561 var i: Long = 0
+
1562 while ((i < values.size) && (i < size))
+
1563 {
+
1564 fbeModel.set(values[i.toInt()])
+
1565 fbeModel.fbeShift(fbeModel.fbeSize)
+
1566 i++
+
1567 }
+
1568 }
+
1569}
+
1570)CODE";
+
1571
+
1572 std::string type_name = IsPackageType(type) ? type : (domain + package + "." + type);
+
1573
+
1574 // Prepare code template
+
1575 code = std::regex_replace(code, std::regex("_DOMAIN_"), domain);
+
1576 code = std::regex_replace(code, std::regex("_NAME_"), name);
+
1577 code = std::regex_replace(code, std::regex("_TYPE_"), type_name);
+
1578 code = std::regex_replace(code, std::regex("_MODEL_"), model);
+
1579 code = std::regex_replace(code, std::regex("_ARRAY_"), "Array<" + type_name + ">");
+
1580 if (optional)
+
1581 code = std::regex_replace(code, std::regex("_INIT_"), "arrayOfNulls<" + type_name + ">(size.toInt())");
+
1582 else
+
1583 code = std::regex_replace(code, std::regex("_INIT_"), "Array(size.toInt()) { " + ConvertDefault(domain, package, base) + " }");
+
1584 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
1585
+
1586 Write(code);
+
1587
+
1588 // Generate footer
+
1589 GenerateFooter();
+
1590
+
1591 // Store the file
+
1592 WriteEnd();
+
1593 Store(file);
+
1594}
+
1595
+
1596void GeneratorKotlin::GenerateFBEFieldModelVector(const std::string& domain, const std::string& package, const std::string& name, const std::string& type, const std::string& model)
+
1597{
+
1598 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "fbe";
+
1599
+
1600 // Create package path
+
1601 CppCommon::Directory::CreateTree(path);
+
1602
+
1603 // Generate the file
+
1604 CppCommon::Path file = path / ("FieldModelVector" + name + ".kt");
+
1605 WriteBegin();
+
1606
+
1607 // Generate headers
+
1608 GenerateHeader(CppCommon::Path(_input).filename().string());
+
1609 GenerateImports(domain, package + ".fbe");
+
1610
+
1611 std::string code = R"CODE(
+
1612// Fast Binary Encoding _NAME_ vector field model
+
1613class FieldModelVector_NAME_(buffer: _DOMAIN_fbe.Buffer, offset: Long) : _DOMAIN_fbe.FieldModel(buffer, offset)
+
1614{
+
1615 private val _model = _MODEL_(buffer, offset)
+
1616
+
1617 // Field size
+
1618 override val fbeSize: Long = 4
+
1619
+
1620 // Field extra size
+
1621 override val fbeExtra: Long get()
+
1622 {
+
1623 if ((_buffer.offset + fbeOffset + fbeSize) > _buffer.size)
+
1624 return 0
+
1625
+
1626 val fbeVectorOffset = readUInt32(fbeOffset).toLong()
+
1627 if ((fbeVectorOffset == 0L) || ((_buffer.offset + fbeVectorOffset + 4) > _buffer.size))
+
1628 return 0
+
1629
+
1630 val fbeVectorSize = readUInt32(fbeVectorOffset).toLong()
+
1631
+
1632 var fbeResult: Long = 4
+
1633 _model.fbeOffset = fbeVectorOffset + 4
+
1634 var i = fbeVectorSize
+
1635 while (i-- > 0)
+
1636 {
+
1637 fbeResult += _model.fbeSize + _model.fbeExtra
+
1638 _model.fbeShift(_model.fbeSize)
+
1639 }
+
1640 return fbeResult
+
1641 }
+
1642
+
1643 // Get the vector offset
+
1644 val offset: Long get()
+
1645 {
+
1646 if ((_buffer.offset + fbeOffset + fbeSize) > _buffer.size)
+
1647 return 0
+
1648
+
1649 return readUInt32(fbeOffset).toLong()
+
1650 }
+
1651
+
1652 // Get the vector size
+
1653 val size: Long get()
+
1654 {
+
1655 if ((_buffer.offset + fbeOffset + fbeSize) > _buffer.size)
+
1656 return 0
+
1657
+
1658 val fbeVectorOffset = readUInt32(fbeOffset).toLong()
+
1659 if ((fbeVectorOffset == 0L) || ((_buffer.offset + fbeVectorOffset + 4) > _buffer.size))
+
1660 return 0
+
1661
+
1662 return readUInt32(fbeVectorOffset).toLong()
+
1663 }
+
1664
+
1665 // Vector index operator
+
1666 fun getItem(index: Long): _MODEL_
+
1667 {
+
1668 assert((_buffer.offset + fbeOffset + fbeSize) <= _buffer.size) { "Model is broken!" }
+
1669
+
1670 val fbeVectorOffset = readUInt32(fbeOffset).toLong()
+
1671 assert((fbeVectorOffset > 0) && ((_buffer.offset + fbeVectorOffset + 4) <= _buffer.size)) { "Model is broken!" }
+
1672
+
1673 val fbeVectorSize = readUInt32(fbeVectorOffset).toLong()
+
1674 assert(index < fbeVectorSize) { "Index is out of bounds!" }
+
1675
+
1676 _model.fbeOffset = fbeVectorOffset + 4
+
1677 _model.fbeShift(index * _model.fbeSize)
+
1678 return _model
+
1679 }
+
1680
+
1681 // Resize the vector and get its first model
+
1682 fun resize(size: Long): _MODEL_
+
1683 {
+
1684 val fbeVectorSize = size * _model.fbeSize
+
1685 val fbeVectorOffset = _buffer.allocate(4 + fbeVectorSize) - _buffer.offset
+
1686 assert((fbeVectorOffset > 0) && ((_buffer.offset + fbeVectorOffset + 4) <= _buffer.size)) { "Model is broken!" }
+
1687
+
1688 write(fbeOffset, fbeVectorOffset.toUInt())
+
1689 write(fbeVectorOffset, size.toUInt())
+
1690 write(fbeVectorOffset + 4, 0.toByte(), fbeVectorSize)
+
1691
+
1692 _model.fbeOffset = fbeVectorOffset + 4
+
1693 return _model
+
1694 }
+
1695
+
1696 // Check if the vector is valid
+
1697 override fun verify(): Boolean
+
1698 {
+
1699 if ((_buffer.offset + fbeOffset + fbeSize) > _buffer.size)
+
1700 return true
+
1701
+
1702 val fbeVectorOffset = readUInt32(fbeOffset).toLong()
+
1703 if (fbeVectorOffset == 0L)
+
1704 return true
+
1705
+
1706 if ((_buffer.offset + fbeVectorOffset + 4) > _buffer.size)
+
1707 return false
+
1708
+
1709 val fbeVectorSize = readUInt32(fbeVectorOffset).toLong()
+
1710
+
1711 _model.fbeOffset = fbeVectorOffset + 4
+
1712 var i = fbeVectorSize
+
1713 while (i-- > 0)
+
1714 {
+
1715 if (!_model.verify())
+
1716 return false
+
1717 _model.fbeShift(_model.fbeSize)
+
1718 }
+
1719
+
1720 return true
+
1721 }
+
1722
+
1723 // Get the vector as java.util.ArrayList
+
1724 operator fun get(values: java.util.ArrayList<_TYPE_>)
+
1725 {
+
1726 values.clear()
+
1727
+
1728 val fbeVectorSize = size
+
1729 if (fbeVectorSize == 0L)
+
1730 return
+
1731
+
1732 values.ensureCapacity(fbeVectorSize.toInt())
+
1733
+
1734 val fbeModel = getItem(0)
+
1735 var i = fbeVectorSize
+
1736 while (i-- > 0)
+
1737 {
+
1738 val value = fbeModel.get()
+
1739 values.add(value)
+
1740 fbeModel.fbeShift(fbeModel.fbeSize)
+
1741 }
+
1742 }
+
1743
+
1744 // Get the vector as java.util.LinkedList
+
1745 operator fun get(values: java.util.LinkedList<_TYPE_>)
+
1746 {
+
1747 values.clear()
+
1748
+
1749 val fbeVectorSize = size
+
1750 if (fbeVectorSize == 0L)
+
1751 return
+
1752
+
1753 val fbeModel = getItem(0)
+
1754 var i = fbeVectorSize
+
1755 while (i-- > 0)
+
1756 {
+
1757 val value = fbeModel.get()
+
1758 values.add(value)
+
1759 fbeModel.fbeShift(fbeModel.fbeSize)
+
1760 }
+
1761 }
+
1762
+
1763 // Get the vector as java.util.HashSet
+
1764 operator fun get(values: java.util.HashSet<_TYPE_>)
+
1765 {
+
1766 values.clear()
+
1767
+
1768 val fbeVectorSize = size
+
1769 if (fbeVectorSize == 0L)
+
1770 return
+
1771
+
1772 val fbeModel = getItem(0)
+
1773 var i = fbeVectorSize
+
1774 while (i-- > 0)
+
1775 {
+
1776 val value = fbeModel.get()
+
1777 values.add(value)
+
1778 fbeModel.fbeShift(fbeModel.fbeSize)
+
1779 }
+
1780 }
+
1781
+
1782 // Set the vector as java.util.ArrayList
+
1783 fun set(values: java.util.ArrayList<_TYPE_>)
+
1784 {
+
1785 assert((_buffer.offset + fbeOffset + fbeSize) <= _buffer.size) { "Model is broken!" }
+
1786 if ((_buffer.offset + fbeOffset + fbeSize) > _buffer.size)
+
1787 return
+
1788
+
1789 val fbeModel = resize(values.size.toLong())
+
1790 for (value in values)
+
1791 {
+
1792 fbeModel.set(value)
+
1793 fbeModel.fbeShift(fbeModel.fbeSize)
+
1794 }
+
1795 }
+
1796
+
1797 // Set the vector as java.util.LinkedList
+
1798 fun set(values: java.util.LinkedList<_TYPE_>)
+
1799 {
+
1800 assert((_buffer.offset + fbeOffset + fbeSize) <= _buffer.size) { "Model is broken!" }
+
1801 if ((_buffer.offset + fbeOffset + fbeSize) > _buffer.size)
+
1802 return
+
1803
+
1804 val fbeModel = resize(values.size.toLong())
+
1805 for (value in values)
+
1806 {
+
1807 fbeModel.set(value)
+
1808 fbeModel.fbeShift(fbeModel.fbeSize)
+
1809 }
+
1810 }
+
1811
+
1812 // Set the vector as java.util.HashSet
+
1813 fun set(values: java.util.HashSet<_TYPE_>)
+
1814 {
+
1815 assert((_buffer.offset + fbeOffset + fbeSize) <= _buffer.size) { "Model is broken!" }
+
1816 if ((_buffer.offset + fbeOffset + fbeSize) > _buffer.size)
+
1817 return
+
1818
+
1819 val fbeModel = resize(values.size.toLong())
+
1820 for (value in values)
+
1821 {
+
1822 fbeModel.set(value)
+
1823 fbeModel.fbeShift(fbeModel.fbeSize)
+
1824 }
+
1825 }
+
1826}
+
1827)CODE";
+
1828
+
1829 std::string type_name = IsPackageType(type) ? type : (domain + package + "." + type);
+
1830
+
1831 // Prepare code template
+
1832 code = std::regex_replace(code, std::regex("_DOMAIN_"), domain);
+
1833 code = std::regex_replace(code, std::regex("_NAME_"), name);
+
1834 code = std::regex_replace(code, std::regex("_TYPE_"), type_name);
+
1835 code = std::regex_replace(code, std::regex("_MODEL_"), model);
+
1836 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
1837
+
1838 Write(code);
+
1839
+
1840 // Generate footer
+
1841 GenerateFooter();
+
1842
+
1843 // Store the file
+
1844 WriteEnd();
+
1845 Store(file);
+
1846}
+
1847
+
1848void GeneratorKotlin::GenerateFBEFieldModelMap(const std::string& domain, const std::string& package, const std::string& key_name, const std::string& key_type, const std::string& key_model, const std::string& value_name, const std::string& value_type, const std::string& value_model)
+
1849{
+
1850 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "fbe";
+
1851
+
1852 // Create package path
+
1853 CppCommon::Directory::CreateTree(path);
+
1854
+
1855 // Generate the file
+
1856 CppCommon::Path file = path / ("FieldModelMap" + key_name + value_name + ".kt");
+
1857 WriteBegin();
+
1858
+
1859 // Generate headers
+
1860 GenerateHeader(CppCommon::Path(_input).filename().string());
+
1861 GenerateImports(domain, package + ".fbe");
+
1862
+
1863 std::string code = R"CODE(
+
1864// Fast Binary Encoding _KEY_NAME_->_VALUE_NAME_ map field model
+
1865class FieldModelMap_KEY_NAME__VALUE_NAME_(buffer: _DOMAIN_fbe.Buffer, offset: Long) : _DOMAIN_fbe.FieldModel(buffer, offset)
+
1866{
+
1867 private val _modelKey = _KEY_MODEL_(buffer, offset)
+
1868 private val _modelValue = _VALUE_MODEL_(buffer, offset)
+
1869
+
1870 // Field size
+
1871 override val fbeSize: Long = 4
+
1872
+
1873 // Field extra size
+
1874 override val fbeExtra: Long get()
+
1875 {
+
1876 if ((_buffer.offset + fbeOffset + fbeSize) > _buffer.size)
+
1877 return 0
+
1878
+
1879 val fbeMapOffset = readUInt32(fbeOffset).toLong()
+
1880 if ((fbeMapOffset == 0L) || ((_buffer.offset + fbeMapOffset + 4) > _buffer.size))
+
1881 return 0
+
1882
+
1883 val fbeMapSize = readUInt32(fbeMapOffset).toLong()
+
1884
+
1885 var fbeResult: Long = 4
+
1886 _modelKey.fbeOffset = fbeMapOffset + 4
+
1887 _modelValue.fbeOffset = fbeMapOffset + 4 + _modelKey.fbeSize
+
1888 var i = fbeMapSize
+
1889 while (i-- > 0)
+
1890 {
+
1891 fbeResult += _modelKey.fbeSize + _modelKey.fbeExtra
+
1892 _modelKey.fbeShift(_modelKey.fbeSize + _modelValue.fbeSize)
+
1893
+
1894 fbeResult += _modelValue.fbeSize + _modelValue.fbeExtra
+
1895 _modelValue.fbeShift(_modelKey.fbeSize + _modelValue.fbeSize)
+
1896 }
+
1897 return fbeResult
+
1898 }
+
1899
+
1900 // Get the map offset
+
1901 val offset: Long get()
+
1902 {
+
1903 if ((_buffer.offset + fbeOffset + fbeSize) > _buffer.size)
+
1904 return 0
+
1905
+
1906 return readUInt32(fbeOffset).toLong()
+
1907 }
+
1908
+
1909 // Get the map size
+
1910 val size: Long get()
+
1911 {
+
1912 if ((_buffer.offset + fbeOffset + fbeSize) > _buffer.size)
+
1913 return 0
+
1914
+
1915 val fbeMapOffset = readUInt32(fbeOffset).toLong()
+
1916 if ((fbeMapOffset == 0L) || ((_buffer.offset + fbeMapOffset + 4) > _buffer.size))
+
1917 return 0
+
1918
+
1919 return readUInt32(fbeMapOffset).toLong()
+
1920 }
+
1921
+
1922 // Map index operator
+
1923 fun getItem(index: Long): Pair<_KEY_MODEL_, _VALUE_MODEL_>
+
1924 {
+
1925 assert((_buffer.offset + fbeOffset + fbeSize) <= _buffer.size) { "Model is broken!" }
+
1926
+
1927 val fbeMapOffset = readUInt32(fbeOffset).toLong()
+
1928 assert((fbeMapOffset > 0) && ((_buffer.offset + fbeMapOffset + 4) <= _buffer.size)) { "Model is broken!" }
+
1929
+
1930 val fbeMapSize = readUInt32(fbeMapOffset).toLong()
+
1931 assert(index < fbeMapSize) { "Index is out of bounds!" }
+
1932
+
1933 _modelKey.fbeOffset = fbeMapOffset + 4
+
1934 _modelValue.fbeOffset = fbeMapOffset + 4 + _modelKey.fbeSize
+
1935 _modelKey.fbeShift(index * (_modelKey.fbeSize + _modelValue.fbeSize))
+
1936 _modelValue.fbeShift(index * (_modelKey.fbeSize + _modelValue.fbeSize))
+
1937 return Pair(_modelKey, _modelValue)
+
1938 }
+
1939
+
1940 // Resize the map and get its first model
+
1941 fun resize(size: Long): Pair<_KEY_MODEL_, _VALUE_MODEL_>
+
1942 {
+
1943 val fbeMapSize = size * (_modelKey.fbeSize + _modelValue.fbeSize)
+
1944 val fbeMapOffset = _buffer.allocate(4 + fbeMapSize) - _buffer.offset
+
1945 assert((fbeMapOffset > 0) && ((_buffer.offset + fbeMapOffset + 4) <= _buffer.size)) { "Model is broken!" }
+
1946
+
1947 write(fbeOffset, fbeMapOffset.toUInt())
+
1948 write(fbeMapOffset, size.toUInt())
+
1949 write(fbeMapOffset + 4, 0.toByte(), fbeMapSize)
+
1950
+
1951 _modelKey.fbeOffset = fbeMapOffset + 4
+
1952 _modelValue.fbeOffset = fbeMapOffset + 4 + _modelKey.fbeSize
+
1953 return Pair(_modelKey, _modelValue)
+
1954 }
+
1955
+
1956 // Check if the map is valid
+
1957 override fun verify(): Boolean
+
1958 {
+
1959 if ((_buffer.offset + fbeOffset + fbeSize) > _buffer.size)
+
1960 return true
+
1961
+
1962 val fbeMapOffset = readUInt32(fbeOffset).toLong()
+
1963 if (fbeMapOffset == 0L)
+
1964 return true
+
1965
+
1966 if ((_buffer.offset + fbeMapOffset + 4) > _buffer.size)
+
1967 return false
+
1968
+
1969 val fbeMapSize = readUInt32(fbeMapOffset).toLong()
+
1970
+
1971 _modelKey.fbeOffset = fbeMapOffset + 4
+
1972 _modelValue.fbeOffset = fbeMapOffset + 4 + _modelKey.fbeSize
+
1973 var i = fbeMapSize
+
1974 while (i-- > 0)
+
1975 {
+
1976 if (!_modelKey.verify())
+
1977 return false
+
1978 _modelKey.fbeShift(_modelKey.fbeSize + _modelValue.fbeSize)
+
1979 if (!_modelValue.verify())
+
1980 return false
+
1981 _modelValue.fbeShift(_modelKey.fbeSize + _modelValue.fbeSize)
+
1982 }
+
1983
+
1984 return true
+
1985 }
+
1986
+
1987 // Get the map as java.util.TreeMap
+
1988 fun get(values: java.util.TreeMap<_KEY_TYPE_, _VALUE_TYPE_>)
+
1989 {
+
1990 values.clear()
+
1991
+
1992 val fbeMapSize = size
+
1993 if (fbeMapSize == 0L)
+
1994 return
+
1995
+
1996 val fbeModel = getItem(0)
+
1997 var i = fbeMapSize
+
1998 while (i-- > 0)
+
1999 {
+
2000 val key = fbeModel.first.get()
+
2001 val value = fbeModel.second.get()
+
2002 values[key] = value
+
2003 fbeModel.first.fbeShift(fbeModel.first.fbeSize + fbeModel.second.fbeSize)
+
2004 fbeModel.second.fbeShift(fbeModel.first.fbeSize + fbeModel.second.fbeSize)
+
2005 }
+
2006 }
+
2007
+
2008 // Get the map as java.util.HashMap
+
2009 fun get(values: java.util.HashMap<_KEY_TYPE_, _VALUE_TYPE_>)
+
2010 {
+
2011 values.clear()
+
2012
+
2013 val fbeMapSize = size
+
2014 if (fbeMapSize == 0L)
+
2015 return
+
2016
+
2017 val fbeModel = getItem(0)
+
2018 var i = fbeMapSize
+
2019 while (i-- > 0)
+
2020 {
+
2021 val key = fbeModel.first.get()
+
2022 val value = fbeModel.second.get()
+
2023 values[key] = value
+
2024 fbeModel.first.fbeShift(fbeModel.first.fbeSize + fbeModel.second.fbeSize)
+
2025 fbeModel.second.fbeShift(fbeModel.first.fbeSize + fbeModel.second.fbeSize)
+
2026 }
+
2027 }
+
2028
+
2029 // Set the map as java.util.TreeMap
+
2030 fun set(values: java.util.TreeMap<_KEY_TYPE_, _VALUE_TYPE_>)
+
2031 {
+
2032 assert((_buffer.offset + fbeOffset + fbeSize) <= _buffer.size) { "Model is broken!" }
+
2033 if ((_buffer.offset + fbeOffset + fbeSize) > _buffer.size)
+
2034 return
+
2035
+
2036 val fbeModel = resize(values.size.toLong())
+
2037 for ((key, value1) in values)
+
2038 {
+
2039 fbeModel.first.set(key)
+
2040 fbeModel.first.fbeShift(fbeModel.first.fbeSize + fbeModel.second.fbeSize)
+
2041 fbeModel.second.set(value1)
+
2042 fbeModel.second.fbeShift(fbeModel.first.fbeSize + fbeModel.second.fbeSize)
+
2043 }
+
2044 }
+
2045
+
2046 // Set the map as java.util.HashMap
+
2047 fun set(values: java.util.HashMap<_KEY_TYPE_, _VALUE_TYPE_>)
+
2048 {
+
2049 assert((_buffer.offset + fbeOffset + fbeSize) <= _buffer.size) { "Model is broken!" }
+
2050 if ((_buffer.offset + fbeOffset + fbeSize) > _buffer.size)
+
2051 return
+
2052
+
2053 val fbeModel = resize(values.size.toLong())
+
2054 for ((key, value1) in values)
+
2055 {
+
2056 fbeModel.first.set(key)
+
2057 fbeModel.first.fbeShift(fbeModel.first.fbeSize + fbeModel.second.fbeSize)
+
2058 fbeModel.second.set(value1)
+
2059 fbeModel.second.fbeShift(fbeModel.first.fbeSize + fbeModel.second.fbeSize)
+
2060 }
+
2061 }
+
2062}
+
2063)CODE";
+
2064
+
2065 std::string key_type_name = IsPackageType(key_type) ? key_type : (domain + package + "." + key_type);
+
2066 std::string value_type_name = IsPackageType(value_type) ? value_type : (domain + package + "." + value_type);
+
2067
+
2068 // Prepare code template
+
2069 code = std::regex_replace(code, std::regex("_DOMAIN_"), domain);
+
2070 code = std::regex_replace(code, std::regex("_KEY_NAME_"), key_name);
+
2071 code = std::regex_replace(code, std::regex("_KEY_TYPE_"), key_type_name);
+
2072 code = std::regex_replace(code, std::regex("_KEY_MODEL_"), key_model);
+
2073 code = std::regex_replace(code, std::regex("_VALUE_NAME_"), value_name);
+
2074 code = std::regex_replace(code, std::regex("_VALUE_TYPE_"), value_type_name);
+
2075 code = std::regex_replace(code, std::regex("_VALUE_MODEL_"), value_model);
+
2076 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2077
+
2078 Write(code);
+
2079
+
2080 // Generate footer
+
2081 GenerateFooter();
+
2082
+
2083 // Store the file
+
2084 WriteEnd();
+
2085 Store(file);
+
2086}
+
2087
+
2088void GeneratorKotlin::GenerateFBEFieldModelEnumFlags(const std::string& domain, const std::string& package, const std::string& name, const std::string& type)
+
2089{
+
2090 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "fbe";
+
2091
+
2092 // Create package path
+
2093 CppCommon::Directory::CreateTree(path);
+
2094
+
2095 // Generate the file
+
2096 CppCommon::Path file = path / ("FieldModel" + name + ".kt");
+
2097 WriteBegin();
+
2098
+
2099 // Generate headers
+
2100 GenerateHeader(CppCommon::Path(_input).filename().string());
+
2101 GenerateImports(domain, package + ".fbe");
+
2102
+
2103 std::string code = R"CODE(
+
2104// Fast Binary Encoding _NAME_ field model
+
2105class FieldModel_NAME_(buffer: _DOMAIN_fbe.Buffer, offset: Long) : _DOMAIN_fbe.FieldModel(buffer, offset)
+
2106{
+
2107 // Field size
+
2108 override val fbeSize: Long = _SIZE_
+
2109
+
2110 // Get the value
+
2111 fun get(defaults: _DOMAIN__PACKAGE_._NAME_ = _DOMAIN__PACKAGE_._NAME_()): _DOMAIN__PACKAGE_._NAME_
+
2112 {
+
2113 if ((_buffer.offset + fbeOffset + fbeSize) > _buffer.size)
+
2114 return defaults
+
2115
+
2116 return _DOMAIN__PACKAGE_._NAME_(_READ_(fbeOffset))
+
2117 }
+
2118
+
2119 // Set the value
+
2120 fun set(value: _DOMAIN__PACKAGE_._NAME_)
+
2121 {
+
2122 assert((_buffer.offset + fbeOffset + fbeSize) <= _buffer.size) { "Model is broken!" }
+
2123 if ((_buffer.offset + fbeOffset + fbeSize) > _buffer.size)
+
2124 return
+
2125
+
2126 write(fbeOffset, value.raw)
+
2127 }
+
2128}
+
2129)CODE";
+
2130
+
2131 // Prepare code template
+
2132 code = std::regex_replace(code, std::regex("_DOMAIN_"), domain);
+
2133 code = std::regex_replace(code, std::regex("_PACKAGE_"), package);
+
2134 code = std::regex_replace(code, std::regex("_NAME_"), name);
+
2135 code = std::regex_replace(code, std::regex("_SIZE_"), ConvertEnumSize(type));
+
2136 code = std::regex_replace(code, std::regex("_READ_"), ConvertEnumRead(type));
+
2137 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2138
+
2139 Write(code);
+
2140
+
2141 // Generate footer
+
2142 GenerateFooter();
+
2143
+
2144 // Store the file
+
2145 WriteEnd();
+
2146 Store(file);
+
2147}
+
2148
+
2149void GeneratorKotlin::GenerateFBESize(const std::string& domain, const std::string& package)
+
2150{
+
2151 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
2152
+
2153 // Generate the file
+
2154 CppCommon::Path file = path / "Size.kt";
+
2155 WriteBegin();
+
2156
+
2157 // Generate headers
+
2158 GenerateHeader("FBE");
+
2159 GenerateImports(domain, package);
+
2160
+
2161 std::string code = R"CODE(
+
2162// Fast Binary Encoding size
+
2163class Size
+
2164{
+
2165 var value: Long = 0
+
2166
+
2167 // Initialize a new size
+
2168 constructor()
+
2169 constructor(size: Long) { value = size }
+
2170}
+
2171)CODE";
+
2172
+
2173 // Prepare code template
+
2174 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2175
+
2176 Write(code);
+
2177
+
2178 // Generate footer
+
2179 GenerateFooter();
+
2180
+
2181 // Store the file
+
2182 WriteEnd();
+
2183 Store(file);
+
2184}
+
2185
+
2186void GeneratorKotlin::GenerateFBEFinalModel(const std::string& domain, const std::string& package)
+
2187{
+
2188 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
2189
+
2190 // Generate the file
+
2191 CppCommon::Path file = path / "FinalModel.kt";
+
2192 WriteBegin();
+
2193
+
2194 // Generate headers
+
2195 GenerateHeader("FBE");
+
2196 GenerateImports(domain, package);
+
2197
+
2198 std::string code = R"CODE(
+
2199// Fast Binary Encoding base final model
+
2200@Suppress("MemberVisibilityCanBePrivate")
+
2201abstract class FinalModel protected constructor(protected var _buffer: Buffer, protected var _offset: Long)
+
2202{
+
2203 // Final offset
+
2204 var fbeOffset: Long
+
2205 get() = _offset
+
2206 set(value) { _offset = value }
+
2207 // Final size
+
2208 open val fbeSize: Long = 0
+
2209 // Final extra size
+
2210 open val fbeExtra: Long = 0
+
2211
+
2212 // Shift the current final offset
+
2213 fun fbeShift(size: Long) { _offset += size }
+
2214 // Unshift the current final offset
+
2215 fun fbeUnshift(size: Long) { _offset -= size }
+
2216
+
2217 // Check if the value is valid
+
2218 abstract fun verify(): Long
+
2219
+
2220 // Buffer I/O methods
+
2221 protected fun readBoolean(offset: Long): Boolean { return Buffer.readBoolean(_buffer.data, _buffer.offset + offset) }
+
2222 protected fun readByte(offset: Long): Byte { return Buffer.readByte(_buffer.data, _buffer.offset + offset) }
+
2223 protected fun readChar(offset: Long): Char { return Buffer.readChar(_buffer.data, _buffer.offset + offset) }
+
2224 protected fun readWChar(offset: Long): Char { return Buffer.readWChar(_buffer.data, _buffer.offset + offset) }
+
2225 protected fun readInt8(offset: Long): Byte { return Buffer.readInt8(_buffer.data, _buffer.offset + offset) }
+
2226 protected fun readUInt8(offset: Long): UByte { return Buffer.readUInt8(_buffer.data, _buffer.offset + offset) }
+
2227 protected fun readInt16(offset: Long): Short { return Buffer.readInt16(_buffer.data, _buffer.offset + offset) }
+
2228 protected fun readUInt16(offset: Long): UShort { return Buffer.readUInt16(_buffer.data, _buffer.offset + offset) }
+
2229 protected fun readInt32(offset: Long): Int { return Buffer.readInt32(_buffer.data, _buffer.offset + offset) }
+
2230 protected fun readUInt32(offset: Long): UInt { return Buffer.readUInt32(_buffer.data, _buffer.offset + offset) }
+
2231 protected fun readInt64(offset: Long): Long { return Buffer.readInt64(_buffer.data, _buffer.offset + offset) }
+
2232 protected fun readUInt64(offset: Long): ULong { return Buffer.readUInt64(_buffer.data, _buffer.offset + offset) }
+
2233 protected fun readFloat(offset: Long): Float { return Buffer.readFloat(_buffer.data, _buffer.offset + offset) }
+
2234 protected fun readDouble(offset: Long): Double { return Buffer.readDouble(_buffer.data, _buffer.offset + offset) }
+
2235 protected fun readBytes(offset: Long, size: Long): ByteArray { return Buffer.readBytes(_buffer.data, _buffer.offset + offset, size) }
+
2236 protected fun readString(offset: Long, size: Long): String { return Buffer.readString(_buffer.data, _buffer.offset + offset, size) }
+
2237 protected fun readUUID(offset: Long): java.util.UUID { return Buffer.readUUID(_buffer.data, _buffer.offset + offset) }
+
2238 protected fun write(offset: Long, value: Boolean) { Buffer.write(_buffer.data, _buffer.offset + offset, value) }
+
2239 protected fun write(offset: Long, value: Byte) { Buffer.write(_buffer.data, _buffer.offset + offset, value) }
+
2240 protected fun write(offset: Long, value: UByte) { Buffer.write(_buffer.data, _buffer.offset + offset, value) }
+
2241 protected fun write(offset: Long, value: Short) { Buffer.write(_buffer.data, _buffer.offset + offset, value) }
+
2242 protected fun write(offset: Long, value: UShort) { Buffer.write(_buffer.data, _buffer.offset + offset, value) }
+
2243 protected fun write(offset: Long, value: Int) { Buffer.write(_buffer.data, _buffer.offset + offset, value) }
+
2244 protected fun write(offset: Long, value: UInt) { Buffer.write(_buffer.data, _buffer.offset + offset, value) }
+
2245 protected fun write(offset: Long, value: Long) { Buffer.write(_buffer.data, _buffer.offset + offset, value) }
+
2246 protected fun write(offset: Long, value: ULong) { Buffer.write(_buffer.data, _buffer.offset + offset, value) }
+
2247 protected fun write(offset: Long, value: Float) { Buffer.write(_buffer.data, _buffer.offset + offset, value) }
+
2248 protected fun write(offset: Long, value: Double) { Buffer.write(_buffer.data, _buffer.offset + offset, value) }
+
2249 protected fun write(offset: Long, value: ByteArray) { Buffer.write(_buffer.data, _buffer.offset + offset, value) }
+
2250 protected fun write(offset: Long, value: ByteArray, valueOffset: Long, valueSize: Long) { Buffer.write(_buffer.data, _buffer.offset + offset, value, valueOffset, valueSize) }
+
2251 protected fun write(offset: Long, value: Byte, valueCount: Long) { Buffer.write(_buffer.data, _buffer.offset + offset, value, valueCount) }
+
2252 protected fun write(offset: Long, value: java.util.UUID) { Buffer.write(_buffer.data, _buffer.offset + offset, value) }
+
2253}
+
2254)CODE";
+
2255
+
2256 // Prepare code template
+
2257 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2258
+
2259 Write(code);
+
2260
+
2261 // Generate footer
+
2262 GenerateFooter();
+
2263
+
2264 // Store the file
+
2265 WriteEnd();
+
2266 Store(file);
+
2267}
+
2268
+
2269void GeneratorKotlin::GenerateFBEFinalModel(const std::string& domain, const std::string& package, const std::string& name, const std::string& type, const std::string& base, const std::string& size, const std::string& defaults)
+
2270{
+
2271 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
2272
+
2273 // Generate the file
+
2274 CppCommon::Path file = path / ("FinalModel" + name + ".kt");
+
2275 WriteBegin();
+
2276
+
2277 // Generate headers
+
2278 GenerateHeader("FBE");
+
2279 GenerateImports(domain, package);
+
2280
+
2281 std::string code = R"CODE(
+
2282// Fast Binary Encoding _TYPE_ final model
+
2283class FinalModel_NAME_(buffer: Buffer, offset: Long) : FinalModel(buffer, offset)
+
2284{
+
2285 // Get the allocation size
+
2286 @Suppress("UNUSED_PARAMETER")
+
2287 fun fbeAllocationSize(value: _TYPE_): Long = fbeSize
+
2288
+
2289 // Final size
+
2290 override val fbeSize: Long = _SIZE_
+
2291
+
2292 // Check if the value is valid
+
2293 override fun verify(): Long
+
2294 {
+
2295 if ((_buffer.offset + fbeOffset + fbeSize) > _buffer.size)
+
2296 return Long.MAX_VALUE
+
2297
+
2298 return fbeSize
+
2299 }
+
2300
+
2301 // Get the value
+
2302 fun get(size: Size): _TYPE_
+
2303 {
+
2304 if ((_buffer.offset + fbeOffset + fbeSize) > _buffer.size)
+
2305 return _DEFAULTS_
+
2306
+
2307 size.value = fbeSize
+
2308 return read_NAME_(fbeOffset)
+
2309 }
+
2310
+
2311 // Set the value
+
2312 fun set(value: _TYPE_): Long
+
2313 {
+
2314 assert((_buffer.offset + fbeOffset + fbeSize) <= _buffer.size) { "Model is broken!" }
+
2315 if ((_buffer.offset + fbeOffset + fbeSize) > _buffer.size)
+
2316 return 0
+
2317
+
2318 write(fbeOffset, value_BASE_)
+
2319 return fbeSize
+
2320 }
+
2321}
+
2322)CODE";
+
2323
+
2324 // Prepare code template
+
2325 code = std::regex_replace(code, std::regex("_NAME_"), name);
+
2326 code = std::regex_replace(code, std::regex("_TYPE_"), type);
+
2327 code = std::regex_replace(code, std::regex("_BASE_"), base);
+
2328 code = std::regex_replace(code, std::regex("_SIZE_"), size);
+
2329 code = std::regex_replace(code, std::regex("_DEFAULTS_"), defaults);
+
2330 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2331
+
2332 Write(code);
+
2333
+
2334 // Generate footer
+
2335 GenerateFooter();
+
2336
+
2337 // Store the file
+
2338 WriteEnd();
+
2339 Store(file);
+
2340}
+
2341
+
2342void GeneratorKotlin::GenerateFBEFinalModelDecimal(const std::string& domain, const std::string& package)
+
2343{
+
2344 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
2345
+
2346 // Generate the file
+
2347 CppCommon::Path file = path / "FinalModelDecimal.kt";
+
2348 WriteBegin();
+
2349
+
2350 // Generate headers
+
2351 GenerateHeader("FBE");
+
2352 GenerateImports(domain, package);
+
2353
+
2354 std::string code = R"CODE(
+
2355// Fast Binary Encoding decimal final model
+
2356class FinalModelDecimal(buffer: Buffer, offset: Long) : FinalModel(buffer, offset)
+
2357{
+
2358 // Get the allocation size
+
2359 @Suppress("UNUSED_PARAMETER")
+
2360 fun fbeAllocationSize(value: java.math.BigDecimal): Long = fbeSize
+
2361
+
2362 // Final size
+
2363 override val fbeSize: Long = 16
+
2364
+
2365 // Check if the decimal value is valid
+
2366 override fun verify(): Long
+
2367 {
+
2368 if ((_buffer.offset + fbeOffset + fbeSize) > _buffer.size)
+
2369 return Long.MAX_VALUE
+
2370
+
2371 return fbeSize
+
2372 }
+
2373
+
2374 // Get the decimal value
+
2375 fun get(size: Size): java.math.BigDecimal
+
2376 {
+
2377 if ((_buffer.offset + fbeOffset + fbeSize) > _buffer.size)
+
2378 return java.math.BigDecimal.valueOf(0L)
+
2379
+
2380 val magnitude = readBytes(fbeOffset, 12)
+
2381 val scale = readByte(fbeOffset + 14).toInt()
+
2382 val signum = if (readByte(fbeOffset + 15) < 0) -1 else 1
+
2383
+
2384 // Reverse magnitude
+
2385 for (i in 0 until (magnitude.size / 2))
+
2386 {
+
2387 val temp = magnitude[i]
+
2388 magnitude[i] = magnitude[magnitude.size - i - 1]
+
2389 magnitude[magnitude.size - i - 1] = temp
+
2390 }
+
2391
+
2392 val unscaled = java.math.BigInteger(signum, magnitude)
+
2393
+
2394 size.value = fbeSize
+
2395 return java.math.BigDecimal(unscaled, scale)
+
2396 }
+
2397
+
2398 // Set the decimal value
+
2399 fun set(value: java.math.BigDecimal): Long
+
2400 {
+
2401 assert((_buffer.offset + fbeOffset + fbeSize) <= _buffer.size) { "Model is broken!" }
+
2402 if ((_buffer.offset + fbeOffset + fbeSize) > _buffer.size)
+
2403 return 0
+
2404
+
2405 // Get unscaled absolute value
+
2406 val unscaled = value.abs().unscaledValue()
+
2407 val bitLength = unscaled.bitLength()
+
2408 if ((bitLength < 0) || (bitLength > 96))
+
2409 {
+
2410 // Value too big for .NET Decimal (bit length is limited to [0, 96])
+
2411 write(fbeOffset, 0.toByte(), fbeSize)
+
2412 return fbeSize
+
2413 }
+
2414
+
2415 // Get byte array
+
2416 val unscaledBytes = unscaled.toByteArray()
+
2417
+
2418 // Get scale
+
2419 val scale = value.scale()
+
2420 if ((scale < 0) || (scale > 28))
+
2421 {
+
2422 // Value scale exceeds .NET Decimal limit of [0, 28]
+
2423 write(fbeOffset, 0.toByte(), fbeSize)
+
2424 return fbeSize
+
2425 }
+
2426
+
2427 // Write unscaled value to bytes 0-11
+
2428 var index = 0
+
2429 var i = unscaledBytes.size - 1
+
2430 while ((i >= 0) && (index < 12))
+
2431 {
+
2432 write(fbeOffset + index, unscaledBytes[i])
+
2433 i--
+
2434 index++
+
2435 }
+
2436
+
2437 // Fill remaining bytes with zeros
+
2438 while (index < 14)
+
2439 {
+
2440 write(fbeOffset + index, 0.toByte())
+
2441 index++
+
2442 }
+
2443
+
2444 // Write scale at byte 14
+
2445 write(fbeOffset + 14, scale.toByte())
+
2446
+
2447 // Write signum at byte 15
+
2448 write(fbeOffset + 15, (if (value.signum() < 0) -128 else 0).toByte())
+
2449 return fbeSize
+
2450 }
+
2451}
+
2452)CODE";
+
2453
+
2454 // Prepare code template
+
2455 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2456
+
2457 Write(code);
+
2458
+
2459 // Generate footer
+
2460 GenerateFooter();
+
2461
+
2462 // Store the file
+
2463 WriteEnd();
+
2464 Store(file);
+
2465}
+
2466
+
2467void GeneratorKotlin::GenerateFBEFinalModelDate(const std::string& domain, const std::string& package)
+
2468{
+
2469 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
2470
+
2471 // Generate the file
+
2472 CppCommon::Path file = path / "FinalModelDate.kt";
+
2473 WriteBegin();
+
2474
+
2475 // Generate headers
+
2476 GenerateHeader("FBE");
+
2477 GenerateImports(domain, package);
+
2478
+
2479 std::string code = R"CODE(
+
2480// Fast Binary Encoding date final model
+
2481class FinalModelDate(buffer: Buffer, offset: Long) : FinalModel(buffer, offset)
+
2482{
+
2483 // Get the allocation size
+
2484 @Suppress("UNUSED_PARAMETER")
+
2485 fun fbeAllocationSize(value: java.util.Date): Long = fbeSize
+
2486
+
2487 // Final size
+
2488 override val fbeSize: Long = 8
+
2489
+
2490 // Check if the date value is valid
+
2491 override fun verify(): Long
+
2492 {
+
2493 if ((_buffer.offset + fbeOffset + fbeSize) > _buffer.size)
+
2494 return Long.MAX_VALUE
+
2495
+
2496 return fbeSize
+
2497 }
+
2498
+
2499 // Get the date value
+
2500 fun get(size: Size): java.util.Date
+
2501 {
+
2502 if ((_buffer.offset + fbeOffset + fbeSize) > _buffer.size)
+
2503 return java.util.Date(0)
+
2504
+
2505 size.value = fbeSize
+
2506 val nanoseconds = readInt64(fbeOffset)
+
2507 return java.util.Date(nanoseconds / 1000000)
+
2508 }
+
2509
+
2510 // Set the date value
+
2511 fun set(value: java.util.Date): Long
+
2512 {
+
2513 assert((_buffer.offset + fbeOffset + fbeSize) <= _buffer.size) { "Model is broken!" }
+
2514 if ((_buffer.offset + fbeOffset + fbeSize) > _buffer.size)
+
2515 return 0
+
2516
+
2517 val nanoseconds = value.time * 1000000
+
2518 write(fbeOffset, nanoseconds.toULong())
+
2519 return fbeSize
+
2520 }
+
2521}
+
2522)CODE";
+
2523
+
2524 // Prepare code template
+
2525 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2526
+
2527 Write(code);
+
2528
+
2529 // Generate footer
+
2530 GenerateFooter();
+
2531
+
2532 // Store the file
+
2533 WriteEnd();
+
2534 Store(file);
+
2535}
+
2536
+
2537void GeneratorKotlin::GenerateFBEFinalModelTimestamp(const std::string& domain, const std::string& package)
+
2538{
+
2539 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
2540
+
2541 // Generate the file
+
2542 CppCommon::Path file = path / "FinalModelTimestamp.kt";
+
2543 WriteBegin();
+
2544
+
2545 // Generate headers
+
2546 GenerateHeader("FBE");
+
2547 GenerateImports(domain, package);
+
2548
+
2549 std::string code = R"CODE(
+
2550// Fast Binary Encoding timestamp final model
+
2551class FinalModelTimestamp(buffer: Buffer, offset: Long) : FinalModel(buffer, offset)
+
2552{
+
2553 // Get the allocation size
+
2554 @Suppress("UNUSED_PARAMETER")
+
2555 fun fbeAllocationSize(value: java.time.Instant): Long = fbeSize
+
2556
+
2557 // Final size
+
2558 override val fbeSize: Long = 8
+
2559
+
2560 // Check if the timestamp value is valid
+
2561 override fun verify(): Long
+
2562 {
+
2563 if ((_buffer.offset + fbeOffset + fbeSize) > _buffer.size)
+
2564 return Long.MAX_VALUE
+
2565
+
2566 return fbeSize
+
2567 }
+
2568
+
2569 // Get the timestamp value
+
2570 fun get(size: Size): java.time.Instant
+
2571 {
+
2572 if ((_buffer.offset + fbeOffset + fbeSize) > _buffer.size)
+
2573 return java.time.Instant.EPOCH
+
2574
+
2575 size.value = fbeSize
+
2576 val nanoseconds = readInt64(fbeOffset)
+
2577 return java.time.Instant.ofEpochSecond(nanoseconds / 1000000000, nanoseconds % 1000000000)
+
2578 }
+
2579
+
2580 // Set the timestamp value
+
2581 fun set(value: java.time.Instant): Long
+
2582 {
+
2583 assert((_buffer.offset + fbeOffset + fbeSize) <= _buffer.size) { "Model is broken!" }
+
2584 if ((_buffer.offset + fbeOffset + fbeSize) > _buffer.size)
+
2585 return 0
+
2586
+
2587 val nanoseconds = value.epochSecond * 1000000000 + value.nano
+
2588 write(fbeOffset, nanoseconds.toULong())
+
2589 return fbeSize
+
2590 }
+
2591}
+
2592)CODE";
+
2593
+
2594 // Prepare code template
+
2595 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2596
+
2597 Write(code);
+
2598
+
2599 // Generate footer
+
2600 GenerateFooter();
+
2601
+
2602 // Store the file
+
2603 WriteEnd();
+
2604 Store(file);
+
2605}
+
2606
+
2607void GeneratorKotlin::GenerateFBEFinalModelBytes(const std::string& domain, const std::string& package)
+
2608{
+
2609 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
2610
+
2611 // Generate the file
+
2612 CppCommon::Path file = path / "FinalModelBytes.kt";
+
2613 WriteBegin();
+
2614
+
2615 // Generate headers
+
2616 GenerateHeader("FBE");
+
2617 GenerateImports(domain, package);
+
2618
+
2619 std::string code = R"CODE(
+
2620// Fast Binary Encoding bytes final model
+
2621class FinalModelBytes(buffer: Buffer, offset: Long) : FinalModel(buffer, offset)
+
2622{
+
2623 // Get the allocation size
+
2624 fun fbeAllocationSize(value: ByteArray): Long = 4 + value.size.toLong()
+
2625
+
2626 // Check if the bytes value is valid
+
2627 override fun verify(): Long
+
2628 {
+
2629 if ((_buffer.offset + fbeOffset) + 4 > _buffer.size)
+
2630 return Long.MAX_VALUE
+
2631
+
2632 val fbeBytesSize = readUInt32(fbeOffset).toLong()
+
2633 if ((_buffer.offset + fbeOffset + 4 + fbeBytesSize) > _buffer.size)
+
2634 return Long.MAX_VALUE
+
2635
+
2636 return 4 + fbeBytesSize
+
2637 }
+
2638
+
2639 // Get the bytes value
+
2640 fun get(size: Size): ByteArray
+
2641 {
+
2642 if ((_buffer.offset + fbeOffset) + 4 > _buffer.size)
+
2643 {
+
2644 size.value = 0
+
2645 return ByteArray(0)
+
2646 }
+
2647
+
2648 val fbeBytesSize = readUInt32(fbeOffset).toLong()
+
2649 assert((_buffer.offset + fbeOffset + 4 + fbeBytesSize) <= _buffer.size) { "Model is broken!" }
+
2650 if ((_buffer.offset + fbeOffset + 4 + fbeBytesSize) > _buffer.size)
+
2651 {
+
2652 size.value = 4
+
2653 return ByteArray(0)
+
2654 }
+
2655
+
2656 size.value = 4 + fbeBytesSize
+
2657 return readBytes(fbeOffset + 4, fbeBytesSize)
+
2658 }
+
2659
+
2660 // Set the bytes value
+
2661 fun set(value: ByteArray): Long
+
2662 {
+
2663 assert((_buffer.offset + fbeOffset + 4) <= _buffer.size) { "Model is broken!" }
+
2664 if ((_buffer.offset + fbeOffset + 4) > _buffer.size)
+
2665 return 0
+
2666
+
2667 val fbeBytesSize = value.size.toLong()
+
2668 assert((_buffer.offset + fbeOffset + 4 + fbeBytesSize) <= _buffer.size) { "Model is broken!" }
+
2669 if ((_buffer.offset + fbeOffset + 4 + fbeBytesSize) > _buffer.size)
+
2670 return 4
+
2671
+
2672 write(fbeOffset, fbeBytesSize.toUInt())
+
2673 write(fbeOffset + 4, value)
+
2674 return 4 + fbeBytesSize
+
2675 }
+
2676}
+
2677)CODE";
+
2678
+
2679 // Prepare code template
+
2680 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2681
+
2682 Write(code);
+
2683
+
2684 // Generate footer
+
2685 GenerateFooter();
+
2686
+
2687 // Store the file
+
2688 WriteEnd();
+
2689 Store(file);
+
2690}
+
2691
+
2692void GeneratorKotlin::GenerateFBEFinalModelString(const std::string& domain, const std::string& package)
+
2693{
+
2694 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
2695
+
2696 // Generate the file
+
2697 CppCommon::Path file = path / "FinalModelString.kt";
+
2698 WriteBegin();
+
2699
+
2700 // Generate headers
+
2701 GenerateHeader("FBE");
+
2702 GenerateImports(domain, package);
+
2703
+
2704 std::string code = R"CODE(
+
2705// Fast Binary Encoding string final model
+
2706class FinalModelString(buffer: Buffer, offset: Long) : FinalModel(buffer, offset)
+
2707{
+
2708 // Get the allocation size
+
2709 fun fbeAllocationSize(value: String): Long = 4 + 3 * (value.length.toLong() + 1)
+
2710
+
2711 // Check if the string value is valid
+
2712 override fun verify(): Long
+
2713 {
+
2714 if ((_buffer.offset + fbeOffset + 4) > _buffer.size)
+
2715 return Long.MAX_VALUE
+
2716
+
2717 val fbeStringSize = readUInt32(fbeOffset).toLong()
+
2718 if ((_buffer.offset + fbeOffset + 4 + fbeStringSize) > _buffer.size)
+
2719 return Long.MAX_VALUE
+
2720
+
2721 return 4 + fbeStringSize
+
2722 }
+
2723
+
2724 // Get the string value
+
2725 fun get(size: Size): String
+
2726 {
+
2727 if ((_buffer.offset + fbeOffset + 4) > _buffer.size)
+
2728 {
+
2729 size.value = 0
+
2730 return ""
+
2731 }
+
2732
+
2733 val fbeStringSize = readUInt32(fbeOffset).toLong()
+
2734 assert((_buffer.offset + fbeOffset + 4 + fbeStringSize) <= _buffer.size) { "Model is broken!" }
+
2735 if ((_buffer.offset + fbeOffset + 4 + fbeStringSize) > _buffer.size)
+
2736 {
+
2737 size.value = 4
+
2738 return ""
+
2739 }
+
2740
+
2741 size.value = 4 + fbeStringSize
+
2742 return readString(fbeOffset + 4, fbeStringSize)
+
2743 }
+
2744
+
2745 // Set the string value
+
2746 fun set(value: String): Long
+
2747 {
+
2748 assert((_buffer.offset + fbeOffset + 4) <= _buffer.size) { "Model is broken!" }
+
2749 if ((_buffer.offset + fbeOffset + 4) > _buffer.size)
+
2750 return 0
+
2751
+
2752 val bytes = value.toByteArray(java.nio.charset.StandardCharsets.UTF_8)
+
2753
+
2754 val fbeStringSize = bytes.size.toLong()
+
2755 assert((_buffer.offset + fbeOffset + 4 + fbeStringSize) <= _buffer.size) { "Model is broken!" }
+
2756 if ((_buffer.offset + fbeOffset + 4 + fbeStringSize) > _buffer.size)
+
2757 return 4
+
2758
+
2759 write(fbeOffset, fbeStringSize.toUInt())
+
2760 write(fbeOffset + 4, bytes)
+
2761 return 4 + fbeStringSize
+
2762 }
+
2763}
+
2764)CODE";
+
2765
+
2766 // Prepare code template
+
2767 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2768
+
2769 Write(code);
+
2770
+
2771 // Generate footer
+
2772 GenerateFooter();
+
2773
+
2774 // Store the file
+
2775 WriteEnd();
+
2776 Store(file);
+
2777}
+
2778
+
2779void GeneratorKotlin::GenerateFBEFinalModelOptional(const std::string& domain, const std::string& package, const std::string& name, const std::string& type, const std::string& model)
+
2780{
+
2781 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "fbe";
+
2782
+
2783 // Create package path
+
2784 CppCommon::Directory::CreateTree(path);
+
2785
+
2786 // Generate the file
+
2787 CppCommon::Path file = path / ("FinalModelOptional" + name + ".kt");
+
2788 WriteBegin();
+
2789
+
2790 // Generate headers
+
2791 GenerateHeader(CppCommon::Path(_input).filename().string());
+
2792 GenerateImports(domain, package + ".fbe");
+
2793
+
2794 std::string code = R"CODE(
+
2795// Fast Binary Encoding optional _NAME_ final model
+
2796class FinalModelOptional_NAME_(buffer: _DOMAIN_fbe.Buffer, offset: Long) : _DOMAIN_fbe.FinalModel(buffer, offset)
+
2797{
+
2798 // Get the allocation size
+
2799 fun fbeAllocationSize(optional: _TYPE_): Long = 1 + (if (optional != null) value.fbeAllocationSize(optional) else 0)
+
2800
+
2801 // Checks if the object contains a value
+
2802 fun hasValue(): Boolean
+
2803 {
+
2804 if ((_buffer.offset + fbeOffset + 1) > _buffer.size)
+
2805 return false
+
2806
+
2807 val fbeHasValue = readInt8(fbeOffset).toInt()
+
2808 return fbeHasValue != 0
+
2809 }
+
2810
+
2811 // Base final model value
+
2812 val value = _MODEL_(buffer, 0)
+
2813
+
2814 // Check if the optional value is valid
+
2815 override fun verify(): Long
+
2816 {
+
2817 if ((_buffer.offset + fbeOffset + 1) > _buffer.size)
+
2818 return Long.MAX_VALUE
+
2819
+
2820 val fbeHasValue = readInt8(fbeOffset).toInt()
+
2821 if (fbeHasValue == 0)
+
2822 return 1
+
2823
+
2824 _buffer.shift(fbeOffset + 1)
+
2825 val fbeResult = value.verify()
+
2826 _buffer.unshift(fbeOffset + 1)
+
2827 return 1 + fbeResult
+
2828 }
+
2829
+
2830 // Get the optional value
+
2831 fun get(size: _DOMAIN_fbe.Size): _TYPE_
+
2832 {
+
2833 assert((_buffer.offset + fbeOffset + 1) <= _buffer.size) { "Model is broken!" }
+
2834 if ((_buffer.offset + fbeOffset + 1) > _buffer.size)
+
2835 {
+
2836 size.value = 0
+
2837 return null
+
2838 }
+
2839
+
2840 if (!hasValue())
+
2841 {
+
2842 size.value = 1
+
2843 return null
+
2844 }
+
2845
+
2846 _buffer.shift(fbeOffset + 1)
+
2847 val optional = value.get(size)
+
2848 _buffer.unshift(fbeOffset + 1)
+
2849 size.value += 1
+
2850 return optional
+
2851 }
+
2852
+
2853 // Set the optional value
+
2854 fun set(optional: _TYPE_): Long
+
2855 {
+
2856 assert((_buffer.offset + fbeOffset + 1) <= _buffer.size) { "Model is broken!" }
+
2857 if ((_buffer.offset + fbeOffset + 1) > _buffer.size)
+
2858 return 0
+
2859
+
2860 val fbeHasValue = if (optional != null) 1 else 0
+
2861 write(fbeOffset, fbeHasValue.toByte())
+
2862 if (fbeHasValue == 0)
+
2863 return 1
+
2864
+
2865 _buffer.shift(fbeOffset + 1)
+
2866 val size = value.set(optional!!)
+
2867 _buffer.unshift(fbeOffset + 1)
+
2868 return 1 + size
+
2869 }
+
2870}
+
2871)CODE";
+
2872
+
2873 std::string type_name = IsPackageType(type) ? type : (domain + package + "." + type);
+
2874
+
2875 // Prepare code template
+
2876 code = std::regex_replace(code, std::regex("_DOMAIN_"), domain);
+
2877 code = std::regex_replace(code, std::regex("_NAME_"), name);
+
2878 code = std::regex_replace(code, std::regex("_TYPE_"), type_name);
+
2879 code = std::regex_replace(code, std::regex("_MODEL_"), model);
+
2880 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2881
+
2882 Write(code);
+
2883
+
2884 // Generate footer
+
2885 GenerateFooter();
+
2886
+
2887 // Store the file
+
2888 WriteEnd();
+
2889 Store(file);
+
2890}
+
2891
+
2892void GeneratorKotlin::GenerateFBEFinalModelArray(const std::string& domain, const std::string& package, const std::string& name, const std::string& type, const std::string& base, bool optional, const std::string& model)
+
2893{
+
2894 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "fbe";
+
2895
+
2896 // Create package path
+
2897 CppCommon::Directory::CreateTree(path);
+
2898
+
2899 // Generate the file
+
2900 CppCommon::Path file = path / ("FinalModelArray" + name + ".kt");
+
2901 WriteBegin();
+
2902
+
2903 // Generate headers
+
2904 GenerateHeader(CppCommon::Path(_input).filename().string());
+
2905 GenerateImports(domain, package + ".fbe");
+
2906
+
2907 std::string code = R"CODE(
+
2908// Fast Binary Encoding _NAME_ array final model
+
2909class FinalModelArray_NAME_(buffer: _DOMAIN_fbe.Buffer, offset: Long, private val _size: Long) : _DOMAIN_fbe.FinalModel(buffer, offset)
+
2910{
+
2911 private val _model = _MODEL_(buffer, offset)
+
2912
+
2913 // Get the allocation size
+
2914 fun fbeAllocationSize(values: _ARRAY_): Long
+
2915 {
+
2916 var size: Long = 0
+
2917 var i: Long = 0
+
2918 while ((i < values.size) && (i < _size))
+
2919 {
+
2920 size += _model.fbeAllocationSize(values[i.toInt()])
+
2921 i++
+
2922 }
+
2923 return size
+
2924 }
+
2925 fun fbeAllocationSize(values: java.util.ArrayList<_TYPE_>): Long
+
2926 {
+
2927 var size: Long = 0
+
2928 var i: Long = 0
+
2929 while ((i < values.size) && (i < _size))
+
2930 {
+
2931 size += _model.fbeAllocationSize(values[i.toInt()])
+
2932 i++
+
2933 }
+
2934 return size
+
2935 }
+
2936
+
2937 // Check if the array is valid
+
2938 override fun verify(): Long
+
2939 {
+
2940 if ((_buffer.offset + fbeOffset) > _buffer.size)
+
2941 return Long.MAX_VALUE
+
2942
+
2943 var size: Long = 0
+
2944 _model.fbeOffset = fbeOffset
+
2945 var i = _size
+
2946 while (i-- > 0)
+
2947 {
+
2948 val offset = _model.verify()
+
2949 if (offset == Long.MAX_VALUE)
+
2950 return Long.MAX_VALUE
+
2951 _model.fbeShift(offset)
+
2952 size += offset
+
2953 }
+
2954 return size
+
2955 }
+
2956
+
2957 // Get the array
+
2958 fun get(size: _DOMAIN_fbe.Size): _ARRAY_
+
2959 {
+
2960 val values = _INIT_
+
2961
+
2962 assert((_buffer.offset + fbeOffset) <= _buffer.size) { "Model is broken!" }
+
2963 if ((_buffer.offset + fbeOffset) > _buffer.size)
+
2964 {
+
2965 size.value = 0
+
2966 return values
+
2967 }
+
2968
+
2969 size.value = 0
+
2970 val offset = _DOMAIN_fbe.Size()
+
2971 _model.fbeOffset = fbeOffset
+
2972 for (i in 0 until _size)
+
2973 {
+
2974 offset.value = 0
+
2975 values[i.toInt()] = _model.get(offset)
+
2976 _model.fbeShift(offset.value)
+
2977 size.value += offset.value
+
2978 }
+
2979 return values
+
2980 }
+
2981
+
2982 // Get the array
+
2983 fun get(values: _ARRAY_): Long
+
2984 {
+
2985 assert((_buffer.offset + fbeOffset) <= _buffer.size) { "Model is broken!" }
+
2986 if ((_buffer.offset + fbeOffset) > _buffer.size)
+
2987 return 0
+
2988
+
2989 var size: Long = 0
+
2990 val offset = _DOMAIN_fbe.Size()
+
2991 _model.fbeOffset = fbeOffset
+
2992 var i: Long = 0
+
2993 while ((i < values.size) && (i < _size))
+
2994 {
+
2995 offset.value = 0
+
2996 values[i.toInt()] = _model.get(offset)
+
2997 _model.fbeShift(offset.value)
+
2998 size += offset.value
+
2999 i++
+
3000 }
+
3001 return size
+
3002 }
+
3003
+
3004 // Get the array as java.util.ArrayList
+
3005 fun get(values: java.util.ArrayList<_TYPE_>): Long
+
3006 {
+
3007 values.clear()
+
3008
+
3009 assert((_buffer.offset + fbeOffset) <= _buffer.size) { "Model is broken!" }
+
3010 if ((_buffer.offset + fbeOffset) > _buffer.size)
+
3011 return 0
+
3012
+
3013 values.ensureCapacity(_size.toInt())
+
3014
+
3015 var size: Long = 0
+
3016 val offset = _DOMAIN_fbe.Size()
+
3017 _model.fbeOffset = fbeOffset
+
3018 var i = _size
+
3019 while (i-- > 0)
+
3020 {
+
3021 offset.value = 0
+
3022 val value = _model.get(offset)
+
3023 values.add(value)
+
3024 _model.fbeShift(offset.value)
+
3025 size += offset.value
+
3026 }
+
3027 return size
+
3028 }
+
3029
+
3030 // Set the array
+
3031 fun set(values: _ARRAY_): Long
+
3032 {
+
3033 assert((_buffer.offset + fbeOffset) <= _buffer.size) { "Model is broken!" }
+
3034 if ((_buffer.offset + fbeOffset) > _buffer.size)
+
3035 return 0
+
3036
+
3037 var size: Long = 0
+
3038 _model.fbeOffset = fbeOffset
+
3039 var i: Long = 0
+
3040 while ((i < values.size) && (i < _size))
+
3041 {
+
3042 val offset = _model.set(values[i.toInt()])
+
3043 _model.fbeShift(offset)
+
3044 size += offset
+
3045 i++
+
3046 }
+
3047 return size
+
3048 }
+
3049
+
3050 // Set the array as java.util.ArrayList
+
3051 fun set(values: java.util.ArrayList<_TYPE_>): Long
+
3052 {
+
3053 assert((_buffer.offset + fbeOffset) <= _buffer.size) { "Model is broken!" }
+
3054 if ((_buffer.offset + fbeOffset) > _buffer.size)
+
3055 return 0
+
3056
+
3057 var size: Long = 0
+
3058 _model.fbeOffset = fbeOffset
+
3059 var i: Long = 0
+
3060 while ((i < values.size) && (i < _size))
+
3061 {
+
3062 val offset = _model.set(values[i.toInt()])
+
3063 _model.fbeShift(offset)
+
3064 size += offset
+
3065 i++
+
3066 }
+
3067 return size
+
3068 }
+
3069}
+
3070)CODE";
+
3071
+
3072 std::string type_name = IsPackageType(type) ? type : (domain + package + "." + type);
+
3073
+
3074 // Prepare code template
+
3075 code = std::regex_replace(code, std::regex("_DOMAIN_"), domain);
+
3076 code = std::regex_replace(code, std::regex("_NAME_"), name);
+
3077 code = std::regex_replace(code, std::regex("_TYPE_"), type_name);
+
3078 code = std::regex_replace(code, std::regex("_MODEL_"), model);
+
3079 code = std::regex_replace(code, std::regex("_ARRAY_"), "Array<" + type_name + ">");
+
3080 if (optional)
+
3081 code = std::regex_replace(code, std::regex("_INIT_"), "arrayOfNulls<" + type_name + ">(_size.toInt())");
+
3082 else
+
3083 code = std::regex_replace(code, std::regex("_INIT_"), "Array(_size.toInt()) { " + ConvertDefault(domain, package, base) + " }");
+
3084 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
3085
+
3086 Write(code);
+
3087
+
3088 // Generate footer
+
3089 GenerateFooter();
+
3090
+
3091 // Store the file
+
3092 WriteEnd();
+
3093 Store(file);
+
3094}
+
3095
+
3096void GeneratorKotlin::GenerateFBEFinalModelVector(const std::string& domain, const std::string& package, const std::string& name, const std::string& type, const std::string& model)
+
3097{
+
3098 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "fbe";
+
3099
+
3100 // Create package path
+
3101 CppCommon::Directory::CreateTree(path);
+
3102
+
3103 // Generate the file
+
3104 CppCommon::Path file = path / ("FinalModelVector" + name + ".kt");
+
3105 WriteBegin();
+
3106
+
3107 // Generate headers
+
3108 GenerateHeader(CppCommon::Path(_input).filename().string());
+
3109 GenerateImports(domain, package + ".fbe");
+
3110
+
3111 std::string code = R"CODE(
+
3112// Fast Binary Encoding _NAME_ vector final model
+
3113class FinalModelVector_NAME_(buffer: _DOMAIN_fbe.Buffer, offset: Long) : _DOMAIN_fbe.FinalModel(buffer, offset)
+
3114{
+
3115 private val _model = _MODEL_(buffer, offset)
+
3116
+
3117 // Get the allocation size
+
3118 fun fbeAllocationSize(values: java.util.ArrayList<_TYPE_>): Long
+
3119 {
+
3120 var size: Long = 4
+
3121 for (value in values)
+
3122 size += _model.fbeAllocationSize(value)
+
3123 return size
+
3124 }
+
3125 fun fbeAllocationSize(values: java.util.LinkedList<_TYPE_>): Long
+
3126 {
+
3127 var size: Long = 4
+
3128 for (value in values)
+
3129 size += _model.fbeAllocationSize(value)
+
3130 return size
+
3131 }
+
3132 fun fbeAllocationSize(values: java.util.HashSet<_TYPE_>): Long
+
3133 {
+
3134 var size: Long = 4
+
3135 for (value in values)
+
3136 size += _model.fbeAllocationSize(value)
+
3137 return size
+
3138 }
+
3139
+
3140 // Check if the vector is valid
+
3141 override fun verify(): Long
+
3142 {
+
3143 if ((_buffer.offset + fbeOffset + 4) > _buffer.size)
+
3144 return Long.MAX_VALUE
+
3145
+
3146 val fbeVectorSize = readUInt32(fbeOffset).toLong()
+
3147
+
3148 var size: Long = 4
+
3149 _model.fbeOffset = fbeOffset + 4
+
3150 var i = fbeVectorSize
+
3151 while (i-- > 0)
+
3152 {
+
3153 val offset = _model.verify()
+
3154 if (offset == Long.MAX_VALUE)
+
3155 return Long.MAX_VALUE
+
3156 _model.fbeShift(offset)
+
3157 size += offset
+
3158 }
+
3159 return size
+
3160 }
+
3161
+
3162 // Get the vector as java.util.ArrayList
+
3163 fun get(values: java.util.ArrayList<_TYPE_>): Long
+
3164 {
+
3165 values.clear()
+
3166
+
3167 assert((_buffer.offset + fbeOffset + 4) <= _buffer.size) { "Model is broken!" }
+
3168 if ((_buffer.offset + fbeOffset + 4) > _buffer.size)
+
3169 return 0
+
3170
+
3171 val fbeVectorSize = readUInt32(fbeOffset).toLong()
+
3172 if (fbeVectorSize == 0L)
+
3173 return 4
+
3174
+
3175 values.ensureCapacity(fbeVectorSize.toInt())
+
3176
+
3177 var size: Long = 4
+
3178 val offset = _DOMAIN_fbe.Size()
+
3179 _model.fbeOffset = fbeOffset + 4
+
3180 for (i in 0 until fbeVectorSize)
+
3181 {
+
3182 offset.value = 0
+
3183 val value = _model.get(offset)
+
3184 values.add(value)
+
3185 _model.fbeShift(offset.value)
+
3186 size += offset.value
+
3187 }
+
3188 return size
+
3189 }
+
3190
+
3191 // Get the vector as java.util.LinkedList
+
3192 fun get(values: java.util.LinkedList<_TYPE_>): Long
+
3193 {
+
3194 values.clear()
+
3195
+
3196 assert((_buffer.offset + fbeOffset + 4) <= _buffer.size) { "Model is broken!" }
+
3197 if ((_buffer.offset + fbeOffset + 4) > _buffer.size)
+
3198 return 0
+
3199
+
3200 val fbeVectorSize = readUInt32(fbeOffset).toLong()
+
3201 if (fbeVectorSize == 0L)
+
3202 return 4
+
3203
+
3204 var size: Long = 4
+
3205 val offset = _DOMAIN_fbe.Size()
+
3206 _model.fbeOffset = fbeOffset + 4
+
3207 for (i in 0 until fbeVectorSize)
+
3208 {
+
3209 offset.value = 0
+
3210 val value = _model.get(offset)
+
3211 values.add(value)
+
3212 _model.fbeShift(offset.value)
+
3213 size += offset.value
+
3214 }
+
3215 return size
+
3216 }
+
3217
+
3218 // Get the vector as java.util.HashSet
+
3219 fun get(values: java.util.HashSet<_TYPE_>): Long
+
3220 {
+
3221 values.clear()
+
3222
+
3223 assert((_buffer.offset + fbeOffset + 4) <= _buffer.size) { "Model is broken!" }
+
3224 if ((_buffer.offset + fbeOffset + 4) > _buffer.size)
+
3225 return 0
+
3226
+
3227 val fbeVectorSize = readUInt32(fbeOffset).toLong()
+
3228 if (fbeVectorSize == 0L)
+
3229 return 4
+
3230
+
3231 var size: Long = 4
+
3232 val offset = _DOMAIN_fbe.Size()
+
3233 _model.fbeOffset = fbeOffset + 4
+
3234 for (i in 0 until fbeVectorSize)
+
3235 {
+
3236 offset.value = 0
+
3237 val value = _model.get(offset)
+
3238 values.add(value)
+
3239 _model.fbeShift(offset.value)
+
3240 size += offset.value
+
3241 }
+
3242 return size
+
3243 }
+
3244
+
3245 // Set the vector as java.util.ArrayList
+
3246 fun set(values: java.util.ArrayList<_TYPE_>): Long
+
3247 {
+
3248 assert((_buffer.offset + fbeOffset + 4) <= _buffer.size) { "Model is broken!" }
+
3249 if ((_buffer.offset + fbeOffset + 4) > _buffer.size)
+
3250 return 0
+
3251
+
3252 write(fbeOffset, values.size.toUInt())
+
3253
+
3254 var size: Long = 4
+
3255 _model.fbeOffset = fbeOffset + 4
+
3256 for (value in values)
+
3257 {
+
3258 val offset = _model.set(value)
+
3259 _model.fbeShift(offset)
+
3260 size += offset
+
3261 }
+
3262 return size
+
3263 }
+
3264
+
3265 // Set the vector as java.util.LinkedList
+
3266 fun set(values: java.util.LinkedList<_TYPE_>): Long
+
3267 {
+
3268 assert((_buffer.offset + fbeOffset + 4) <= _buffer.size) { "Model is broken!" }
+
3269 if ((_buffer.offset + fbeOffset + 4) > _buffer.size)
+
3270 return 0
+
3271
+
3272 write(fbeOffset, values.size.toUInt())
+
3273
+
3274 var size: Long = 4
+
3275 _model.fbeOffset = fbeOffset + 4
+
3276 for (value in values)
+
3277 {
+
3278 val offset = _model.set(value)
+
3279 _model.fbeShift(offset)
+
3280 size += offset
+
3281 }
+
3282 return size
+
3283 }
+
3284
+
3285 // Set the vector as java.util.HashSet
+
3286 fun set(values: java.util.HashSet<_TYPE_>): Long
+
3287 {
+
3288 assert((_buffer.offset + fbeOffset + 4) <= _buffer.size) { "Model is broken!" }
+
3289 if ((_buffer.offset + fbeOffset + 4) > _buffer.size)
+
3290 return 0
+
3291
+
3292 write(fbeOffset, values.size.toUInt())
+
3293
+
3294 var size: Long = 4
+
3295 _model.fbeOffset = fbeOffset + 4
+
3296 for (value in values)
+
3297 {
+
3298 val offset = _model.set(value)
+
3299 _model.fbeShift(offset)
+
3300 size += offset
+
3301 }
+
3302 return size
+
3303 }
+
3304}
+
3305)CODE";
+
3306
+
3307 std::string type_name = IsPackageType(type) ? type : (domain + package + "." + type);
+
3308
+
3309 // Prepare code template
+
3310 code = std::regex_replace(code, std::regex("_DOMAIN_"), domain);
+
3311 code = std::regex_replace(code, std::regex("_NAME_"), name);
+
3312 code = std::regex_replace(code, std::regex("_TYPE_"), type_name);
+
3313 code = std::regex_replace(code, std::regex("_MODEL_"), model);
+
3314 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
3315
+
3316 Write(code);
+
3317
+
3318 // Generate footer
+
3319 GenerateFooter();
+
3320
+
3321 // Store the file
+
3322 WriteEnd();
+
3323 Store(file);
+
3324}
+
3325
+
3326void GeneratorKotlin::GenerateFBEFinalModelMap(const std::string& domain, const std::string& package, const std::string& key_name, const std::string& key_type, const std::string& key_model, const std::string& value_name, const std::string& value_type, const std::string& value_model)
+
3327{
+
3328 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "fbe";
+
3329
+
3330 // Create package path
+
3331 CppCommon::Directory::CreateTree(path);
+
3332
+
3333 // Generate the file
+
3334 CppCommon::Path file = path / ("FinalModelMap" + key_name + value_name + ".kt");
+
3335 WriteBegin();
+
3336
+
3337 // Generate headers
+
3338 GenerateHeader(CppCommon::Path(_input).filename().string());
+
3339 GenerateImports(domain, package + ".fbe");
+
3340
+
3341 std::string code = R"CODE(
+
3342// Fast Binary Encoding _KEY_NAME_->_VALUE_NAME_ map final model
+
3343class FinalModelMap_KEY_NAME__VALUE_NAME_(buffer: _DOMAIN_fbe.Buffer, offset: Long) : _DOMAIN_fbe.FinalModel(buffer, offset)
+
3344{
+
3345 private val _modelKey = _KEY_MODEL_(buffer, offset)
+
3346 private val _modelValue = _VALUE_MODEL_(buffer, offset)
+
3347
+
3348 // Get the allocation size
+
3349 fun fbeAllocationSize(values: java.util.TreeMap<_KEY_TYPE_, _VALUE_TYPE_>): Long
+
3350 {
+
3351 var size: Long = 4
+
3352 for ((key, value1) in values)
+
3353 {
+
3354 size += _modelKey.fbeAllocationSize(key)
+
3355 size += _modelValue.fbeAllocationSize(value1)
+
3356 }
+
3357 return size
+
3358 }
+
3359 fun fbeAllocationSize(values: java.util.HashMap<_KEY_TYPE_, _VALUE_TYPE_>): Long
+
3360 {
+
3361 var size: Long = 4
+
3362 for ((key, value1) in values)
+
3363 {
+
3364 size += _modelKey.fbeAllocationSize(key)
+
3365 size += _modelValue.fbeAllocationSize(value1)
+
3366 }
+
3367 return size
+
3368 }
+
3369
+
3370 // Check if the map is valid
+
3371 override fun verify(): Long
+
3372 {
+
3373 if ((_buffer.offset + fbeOffset + 4) > _buffer.size)
+
3374 return Long.MAX_VALUE
+
3375
+
3376 val fbeMapSize = readUInt32(fbeOffset).toLong()
+
3377
+
3378 var size: Long = 4
+
3379 _modelKey.fbeOffset = fbeOffset + 4
+
3380 _modelValue.fbeOffset = fbeOffset + 4
+
3381 var i = fbeMapSize
+
3382 while (i-- > 0)
+
3383 {
+
3384 val offsetKey = _modelKey.verify()
+
3385 if (offsetKey == Long.MAX_VALUE)
+
3386 return Long.MAX_VALUE
+
3387 _modelKey.fbeShift(offsetKey)
+
3388 _modelValue.fbeShift(offsetKey)
+
3389 size += offsetKey
+
3390 val offsetValue = _modelValue.verify()
+
3391 if (offsetValue == Long.MAX_VALUE)
+
3392 return Long.MAX_VALUE
+
3393 _modelKey.fbeShift(offsetValue)
+
3394 _modelValue.fbeShift(offsetValue)
+
3395 size += offsetValue
+
3396 }
+
3397 return size
+
3398 }
+
3399
+
3400 // Get the map as java.util.TreeMap
+
3401 fun get(values: java.util.TreeMap<_KEY_TYPE_, _VALUE_TYPE_>): Long
+
3402 {
+
3403 values.clear()
+
3404
+
3405 assert((_buffer.offset + fbeOffset + 4) <= _buffer.size) { "Model is broken!" }
+
3406 if ((_buffer.offset + fbeOffset + 4) > _buffer.size)
+
3407 return 0
+
3408
+
3409 val fbeMapSize = readUInt32(fbeOffset).toLong()
+
3410 if (fbeMapSize == 0L)
+
3411 return 4
+
3412
+
3413 var size: Long = 4
+
3414 val offset = _DOMAIN_fbe.Size()
+
3415 _modelKey.fbeOffset = fbeOffset + 4
+
3416 _modelValue.fbeOffset = fbeOffset + 4
+
3417 var i = fbeMapSize
+
3418 while (i-- > 0)
+
3419 {
+
3420 offset.value = 0
+
3421 val key = _modelKey.get(offset)
+
3422 _modelKey.fbeShift(offset.value)
+
3423 _modelValue.fbeShift(offset.value)
+
3424 size += offset.value
+
3425 offset.value = 0
+
3426 val value = _modelValue.get(offset)
+
3427 _modelKey.fbeShift(offset.value)
+
3428 _modelValue.fbeShift(offset.value)
+
3429 size += offset.value
+
3430 values[key] = value
+
3431 }
+
3432 return size
+
3433 }
+
3434
+
3435 // Get the map as java.util.HashMap
+
3436 fun get(values: java.util.HashMap<_KEY_TYPE_, _VALUE_TYPE_>): Long
+
3437 {
+
3438 values.clear()
+
3439
+
3440 assert((_buffer.offset + fbeOffset + 4) <= _buffer.size) { "Model is broken!" }
+
3441 if ((_buffer.offset + fbeOffset + 4) > _buffer.size)
+
3442 return 0
+
3443
+
3444 val fbeMapSize = readUInt32(fbeOffset).toLong()
+
3445 if (fbeMapSize == 0L)
+
3446 return 4
+
3447
+
3448 var size: Long = 4
+
3449 val offset = _DOMAIN_fbe.Size()
+
3450 _modelKey.fbeOffset = fbeOffset + 4
+
3451 _modelValue.fbeOffset = fbeOffset + 4
+
3452 var i = fbeMapSize
+
3453 while (i-- > 0)
+
3454 {
+
3455 offset.value = 0
+
3456 val key = _modelKey.get(offset)
+
3457 _modelKey.fbeShift(offset.value)
+
3458 _modelValue.fbeShift(offset.value)
+
3459 size += offset.value
+
3460 offset.value = 0
+
3461 val value = _modelValue.get(offset)
+
3462 _modelKey.fbeShift(offset.value)
+
3463 _modelValue.fbeShift(offset.value)
+
3464 size += offset.value
+
3465
+
3466 values[key] = value
+
3467 }
+
3468 return size
+
3469 }
+
3470
+
3471 // Set the map as java.util.TreeMap
+
3472 fun set(values: java.util.TreeMap<_KEY_TYPE_, _VALUE_TYPE_>): Long
+
3473 {
+
3474 assert((_buffer.offset + fbeOffset + 4) <= _buffer.size) { "Model is broken!" }
+
3475 if ((_buffer.offset + fbeOffset + 4) > _buffer.size)
+
3476 return 0
+
3477
+
3478 write(fbeOffset, values.size.toUInt())
+
3479
+
3480 var size: Long = 4
+
3481 _modelKey.fbeOffset = fbeOffset + 4
+
3482 _modelValue.fbeOffset = fbeOffset + 4
+
3483 for ((key, value1) in values)
+
3484 {
+
3485 val offsetKey = _modelKey.set(key)
+
3486 _modelKey.fbeShift(offsetKey)
+
3487 _modelValue.fbeShift(offsetKey)
+
3488 val offsetValue = _modelValue.set(value1)
+
3489 _modelKey.fbeShift(offsetValue)
+
3490 _modelValue.fbeShift(offsetValue)
+
3491 size += offsetKey + offsetValue
+
3492 }
+
3493 return size
+
3494 }
+
3495
+
3496 // Set the map as java.util.HashMap
+
3497 fun set(values: java.util.HashMap<_KEY_TYPE_, _VALUE_TYPE_>): Long
+
3498 {
+
3499 assert((_buffer.offset + fbeOffset + 4) <= _buffer.size) { "Model is broken!" }
+
3500 if ((_buffer.offset + fbeOffset + 4) > _buffer.size)
+
3501 return 0
+
3502
+
3503 write(fbeOffset, values.size.toUInt())
+
3504
+
3505 var size: Long = 4
+
3506 _modelKey.fbeOffset = fbeOffset + 4
+
3507 _modelValue.fbeOffset = fbeOffset + 4
+
3508 for ((key, value1) in values)
+
3509 {
+
3510 val offsetKey = _modelKey.set(key)
+
3511 _modelKey.fbeShift(offsetKey)
+
3512 _modelValue.fbeShift(offsetKey)
+
3513 val offsetValue = _modelValue.set(value1)
+
3514 _modelKey.fbeShift(offsetValue)
+
3515 _modelValue.fbeShift(offsetValue)
+
3516 size += offsetKey + offsetValue
+
3517 }
+
3518 return size
+
3519 }
+
3520}
+
3521)CODE";
+
3522
+
3523 std::string key_type_name = IsPackageType(key_type) ? key_type : (domain + package + "." + key_type);
+
3524 std::string value_type_name = IsPackageType(value_type) ? value_type : (domain + package + "." + value_type);
+
3525
+
3526 // Prepare code template
+
3527 code = std::regex_replace(code, std::regex("_DOMAIN_"), domain);
+
3528 code = std::regex_replace(code, std::regex("_KEY_NAME_"), key_name);
+
3529 code = std::regex_replace(code, std::regex("_KEY_TYPE_"), key_type_name);
+
3530 code = std::regex_replace(code, std::regex("_KEY_MODEL_"), key_model);
+
3531 code = std::regex_replace(code, std::regex("_VALUE_NAME_"), value_name);
+
3532 code = std::regex_replace(code, std::regex("_VALUE_TYPE_"), value_type_name);
+
3533 code = std::regex_replace(code, std::regex("_VALUE_MODEL_"), value_model);
+
3534 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
3535
+
3536 Write(code);
+
3537
+
3538 // Generate footer
+
3539 GenerateFooter();
+
3540
+
3541 // Store the file
+
3542 WriteEnd();
+
3543 Store(file);
+
3544}
+
3545
+
3546void GeneratorKotlin::GenerateFBEFinalModelEnumFlags(const std::string& domain, const std::string& package, const std::string& name, const std::string& type)
+
3547{
+
3548 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "fbe";
+
3549
+
3550 // Create package path
+
3551 CppCommon::Directory::CreateTree(path);
+
3552
+
3553 // Generate the file
+
3554 CppCommon::Path file = path / ("FinalModel" + name + ".kt");
+
3555 WriteBegin();
+
3556
+
3557 // Generate headers
+
3558 GenerateHeader(CppCommon::Path(_input).filename().string());
+
3559 GenerateImports(domain, package + ".fbe");
+
3560
+
3561 std::string code = R"CODE(
+
3562// Fast Binary Encoding _NAME_ final model
+
3563class FinalModel_NAME_(buffer: _DOMAIN_fbe.Buffer, offset: Long) : _DOMAIN_fbe.FinalModel(buffer, offset)
+
3564{
+
3565 // Get the allocation size
+
3566 @Suppress("UNUSED_PARAMETER")
+
3567 fun fbeAllocationSize(value: _DOMAIN__PACKAGE_._NAME_): Long = fbeSize
+
3568
+
3569 // Final size
+
3570 override val fbeSize: Long = _SIZE_
+
3571
+
3572 // Check if the value is valid
+
3573 override fun verify(): Long
+
3574 {
+
3575 if ((_buffer.offset + fbeOffset + fbeSize) > _buffer.size)
+
3576 return Long.MAX_VALUE
+
3577
+
3578 return fbeSize
+
3579 }
+
3580
+
3581 // Get the value
+
3582 fun get(size: _DOMAIN_fbe.Size): _DOMAIN__PACKAGE_._NAME_
+
3583 {
+
3584 if ((_buffer.offset + fbeOffset + fbeSize) > _buffer.size)
+
3585 return _DOMAIN__PACKAGE_._NAME_()
+
3586
+
3587 size.value = fbeSize
+
3588 return _DOMAIN__PACKAGE_._NAME_(_READ_(fbeOffset))
+
3589 }
+
3590
+
3591 // Set the value
+
3592 fun set(value: _DOMAIN__PACKAGE_._NAME_): Long
+
3593 {
+
3594 assert((_buffer.offset + fbeOffset + fbeSize) <= _buffer.size) { "Model is broken!" }
+
3595 if ((_buffer.offset + fbeOffset + fbeSize) > _buffer.size)
+
3596 return 0
+
3597
+
3598 write(fbeOffset, value.raw)
+
3599 return fbeSize
+
3600 }
+
3601}
+
3602)CODE";
+
3603
+
3604 // Prepare code template
+
3605 code = std::regex_replace(code, std::regex("_DOMAIN_"), domain);
+
3606 code = std::regex_replace(code, std::regex("_PACKAGE_"), package);
+
3607 code = std::regex_replace(code, std::regex("_NAME_"), name);
+
3608 code = std::regex_replace(code, std::regex("_SIZE_"), ConvertEnumSize(type));
+
3609 code = std::regex_replace(code, std::regex("_READ_"), ConvertEnumRead(type));
+
3610 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
3611
+
3612 Write(code);
+
3613
+
3614 // Generate footer
+
3615 GenerateFooter();
+
3616
+
3617 // Store the file
+
3618 WriteEnd();
+
3619 Store(file);
+
3620}
+
3621
+
3622void GeneratorKotlin::GenerateFBESender(const std::string& domain, const std::string& package)
+
3623{
+
3624 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
3625
+
3626 // Generate the file
+
3627 CppCommon::Path file = path / "Sender.kt";
+
3628 WriteBegin();
+
3629
+
3630 // Generate headers
+
3631 GenerateHeader("FBE");
+
3632 GenerateImports(domain, package);
+
3633
+
3634 std::string code = R"CODE(
+
3635// Fast Binary Encoding base sender
+
3636@Suppress("MemberVisibilityCanBePrivate")
+
3637abstract class Sender : ISenderListener
+
3638{
+
3639 // Get the bytes buffer
+
3640 var buffer: Buffer = Buffer()
+
3641 private set
+
3642 // Enable/Disable logging
+
3643 var logging: Boolean = false
+
3644 // Get the final protocol flag
+
3645 var final: Boolean = false
+
3646 private set
+
3647
+
3648 protected constructor(final: Boolean) { this.final = final }
+
3649 protected constructor(buffer: Buffer, final: Boolean) { this.buffer = buffer; this.final = final }
+
3650
+
3651 // Reset the sender buffer
+
3652 fun reset() { buffer.reset() }
+
3653
+
3654 // Send serialized buffer.
+
3655 // Direct call of the method requires knowledge about internals of FBE models serialization.
+
3656 // Use it with care!
+
3657 fun sendSerialized(listener: ISenderListener, serialized: Long): Long
+
3658 {
+
3659 assert(serialized > 0) { "Invalid size of the serialized buffer!" }
+
3660 if (serialized <= 0)
+
3661 return 0
+
3662
+
3663 // Shift the send buffer
+
3664 buffer.shift(serialized)
+
3665
+
3666 // Send the value
+
3667 val sent = listener.onSend(buffer.data, 0, buffer.size)
+
3668 buffer.remove(0, sent)
+
3669 return sent
+
3670 }
+
3671}
+
3672)CODE";
+
3673
+
3674 // Prepare code template
+
3675 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
3676
+
3677 Write(code);
+
3678
+
3679 // Generate footer
+
3680 GenerateFooter();
+
3681
+
3682 // Store the file
+
3683 WriteEnd();
+
3684 Store(file);
+
3685}
+
3686
+
3687void GeneratorKotlin::GenerateFBESenderListener(const std::string& domain, const std::string& package)
+
3688{
+
3689 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
3690
+
3691 // Generate the file
+
3692 CppCommon::Path file = path / "ISenderListener.kt";
+
3693 WriteBegin();
+
3694
+
3695 // Generate headers
+
3696 GenerateHeader("FBE");
+
3697 GenerateImports(domain, package);
+
3698
+
3699 std::string code = R"CODE(
+
3700// Fast Binary Encoding base sender listener interface
+
3701interface ISenderListener
+
3702{
+
3703 // Send message handler
+
3704 fun onSend(buffer: ByteArray, offset: Long, size: Long): Long { return size }
+
3705 // Send log message handler
+
3706 fun onSendLog(message: String) {}
+
3707}
+
3708)CODE";
+
3709
+
3710 // Prepare code template
+
3711 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
3712
+
3713 Write(code);
+
3714
+
3715 // Generate footer
+
3716 GenerateFooter();
+
3717
+
3718 // Store the file
+
3719 WriteEnd();
+
3720 Store(file);
+
3721}
+
3722
+
3723void GeneratorKotlin::GenerateFBEReceiver(const std::string& domain, const std::string& package)
+
3724{
+
3725 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
3726
+
3727 // Generate the file
+
3728 CppCommon::Path file = path / "Receiver.kt";
+
3729 WriteBegin();
+
3730
+
3731 // Generate headers
+
3732 GenerateHeader("FBE");
+
3733 GenerateImports(domain, package);
+
3734
+
3735 std::string code = R"CODE(
+
3736// Fast Binary Encoding base receiver
+
3737@Suppress("MemberVisibilityCanBePrivate")
+
3738abstract class Receiver : IReceiverListener
+
3739{
+
3740 // Get the bytes buffer
+
3741 var buffer: Buffer = Buffer()
+
3742 private set
+
3743 // Enable/Disable logging
+
3744 var logging: Boolean = false
+
3745 // Get the final protocol flag
+
3746 var final: Boolean = false
+
3747 private set
+
3748
+
3749 protected constructor(final: Boolean) { this.final = final }
+
3750 protected constructor(buffer: Buffer, final: Boolean) { this.buffer = buffer; this.final = final }
+
3751
+
3752 // Reset the receiver buffer
+
3753 fun reset() { buffer.reset() }
+
3754
+
3755 // Receive data
+
3756 fun receive(buffer: Buffer) { receive(buffer.data, 0, buffer.size) }
+
3757 fun receive(buffer: ByteArray, offset: Long = 0, size: Long = buffer.size.toLong())
+
3758 {
+
3759 assert((offset + size) <= buffer.size) { "Invalid offset & size!" }
+
3760 if ((offset + size) > buffer.size)
+
3761 throw IllegalArgumentException("Invalid offset & size!")
+
3762
+
3763 if (size == 0L)
+
3764 return
+
3765
+
3766 // Storage buffer
+
3767 var offset0 = this.buffer.offset
+
3768 var offset1 = this.buffer.size
+
3769 var size1 = this.buffer.size
+
3770
+
3771 // Receive buffer
+
3772 var offset2: Long = 0
+
3773
+
3774 // While receive buffer is available to handle...
+
3775 while (offset2 < size)
+
3776 {
+
3777 var messageBuffer: ByteArray? = null
+
3778 var messageOffset: Long = 0
+
3779 var messageSize: Long = 0
+
3780
+
3781 // Try to receive message size
+
3782 var messageSizeCopied = false
+
3783 var messageSizeFound = false
+
3784 while (!messageSizeFound)
+
3785 {
+
3786 // Look into the storage buffer
+
3787 if (offset0 < size1)
+
3788 {
+
3789 var count = kotlin.math.min(size1 - offset0, 4)
+
3790 if (count == 4L)
+
3791 {
+
3792 messageSizeCopied = true
+
3793 messageSizeFound = true
+
3794 messageSize = Buffer.readUInt32(this.buffer.data, offset0).toLong()
+
3795 offset0 += 4
+
3796 break
+
3797 }
+
3798 else
+
3799 {
+
3800 // Fill remaining data from the receive buffer
+
3801 if (offset2 < size)
+
3802 {
+
3803 count = kotlin.math.min(size - offset2, 4 - count)
+
3804
+
3805 // Allocate and refresh the storage buffer
+
3806 this.buffer.allocate(count)
+
3807 size1 += count
+
3808
+
3809 System.arraycopy(buffer, (offset + offset2).toInt(), this.buffer.data, offset1.toInt(), count.toInt())
+
3810 offset1 += count
+
3811 offset2 += count
+
3812 continue
+
3813 }
+
3814 else
+
3815 break
+
3816 }
+
3817 }
+
3818
+
3819 // Look into the receive buffer
+
3820 if (offset2 < size)
+
3821 {
+
3822 val count = kotlin.math.min(size - offset2, 4)
+
3823 if (count == 4L)
+
3824 {
+
3825 messageSizeFound = true
+
3826 messageSize = Buffer.readUInt32(buffer, offset + offset2).toLong()
+
3827 offset2 += 4
+
3828 break
+
3829 }
+
3830 else
+
3831 {
+
3832 // Allocate and refresh the storage buffer
+
3833 this.buffer.allocate(count)
+
3834 size1 += count
+
3835
+
3836 System.arraycopy(buffer, (offset + offset2).toInt(), this.buffer.data, offset1.toInt(), count.toInt())
+
3837 offset1 += count
+
3838 offset2 += count
+
3839 continue
+
3840 }
+
3841 }
+
3842 else
+
3843 break
+
3844 }
+
3845
+
3846 if (!messageSizeFound)
+
3847 return
+
3848
+
3849 // Check the message full size
+
3850 val minSize = if (final) (4 + 4) else (4 + 4 + 4 + 4)
+
3851 assert(messageSize >= minSize) { "Invalid receive data!" }
+
3852 if (messageSize < minSize)
+
3853 return
+
3854
+
3855 // Try to receive message body
+
3856 var messageFound = false
+
3857 while (!messageFound)
+
3858 {
+
3859 // Look into the storage buffer
+
3860 if (offset0 < size1)
+
3861 {
+
3862 var count = kotlin.math.min(size1 - offset0, messageSize - 4)
+
3863 if (count == (messageSize - 4))
+
3864 {
+
3865 messageFound = true
+
3866 messageBuffer = this.buffer.data
+
3867 messageOffset = offset0 - 4
+
3868 offset0 += messageSize - 4
+
3869 break
+
3870 }
+
3871 else
+
3872 {
+
3873 // Fill remaining data from the receive buffer
+
3874 if (offset2 < size)
+
3875 {
+
3876 // Copy message size into the storage buffer
+
3877 if (!messageSizeCopied)
+
3878 {
+
3879 // Allocate and refresh the storage buffer
+
3880 this.buffer.allocate(4)
+
3881 size1 += 4
+
3882
+
3883 Buffer.write(this.buffer.data, offset0, messageSize.toUInt())
+
3884 offset0 += 4
+
3885 offset1 += 4
+
3886
+
3887 messageSizeCopied = true
+
3888 }
+
3889
+
3890 count = kotlin.math.min(size - offset2, messageSize - 4 - count)
+
3891
+
3892 // Allocate and refresh the storage buffer
+
3893 this.buffer.allocate(count)
+
3894 size1 += count
+
3895
+
3896 System.arraycopy(buffer, (offset + offset2).toInt(), this.buffer.data, offset1.toInt(), count.toInt())
+
3897 offset1 += count
+
3898 offset2 += count
+
3899 continue
+
3900 }
+
3901 else
+
3902 break
+
3903 }
+
3904 }
+
3905
+
3906 // Look into the receive buffer
+
3907 if (offset2 < size)
+
3908 {
+
3909 val count = kotlin.math.min(size - offset2, messageSize - 4)
+
3910 if (!messageSizeCopied && (count == (messageSize - 4)))
+
3911 {
+
3912 messageFound = true
+
3913 messageBuffer = buffer
+
3914 messageOffset = offset + offset2 - 4
+
3915 offset2 += messageSize - 4
+
3916 break
+
3917 }
+
3918 else
+
3919 {
+
3920 // Copy message size into the storage buffer
+
3921 if (!messageSizeCopied)
+
3922 {
+
3923 // Allocate and refresh the storage buffer
+
3924 this.buffer.allocate(4)
+
3925 size1 += 4
+
3926
+
3927 Buffer.write(this.buffer.data, offset0, messageSize.toUInt())
+
3928 offset0 += 4
+
3929 offset1 += 4
+
3930
+
3931 messageSizeCopied = true
+
3932 }
+
3933
+
3934 // Allocate and refresh the storage buffer
+
3935 this.buffer.allocate(count)
+
3936 size1 += count
+
3937
+
3938 System.arraycopy(buffer, (offset + offset2).toInt(), this.buffer.data, offset1.toInt(), count.toInt())
+
3939 offset1 += count
+
3940 offset2 += count
+
3941 continue
+
3942 }
+
3943 }
+
3944 else
+
3945 break
+
3946 }
+
3947
+
3948 if (!messageFound)
+
3949 {
+
3950 // Copy message size into the storage buffer
+
3951 if (!messageSizeCopied)
+
3952 {
+
3953 // Allocate and refresh the storage buffer
+
3954 this.buffer.allocate(4)
+
3955 size1 += 4
+
3956
+
3957 Buffer.write(this.buffer.data, offset0, messageSize.toUInt())
+
3958 offset0 += 4
+
3959 offset1 += 4
+
3960
+
3961 @Suppress("UNUSED_VALUE")
+
3962 messageSizeCopied = true
+
3963 }
+
3964 return
+
3965 }
+
3966
+
3967 if (messageBuffer != null)
+
3968 {
+
3969 @Suppress("ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE")
+
3970 val fbeStructSize: Long
+
3971 val fbeStructType: Long
+
3972
+
3973 // Read the message parameters
+
3974 if (final)
+
3975 {
+
3976 @Suppress("UNUSED_VALUE")
+
3977 fbeStructSize = Buffer.readUInt32(messageBuffer, messageOffset).toLong()
+
3978 fbeStructType = Buffer.readUInt32(messageBuffer, messageOffset + 4).toLong()
+
3979 }
+
3980 else
+
3981 {
+
3982 val fbeStructOffset = Buffer.readUInt32(messageBuffer, messageOffset + 4).toLong()
+
3983 @Suppress("UNUSED_VALUE")
+
3984 fbeStructSize = Buffer.readUInt32(messageBuffer, messageOffset + fbeStructOffset).toLong()
+
3985 fbeStructType = Buffer.readUInt32(messageBuffer, messageOffset + fbeStructOffset + 4).toLong()
+
3986 }
+
3987
+
3988 // Handle the message
+
3989 onReceive(fbeStructType, messageBuffer, messageOffset, messageSize)
+
3990 }
+
3991
+
3992 // Reset the storage buffer
+
3993 this.buffer.reset()
+
3994
+
3995 // Refresh the storage buffer
+
3996 offset0 = this.buffer.offset
+
3997 offset1 = this.buffer.size
+
3998 size1 = this.buffer.size
+
3999 }
+
4000 }
+
4001
+
4002 // Receive message handler
+
4003 abstract fun onReceive(type: Long, buffer: ByteArray, offset: Long, size: Long): Boolean
+
4004}
+
4005)CODE";
+
4006
+
4007 // Prepare code template
+
4008 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
4009
+
4010 Write(code);
+
4011
+
4012 // Generate footer
+
4013 GenerateFooter();
+
4014
+
4015 // Store the file
+
4016 WriteEnd();
+
4017 Store(file);
+
4018}
+
4019
+
4020void GeneratorKotlin::GenerateFBEReceiverListener(const std::string& domain, const std::string& package)
+
4021{
+
4022 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
4023
+
4024 // Generate the file
+
4025 CppCommon::Path file = path / "IReceiverListener.kt";
+
4026 WriteBegin();
+
4027
+
4028 // Generate headers
+
4029 GenerateHeader("FBE");
+
4030 GenerateImports(domain, package);
+
4031
+
4032 std::string code = R"CODE(
+
4033// Fast Binary Encoding base receiver listener interface
+
4034interface IReceiverListener
+
4035{
+
4036 // Receive log message handler
+
4037 fun onReceiveLog(message: String) {}
+
4038}
+
4039)CODE";
+
4040
+
4041 // Prepare code template
+
4042 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
4043
+
4044 Write(code);
+
4045
+
4046 // Generate footer
+
4047 GenerateFooter();
+
4048
+
4049 // Store the file
+
4050 WriteEnd();
+
4051 Store(file);
+
4052}
+
4053
+
4054void GeneratorKotlin::GenerateFBEClient(const std::string& domain, const std::string& package)
+
4055{
+
4056 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
4057
+
4058 // Generate the file
+
4059 CppCommon::Path file = path / "Client.kt";
+
4060 WriteBegin();
+
4061
+
4062 // Generate headers
+
4063 GenerateHeader("FBE");
+
4064 GenerateImports(domain, package);
+
4065
+
4066 std::string code = R"CODE(
+
4067// Fast Binary Encoding base client
+
4068@Suppress("MemberVisibilityCanBePrivate")
+
4069abstract class Client : IClientListener
+
4070{
+
4071 // Get the send bytes buffer
+
4072 var sendBuffer: Buffer = Buffer()
+
4073 private set
+
4074 // Get the receive bytes buffer
+
4075 var receiveBuffer: Buffer = Buffer()
+
4076 private set
+
4077 // Enable/Disable logging
+
4078 var logging: Boolean = false
+
4079 // Get the final protocol flag
+
4080 var final: Boolean = false
+
4081 private set
+
4082
+
4083 protected constructor(final: Boolean) { this.final = final }
+
4084 protected constructor(sendBuffer: Buffer, receiveBuffer: Buffer, final: Boolean) { this.sendBuffer = sendBuffer; this.receiveBuffer = receiveBuffer; this.final = final }
+
4085
+
4086 // Reset the client buffers
+
4087 fun reset() { sendBuffer.reset(); receiveBuffer.reset() }
+
4088
+
4089 // Send serialized buffer.
+
4090 // Direct call of the method requires knowledge about internals of FBE models serialization.
+
4091 // Use it with care!
+
4092 fun sendSerialized(listener: ISenderListener, serialized: Long): Long
+
4093 {
+
4094 assert(serialized > 0) { "Invalid size of the serialized buffer!" }
+
4095 if (serialized <= 0)
+
4096 return 0
+
4097
+
4098 // Shift the send buffer
+
4099 sendBuffer.shift(serialized)
+
4100
+
4101 // Send the value
+
4102 val sent = listener.onSend(sendBuffer.data, 0, sendBuffer.size)
+
4103 sendBuffer.remove(0, sent)
+
4104 return sent
+
4105 }
+
4106
+
4107 // Receive data
+
4108 fun receive(buffer: Buffer) { receive(buffer.data, 0, buffer.size) }
+
4109 fun receive(buffer: ByteArray, offset: Long = 0, size: Long = buffer.size.toLong())
+
4110 {
+
4111 assert((offset + size) <= buffer.size) { "Invalid offset & size!" }
+
4112 if ((offset + size) > buffer.size)
+
4113 throw IllegalArgumentException("Invalid offset & size!")
+
4114
+
4115 if (size == 0L)
+
4116 return
+
4117
+
4118 // Storage buffer
+
4119 var offset0 = this.receiveBuffer.offset
+
4120 var offset1 = this.receiveBuffer.size
+
4121 var size1 = this.receiveBuffer.size
+
4122
+
4123 // Receive buffer
+
4124 var offset2: Long = 0
+
4125
+
4126 // While receive buffer is available to handle...
+
4127 while (offset2 < size)
+
4128 {
+
4129 var messageBuffer: ByteArray? = null
+
4130 var messageOffset: Long = 0
+
4131 var messageSize: Long = 0
+
4132
+
4133 // Try to receive message size
+
4134 var messageSizeCopied = false
+
4135 var messageSizeFound = false
+
4136 while (!messageSizeFound)
+
4137 {
+
4138 // Look into the storage buffer
+
4139 if (offset0 < size1)
+
4140 {
+
4141 var count = kotlin.math.min(size1 - offset0, 4)
+
4142 if (count == 4L)
+
4143 {
+
4144 messageSizeCopied = true
+
4145 messageSizeFound = true
+
4146 messageSize = Buffer.readUInt32(this.receiveBuffer.data, offset0).toLong()
+
4147 offset0 += 4
+
4148 break
+
4149 }
+
4150 else
+
4151 {
+
4152 // Fill remaining data from the receive buffer
+
4153 if (offset2 < size)
+
4154 {
+
4155 count = kotlin.math.min(size - offset2, 4 - count)
+
4156
+
4157 // Allocate and refresh the storage buffer
+
4158 this.receiveBuffer.allocate(count)
+
4159 size1 += count
+
4160
+
4161 System.arraycopy(buffer, (offset + offset2).toInt(), this.receiveBuffer.data, offset1.toInt(), count.toInt())
+
4162 offset1 += count
+
4163 offset2 += count
+
4164 continue
+
4165 }
+
4166 else
+
4167 break
+
4168 }
+
4169 }
+
4170
+
4171 // Look into the receive buffer
+
4172 if (offset2 < size)
+
4173 {
+
4174 val count = kotlin.math.min(size - offset2, 4)
+
4175 if (count == 4L)
+
4176 {
+
4177 messageSizeFound = true
+
4178 messageSize = Buffer.readUInt32(buffer, offset + offset2).toLong()
+
4179 offset2 += 4
+
4180 break
+
4181 }
+
4182 else
+
4183 {
+
4184 // Allocate and refresh the storage buffer
+
4185 this.receiveBuffer.allocate(count)
+
4186 size1 += count
+
4187
+
4188 System.arraycopy(buffer, (offset + offset2).toInt(), this.receiveBuffer.data, offset1.toInt(), count.toInt())
+
4189 offset1 += count
+
4190 offset2 += count
+
4191 continue
+
4192 }
+
4193 }
+
4194 else
+
4195 break
+
4196 }
+
4197
+
4198 if (!messageSizeFound)
+
4199 return
+
4200
+
4201 // Check the message full size
+
4202 val minSize = if (final) (4 + 4) else (4 + 4 + 4 + 4)
+
4203 assert(messageSize >= minSize) { "Invalid receive data!" }
+
4204 if (messageSize < minSize)
+
4205 return
+
4206
+
4207 // Try to receive message body
+
4208 var messageFound = false
+
4209 while (!messageFound)
+
4210 {
+
4211 // Look into the storage buffer
+
4212 if (offset0 < size1)
+
4213 {
+
4214 var count = kotlin.math.min(size1 - offset0, messageSize - 4)
+
4215 if (count == (messageSize - 4))
+
4216 {
+
4217 messageFound = true
+
4218 messageBuffer = this.receiveBuffer.data
+
4219 messageOffset = offset0 - 4
+
4220 offset0 += messageSize - 4
+
4221 break
+
4222 }
+
4223 else
+
4224 {
+
4225 // Fill remaining data from the receive buffer
+
4226 if (offset2 < size)
+
4227 {
+
4228 // Copy message size into the storage buffer
+
4229 if (!messageSizeCopied)
+
4230 {
+
4231 // Allocate and refresh the storage buffer
+
4232 this.receiveBuffer.allocate(4)
+
4233 size1 += 4
+
4234
+
4235 Buffer.write(this.receiveBuffer.data, offset0, messageSize.toUInt())
+
4236 offset0 += 4
+
4237 offset1 += 4
+
4238
+
4239 messageSizeCopied = true
+
4240 }
+
4241
+
4242 count = kotlin.math.min(size - offset2, messageSize - 4 - count)
+
4243
+
4244 // Allocate and refresh the storage buffer
+
4245 this.receiveBuffer.allocate(count)
+
4246 size1 += count
+
4247
+
4248 System.arraycopy(buffer, (offset + offset2).toInt(), this.receiveBuffer.data, offset1.toInt(), count.toInt())
+
4249 offset1 += count
+
4250 offset2 += count
+
4251 continue
+
4252 }
+
4253 else
+
4254 break
+
4255 }
+
4256 }
+
4257
+
4258 // Look into the receive buffer
+
4259 if (offset2 < size)
+
4260 {
+
4261 val count = kotlin.math.min(size - offset2, messageSize - 4)
+
4262 if (!messageSizeCopied && (count == (messageSize - 4)))
+
4263 {
+
4264 messageFound = true
+
4265 messageBuffer = buffer
+
4266 messageOffset = offset + offset2 - 4
+
4267 offset2 += messageSize - 4
+
4268 break
+
4269 }
+
4270 else
+
4271 {
+
4272 // Copy message size into the storage buffer
+
4273 if (!messageSizeCopied)
+
4274 {
+
4275 // Allocate and refresh the storage buffer
+
4276 this.receiveBuffer.allocate(4)
+
4277 size1 += 4
+
4278
+
4279 Buffer.write(this.receiveBuffer.data, offset0, messageSize.toUInt())
+
4280 offset0 += 4
+
4281 offset1 += 4
+
4282
+
4283 messageSizeCopied = true
+
4284 }
+
4285
+
4286 // Allocate and refresh the storage buffer
+
4287 this.receiveBuffer.allocate(count)
+
4288 size1 += count
+
4289
+
4290 System.arraycopy(buffer, (offset + offset2).toInt(), this.receiveBuffer.data, offset1.toInt(), count.toInt())
+
4291 offset1 += count
+
4292 offset2 += count
+
4293 continue
+
4294 }
+
4295 }
+
4296 else
+
4297 break
+
4298 }
+
4299
+
4300 if (!messageFound)
+
4301 {
+
4302 // Copy message size into the storage buffer
+
4303 if (!messageSizeCopied)
+
4304 {
+
4305 // Allocate and refresh the storage buffer
+
4306 this.receiveBuffer.allocate(4)
+
4307 size1 += 4
+
4308
+
4309 Buffer.write(this.receiveBuffer.data, offset0, messageSize.toUInt())
+
4310 offset0 += 4
+
4311 offset1 += 4
+
4312
+
4313 @Suppress("UNUSED_VALUE")
+
4314 messageSizeCopied = true
+
4315 }
+
4316 return
+
4317 }
+
4318
+
4319 if (messageBuffer != null)
+
4320 {
+
4321 @Suppress("ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE")
+
4322 val fbeStructSize: Long
+
4323 val fbeStructType: Long
+
4324
+
4325 // Read the message parameters
+
4326 if (final)
+
4327 {
+
4328 @Suppress("UNUSED_VALUE")
+
4329 fbeStructSize = Buffer.readUInt32(messageBuffer, messageOffset).toLong()
+
4330 fbeStructType = Buffer.readUInt32(messageBuffer, messageOffset + 4).toLong()
+
4331 }
+
4332 else
+
4333 {
+
4334 val fbeStructOffset = Buffer.readUInt32(messageBuffer, messageOffset + 4).toLong()
+
4335 @Suppress("UNUSED_VALUE")
+
4336 fbeStructSize = Buffer.readUInt32(messageBuffer, messageOffset + fbeStructOffset).toLong()
+
4337 fbeStructType = Buffer.readUInt32(messageBuffer, messageOffset + fbeStructOffset + 4).toLong()
+
4338 }
+
4339
+
4340 // Handle the message
+
4341 onReceive(fbeStructType, messageBuffer, messageOffset, messageSize)
+
4342 }
+
4343
+
4344 // Reset the storage buffer
+
4345 this.receiveBuffer.reset()
+
4346
+
4347 // Refresh the storage buffer
+
4348 offset0 = this.receiveBuffer.offset
+
4349 offset1 = this.receiveBuffer.size
+
4350 size1 = this.receiveBuffer.size
+
4351 }
+
4352 }
+
4353
+
4354 // Receive message handler
+
4355 abstract fun onReceive(type: Long, buffer: ByteArray, offset: Long, size: Long): Boolean
+
4356}
+
4357)CODE";
+
4358
+
4359 // Prepare code template
+
4360 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
4361
+
4362 Write(code);
+
4363
+
4364 // Generate footer
+
4365 GenerateFooter();
+
4366
+
4367 // Store the file
+
4368 WriteEnd();
+
4369 Store(file);
+
4370}
+
4371
+
4372void GeneratorKotlin::GenerateFBEClientListener(const std::string& domain, const std::string& package)
+
4373{
+
4374 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
4375
+
4376 // Generate the file
+
4377 CppCommon::Path file = path / "IClientListener.kt";
+
4378 WriteBegin();
+
4379
+
4380 // Generate headers
+
4381 GenerateHeader("FBE");
+
4382 GenerateImports(domain, package);
+
4383
+
4384 std::string code = R"CODE(
+
4385// Fast Binary Encoding base client listener interface
+
4386interface IClientListener : ISenderListener, IReceiverListener
+
4387{
+
4388}
+
4389)CODE";
+
4390
+
4391 // Prepare code template
+
4392 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
4393
+
4394 Write(code);
+
4395
+
4396 // Generate footer
+
4397 GenerateFooter();
+
4398
+
4399 // Store the file
+
4400 WriteEnd();
+
4401 Store(file);
+
4402}
+
4403
+
4404void GeneratorKotlin::GenerateFBEJson(const std::string& domain, const std::string& package)
+
4405{
+
4406 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
4407
+
4408 // Generate the file
+
4409 CppCommon::Path file = path / "Json.kt";
+
4410 WriteBegin();
+
4411
+
4412 // Generate headers
+
4413 GenerateHeader("FBE");
+
4414 GenerateImports(domain, package);
+
4415
+
4416 std::string code = R"CODE(
+
4417internal class BytesJson : com.google.gson.JsonSerializer<ByteArray>, com.google.gson.JsonDeserializer<ByteArray>
+
4418{
+
4419 override fun serialize(src: ByteArray, typeOfSrc: java.lang.reflect.Type, context: com.google.gson.JsonSerializationContext): com.google.gson.JsonElement
+
4420 {
+
4421 return com.google.gson.JsonPrimitive(java.util.Base64.getEncoder().encodeToString(src))
+
4422 }
+
4423
+
4424 @Throws(com.google.gson.JsonParseException::class)
+
4425 override fun deserialize(json: com.google.gson.JsonElement, type: java.lang.reflect.Type, context: com.google.gson.JsonDeserializationContext): ByteArray
+
4426 {
+
4427 return java.util.Base64.getDecoder().decode(json.asString)
+
4428 }
+
4429}
+
4430
+
4431internal class CharacterJson : com.google.gson.JsonSerializer<Char>, com.google.gson.JsonDeserializer<Char>
+
4432{
+
4433 override fun serialize(src: Char, typeOfSrc: java.lang.reflect.Type, context: com.google.gson.JsonSerializationContext): com.google.gson.JsonElement
+
4434 {
+
4435 return com.google.gson.JsonPrimitive(src.code)
+
4436 }
+
4437
+
4438 @Throws(com.google.gson.JsonParseException::class)
+
4439 override fun deserialize(json: com.google.gson.JsonElement, type: java.lang.reflect.Type, context: com.google.gson.JsonDeserializationContext): Char
+
4440 {
+
4441 return json.asLong.toInt().toChar()
+
4442 }
+
4443}
+
4444
+
4445_TIMESTAMP_CLASS_
+
4446
+
4447internal class BigDecimalJson : com.google.gson.JsonSerializer<java.math.BigDecimal>, com.google.gson.JsonDeserializer<java.math.BigDecimal>
+
4448{
+
4449 override fun serialize(src: java.math.BigDecimal, typeOfSrc: java.lang.reflect.Type, context: com.google.gson.JsonSerializationContext): com.google.gson.JsonElement
+
4450 {
+
4451 return com.google.gson.JsonPrimitive(src.toPlainString())
+
4452 }
+
4453
+
4454 @Throws(com.google.gson.JsonParseException::class)
+
4455 override fun deserialize(json: com.google.gson.JsonElement, type: java.lang.reflect.Type, context: com.google.gson.JsonDeserializationContext): java.math.BigDecimal
+
4456 {
+
4457 return java.math.BigDecimal(json.asJsonPrimitive.asString)
+
4458 }
+
4459}
+
4460
+
4461internal class UUIDJson : com.google.gson.JsonSerializer<java.util.UUID>, com.google.gson.JsonDeserializer<java.util.UUID>
+
4462{
+
4463 override fun serialize(src: java.util.UUID, typeOfSrc: java.lang.reflect.Type, context: com.google.gson.JsonSerializationContext): com.google.gson.JsonElement
+
4464 {
+
4465 return com.google.gson.JsonPrimitive(src.toString())
+
4466 }
+
4467
+
4468 @Throws(com.google.gson.JsonParseException::class)
+
4469 override fun deserialize(json: com.google.gson.JsonElement, type: java.lang.reflect.Type, context: com.google.gson.JsonDeserializationContext): java.util.UUID {
+
4470 return java.util.UUID.fromString(json.asJsonPrimitive.asString)
+
4471 }
+
4472}
+
4473
+
4474internal class UByteNullableJson : com.google.gson.JsonSerializer<UByte?>, com.google.gson.JsonDeserializer<UByte?>
+
4475{
+
4476 override fun serialize(src: UByte?, typeOfSrc: java.lang.reflect.Type, context: com.google.gson.JsonSerializationContext): com.google.gson.JsonElement
+
4477 {
+
4478 if (src == null)
+
4479 return com.google.gson.JsonNull.INSTANCE
+
4480
+
4481 return com.google.gson.JsonPrimitive(src.toLong())
+
4482 }
+
4483
+
4484 @Throws(com.google.gson.JsonParseException::class)
+
4485 override fun deserialize(json: com.google.gson.JsonElement, type: java.lang.reflect.Type, context: com.google.gson.JsonDeserializationContext): UByte?
+
4486 {
+
4487 if (json.isJsonNull)
+
4488 return null
+
4489
+
4490 return json.asLong.toUByte()
+
4491 }
+
4492}
+
4493
+
4494internal class UShortNullableJson : com.google.gson.JsonSerializer<UShort?>, com.google.gson.JsonDeserializer<UShort?>
+
4495{
+
4496 override fun serialize(src: UShort?, typeOfSrc: java.lang.reflect.Type, context: com.google.gson.JsonSerializationContext): com.google.gson.JsonElement
+
4497 {
+
4498 if (src == null)
+
4499 return com.google.gson.JsonNull.INSTANCE
+
4500
+
4501 return com.google.gson.JsonPrimitive(src.toLong())
+
4502 }
+
4503
+
4504 @Throws(com.google.gson.JsonParseException::class)
+
4505 override fun deserialize(json: com.google.gson.JsonElement, type: java.lang.reflect.Type, context: com.google.gson.JsonDeserializationContext): UShort?
+
4506 {
+
4507 if (json.isJsonNull)
+
4508 return null
+
4509
+
4510 return json.asLong.toUShort()
+
4511 }
+
4512}
+
4513
+
4514internal class UIntNullableJson : com.google.gson.JsonSerializer<UInt?>, com.google.gson.JsonDeserializer<UInt?>
+
4515{
+
4516 override fun serialize(src: UInt?, typeOfSrc: java.lang.reflect.Type, context: com.google.gson.JsonSerializationContext): com.google.gson.JsonElement
+
4517 {
+
4518 if (src == null)
+
4519 return com.google.gson.JsonNull.INSTANCE
+
4520
+
4521 return com.google.gson.JsonPrimitive(src.toLong())
+
4522 }
+
4523
+
4524 @Throws(com.google.gson.JsonParseException::class)
+
4525 override fun deserialize(json: com.google.gson.JsonElement, type: java.lang.reflect.Type, context: com.google.gson.JsonDeserializationContext): UInt?
+
4526 {
+
4527 if (json.isJsonNull)
+
4528 return null
+
4529
+
4530 return json.asLong.toUInt()
+
4531 }
+
4532}
+
4533
+
4534internal class ULongNullableJson : com.google.gson.JsonSerializer<ULong?>, com.google.gson.JsonDeserializer<ULong?>
+
4535{
+
4536 override fun serialize(src: ULong?, typeOfSrc: java.lang.reflect.Type, context: com.google.gson.JsonSerializationContext): com.google.gson.JsonElement
+
4537 {
+
4538 if (src == null)
+
4539 return com.google.gson.JsonNull.INSTANCE
+
4540
+
4541 return com.google.gson.JsonPrimitive(src.toLong())
+
4542 }
+
4543
+
4544 @Throws(com.google.gson.JsonParseException::class)
+
4545 override fun deserialize(json: com.google.gson.JsonElement, type: java.lang.reflect.Type, context: com.google.gson.JsonDeserializationContext): ULong?
+
4546 {
+
4547 if (json.isJsonNull)
+
4548 return null
+
4549
+
4550 return json.asLong.toULong()
+
4551 }
+
4552}
+
4553
+
4554// Fast Binary Encoding base JSON engine
+
4555@Suppress("MemberVisibilityCanBePrivate")
+
4556object Json
+
4557{
+
4558 // Get the JSON engine
+
4559 val engine: com.google.gson.Gson = register(com.google.gson.GsonBuilder()).create()
+
4560
+
4561 fun register(builder: com.google.gson.GsonBuilder): com.google.gson.GsonBuilder
+
4562 {
+
4563 builder.serializeNulls()
+
4564 builder.registerTypeAdapter(ByteArray::class.java, BytesJson())
+
4565 builder.registerTypeAdapter(Char::class.java, CharacterJson())
+
4566 builder.registerTypeAdapter(Character::class.java, CharacterJson())
+
4567 _TIMESTAMP_REGISTER_
+
4568 builder.registerTypeAdapter(java.math.BigDecimal::class.java, BigDecimalJson())
+
4569 builder.registerTypeAdapter(java.util.UUID::class.java, UUIDJson())
+
4570 builder.registerTypeAdapter(kotlin.UByte::class.java, UByteNullableJson())
+
4571 builder.registerTypeAdapter(kotlin.UShort::class.java, UShortNullableJson())
+
4572 builder.registerTypeAdapter(kotlin.UInt::class.java, UIntNullableJson())
+
4573 builder.registerTypeAdapter(kotlin.ULong::class.java, ULongNullableJson())
+
4574 return builder
+
4575 }
+
4576}
+
4577)CODE";
+
4578
+
4579 std::string timestamp_class;
+
4580 std::string timestamp_register;
+
4581
+
4582 if (Version() < 8)
+
4583 {
+
4584 timestamp_class = R"CODE(internal class DateJson : com.google.gson.JsonSerializer<java.util.Date>, com.google.gson.JsonDeserializer<java.util.Date>
+
4585{
+
4586 override fun serialize(src: java.util.Date, typeOfSrc: java.lang.reflect.Type, context: com.google.gson.JsonSerializationContext): com.google.gson.JsonElement
+
4587 {
+
4588 val nanoseconds = src.time * 1000000
+
4589 return com.google.gson.JsonPrimitive(nanoseconds)
+
4590 }
+
4591
+
4592 @Throws(com.google.gson.JsonParseException::class)
+
4593 override fun deserialize(json: com.google.gson.JsonElement, type: java.lang.reflect.Type, context: com.google.gson.JsonDeserializationContext): java.util.Date
+
4594 {
+
4595 val nanoseconds = json.asJsonPrimitive.asLong
+
4596 return java.util.Date(nanoseconds / 1000000)
+
4597 }
+
4598})CODE";
+
4599 timestamp_register = "builder.registerTypeAdapter(java.util.Date::class.java, DateJson())";
+
4600 }
+
4601 else
+
4602 {
+
4603 timestamp_class = R"CODE(internal class InstantJson : com.google.gson.JsonSerializer<java.time.Instant>, com.google.gson.JsonDeserializer<java.time.Instant>
+
4604{
+
4605 override fun serialize(src: java.time.Instant, typeOfSrc: java.lang.reflect.Type, context: com.google.gson.JsonSerializationContext): com.google.gson.JsonElement
+
4606 {
+
4607 val nanoseconds = src.epochSecond * 1000000000 + src.nano
+
4608 return com.google.gson.JsonPrimitive(nanoseconds)
+
4609 }
+
4610
+
4611 @Throws(com.google.gson.JsonParseException::class)
+
4612 override fun deserialize(json: com.google.gson.JsonElement, type: java.lang.reflect.Type, context: com.google.gson.JsonDeserializationContext): java.time.Instant
+
4613 {
+
4614 val nanoseconds = json.asJsonPrimitive.asLong
+
4615 return java.time.Instant.ofEpochSecond(nanoseconds / 1000000000, nanoseconds % 1000000000)
+
4616 }
+
4617})CODE";
+
4618 timestamp_register = "builder.registerTypeAdapter(java.time.Instant::class.java, InstantJson())";
+
4619 }
+
4620
+
4621 // Prepare code template
+
4622 code = std::regex_replace(code, std::regex("_TIMESTAMP_CLASS_"), timestamp_class);
+
4623 code = std::regex_replace(code, std::regex("_TIMESTAMP_REGISTER_"), timestamp_register);
+
4624 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
4625
+
4626 Write(code);
+
4627
+
4628 // Generate footer
+
4629 GenerateFooter();
+
4630
+
4631 // Store the file
+
4632 WriteEnd();
+
4633 Store(file);
+
4634}
+
4635
+
4636void GeneratorKotlin::GenerateContainers(const std::shared_ptr<Package>& p, bool final)
+
4637{
+
4638 std::string domain = (p->domain && !p->domain->empty()) ? (*p->domain + ".") : "";
+
4639 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, *p->name);
+
4640
+
4641 // Create package path
+
4642 CppCommon::Directory::CreateTree(path);
+
4643
+
4644 if (p->body)
+
4645 {
+
4646 // Check all structs in the package
+
4647 for (const auto& s : p->body->structs)
+
4648 {
+
4649 if (s->body)
+
4650 {
+
4651 // Check all fields in the struct
+
4652 for (const auto& field : s->body->fields)
+
4653 {
+
4654 if (field->array)
+
4655 {
+
4656 if (final)
+
4657 GenerateFBEFinalModelArray(domain, *p->name, (field->optional ? "Optional" : "") + ConvertTypeFieldName(*field->type), ConvertTypeFieldType(domain, *field->type, field->optional), *field->type, field->optional, ConvertTypeFieldDeclaration(domain, *field->type, field->optional, final));
+
4658 else
+
4659 GenerateFBEFieldModelArray(domain, *p->name, (field->optional ? "Optional" : "") + ConvertTypeFieldName(*field->type), ConvertTypeFieldType(domain, *field->type, field->optional), *field->type, field->optional, ConvertTypeFieldDeclaration(domain, *field->type, field->optional, final));
+
4660 }
+
4661 if (field->vector || field->list || field->set)
+
4662 {
+
4663 if (final)
+
4664 GenerateFBEFinalModelVector(domain, *p->name, (field->optional ? "Optional" : "") + ConvertTypeFieldName(*field->type), ConvertTypeFieldType(domain, *field->type, field->optional), ConvertTypeFieldDeclaration(domain, *field->type, field->optional, final));
+
4665 else
+
4666 GenerateFBEFieldModelVector(domain, *p->name, (field->optional ? "Optional" : "") + ConvertTypeFieldName(*field->type), ConvertTypeFieldType(domain, *field->type, field->optional), ConvertTypeFieldDeclaration(domain, *field->type, field->optional, final));
+
4667 }
+
4668 if (field->map || field->hash)
+
4669 {
+
4670 if (final)
+
4671 GenerateFBEFinalModelMap(domain, *p->name, ConvertTypeFieldName(*field->key), ConvertTypeFieldType(domain, *field->key, false), ConvertTypeFieldDeclaration(domain, *field->key, false, final), (field->optional ? "Optional" : "") + ConvertTypeFieldName(*field->type), ConvertTypeFieldType(domain, *field->type, field->optional), ConvertTypeFieldDeclaration(domain, *field->type, field->optional, final));
+
4672 else
+
4673 GenerateFBEFieldModelMap(domain, *p->name, ConvertTypeFieldName(*field->key), ConvertTypeFieldType(domain, *field->key, false), ConvertTypeFieldDeclaration(domain, *field->key, false, final), (field->optional ? "Optional" : "") + ConvertTypeFieldName(*field->type), ConvertTypeFieldType(domain, *field->type, field->optional), ConvertTypeFieldDeclaration(domain, *field->type, field->optional, final));
+
4674 }
+
4675 if (field->optional)
+
4676 {
+
4677 if (final)
+
4678 GenerateFBEFinalModelOptional(domain, *p->name, ConvertTypeFieldName(*field->type), ConvertTypeFieldType(domain, *field->type, field->optional), ConvertTypeFieldDeclaration(domain, *field->type, false, final));
+
4679 else
+
4680 GenerateFBEFieldModelOptional(domain, *p->name, ConvertTypeFieldName(*field->type), ConvertTypeFieldType(domain, *field->type, field->optional), ConvertTypeFieldDeclaration(domain, *field->type, false, final));
+
4681 }
+
4682 }
+
4683 }
+
4684 }
+
4685 }
+
4686}
+
4687
+
4688void GeneratorKotlin::GeneratePackage(const std::shared_ptr<Package>& p)
+
4689{
+
4690 std::string domain = (p->domain && !p->domain->empty()) ? (*p->domain + ".") : "";
+
4691 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, *p->name);
+
4692
+
4693 // Create package path
+
4694 CppCommon::Directory::CreateTree(path);
+
4695
+
4696 // Generate namespace
+
4697 if (p->body)
+
4698 {
+
4699 // Generate child enums
+
4700 for (const auto& child_e : p->body->enums)
+
4701 GenerateEnum(p, child_e, path);
+
4702
+
4703 // Generate child flags
+
4704 for (const auto& child_f : p->body->flags)
+
4705 GenerateFlags(p, child_f, path);
+
4706
+
4707 // Generate child structs
+
4708 for (const auto& child_s : p->body->structs)
+
4709 GenerateStruct(p, child_s, path);
+
4710 }
+
4711
+
4712 // Generate containers
+
4713 GenerateContainers(p, false);
+
4714 if (Final())
+
4715 GenerateContainers(p, true);
+
4716
+
4717 // Generate protocol
+
4718 if (Proto())
+
4719 {
+
4720 // Generate protocol version
+
4721 GenerateProtocolVersion(p);
+
4722
+
4723 // Generate sender & receiver
+
4724 GenerateSender(p, false);
+
4725 GenerateSenderListener(p, false);
+
4726 GenerateReceiver(p, false);
+
4727 GenerateReceiverListener(p, false);
+
4728 GenerateProxy(p, false);
+
4729 GenerateProxyListener(p, false);
+
4730 GenerateClient(p, false);
+
4731 GenerateClientListener(p, false);
+
4732 if (Final())
+
4733 {
+
4734 GenerateSender(p, true);
+
4735 GenerateSenderListener(p, true);
+
4736 GenerateReceiver(p, true);
+
4737 GenerateReceiverListener(p, true);
+
4738 GenerateClient(p, true);
+
4739 GenerateClientListener(p, true);
+
4740 }
+
4741 }
+
4742
+
4743 // Generate JSON engine
+
4744 if (JSON())
+
4745 GenerateJson(p);
+
4746}
+
4747
+
4748void GeneratorKotlin::GenerateEnum(const std::shared_ptr<Package>& p, const std::shared_ptr<EnumType>& e, const CppCommon::Path& path)
+
4749{
+
4750 std::string enum_name = *e->name + "Enum";
+
4751
+
4752 // Generate the output file
+
4753 CppCommon::Path output = path / (enum_name + ".kt");
+
4754 WriteBegin();
+
4755
+
4756 // Generate enum header
+
4757 GenerateHeader(CppCommon::Path(_input).filename().string());
+
4758 GenerateImports(p);
+
4759
+
4760 std::string enum_type = (e->base && !e->base->empty()) ? *e->base : "int32";
+
4761 std::string enum_base_type = ConvertEnumType(enum_type);
+
4762 std::string enum_mapping_type = ConvertEnumBase(enum_type);
+
4763 std::string enum_to = ConvertEnumTo(enum_type);
+
4764
+
4765 // Generate enum body
+
4766 WriteLine();
+
4767 WriteLineIndent("@Suppress(\"EnumEntryName\", \"MemberVisibilityCanBePrivate\", \"RemoveRedundantCallsOfConversionMethods\")");
+
4768 WriteLineIndent("enum class " + enum_name);
+
4769 WriteLineIndent("{");
+
4770 Indent(1);
+
4771 if (e->body)
+
4772 {
+
4773 int index = 0;
+
4774 bool first = true;
+
4775 std::string last = ConvertEnumConstant(enum_type, enum_type, "0", false);
+
4776 for (const auto& value : e->body->values)
+
4777 {
+
4778 WriteIndent(std::string(first ? "" : ", ") + *value->name + "(");
+
4779 if (value->value)
+
4780 {
+
4781 if (value->value->constant && !value->value->constant->empty())
+
4782 {
+
4783 index = 0;
+
4784 last = ConvertEnumConstant(enum_type, enum_type, *value->value->constant, false);
+
4785 Write(last + " + " + std::to_string(index++) + (IsUnsignedType(enum_type) ? "u" : ""));
+
4786 }
+
4787 else if (value->value->reference && !value->value->reference->empty())
+
4788 {
+
4789 index = 0;
+
4790 last = ConvertEnumConstant(enum_type, "", *value->value->reference, false);
+
4791 Write(last);
+
4792 }
+
4793 }
+
4794 else
+
4795 Write(last + " + " + std::to_string(index++) + (IsUnsignedType(enum_type) ? "u" : ""));
+
4796 WriteLine(")");
+
4797 first = false;
+
4798 }
+
4799 WriteLineIndent(";");
+
4800 WriteLine();
+
4801 }
+
4802
+
4803 // Generate enum value
+
4804 WriteLineIndent("var raw: " + enum_mapping_type + " = " + ConvertEnumConstant(enum_type, enum_type, "0", false));
+
4805 Indent(1);
+
4806 WriteLineIndent("private set");
+
4807 Indent(-1);
+
4808
+
4809 // Generate enum constructors
+
4810 WriteLine();
+
4811 if ((enum_type == "char") || (enum_type == "wchar"))
+
4812 WriteLineIndent("constructor(value: Char) { this.raw = value.code" + enum_to + " }");
+
4813 if (IsUnsignedType(enum_type))
+
4814 {
+
4815 WriteLineIndent("constructor(value: UByte) { this.raw = value" + enum_to + " }");
+
4816 WriteLineIndent("constructor(value: UShort) { this.raw = value" + enum_to + " }");
+
4817 WriteLineIndent("constructor(value: UInt) { this.raw = value" + enum_to + " }");
+
4818 WriteLineIndent("constructor(value: ULong) { this.raw = value" + enum_to + " }");
+
4819 }
+
4820 else
+
4821 {
+
4822 WriteLineIndent("constructor(value: Byte) { this.raw = value" + enum_to + " }");
+
4823 WriteLineIndent("constructor(value: Short) { this.raw = value" + enum_to + " }");
+
4824 WriteLineIndent("constructor(value: Int) { this.raw = value" + enum_to + " }");
+
4825 WriteLineIndent("constructor(value: Long) { this.raw = value" + enum_to + " }");
+
4826 }
+
4827 WriteLineIndent("constructor(value: " + enum_name + ") { this.raw = value.raw }");
+
4828
+
4829 // Generate enum toString() method
+
4830 WriteLine();
+
4831 WriteLineIndent("override fun toString(): String");
+
4832 WriteLineIndent("{");
+
4833 Indent(1);
+
4834 if (e->body && !e->body->values.empty())
+
4835 {
+
4836 for (const auto& value : e->body->values)
+
4837 WriteLineIndent("if (this == " + *value->name + ")" + " return \"" + *value->name + "\"");
+
4838 WriteLineIndent("return \"<unknown>\"");
+
4839 }
+
4840 else
+
4841 WriteLineIndent("return \"<empty>\"");
+
4842 Indent(-1);
+
4843 WriteLineIndent("}");
+
4844
+
4845 // Generate enum mapping
+
4846 WriteLine();
+
4847 WriteLineIndent("companion object");
+
4848 WriteLineIndent("{");
+
4849 Indent(1);
+
4850 WriteLineIndent("private val mapping = java.util.HashMap<" + enum_mapping_type + ", " + enum_name + ">()");
+
4851 WriteLine();
+
4852 WriteLineIndent("init");
+
4853 WriteLineIndent("{");
+
4854 Indent(1);
+
4855 WriteLineIndent("for (value in " + enum_name + ".values())");
+
4856 Indent(1);
+
4857 WriteLineIndent("mapping[value.raw] = value");
+
4858 Indent(-1);
+
4859 Indent(-1);
+
4860 WriteLineIndent("}");
+
4861
+
4862 // Generate enum mapValue() method
+
4863 WriteLine();
+
4864 WriteLineIndent("fun mapValue(value: " + enum_mapping_type + "): " + enum_name + "?" +" { return mapping[value] }");
+
4865
+
4866 Indent(-1);
+
4867 WriteLineIndent("}");
+
4868
+
4869 Indent(-1);
+
4870 WriteLineIndent("}");
+
4871
+
4872 // Generate enum footer
+
4873 GenerateFooter();
+
4874
+
4875 // Store the output file
+
4876 WriteEnd();
+
4877 Store(output);
+
4878
+
4879 // Generate enum wrapper class
+
4880 GenerateEnumClass(p, e, path);
+
4881
+
4882 // Generate enum JSON adapter
+
4883 if (JSON())
+
4884 GenerateEnumJson(p, e);
+
4885
+
4886 std::string domain = (p->domain && !p->domain->empty()) ? (*p->domain + ".") : "";
+
4887
+
4888 // Generate enum field model
+
4889 GenerateFBEFieldModelEnumFlags(domain, *p->name, *e->name, enum_type);
+
4890
+
4891 // Generate enum final model
+
4892 if (Final())
+
4893 GenerateFBEFinalModelEnumFlags(domain, *p->name, *e->name, enum_type);
+
4894}
+
4895
+
4896void GeneratorKotlin::GenerateEnumClass(const std::shared_ptr<Package>& p, const std::shared_ptr<EnumType>& e, const CppCommon::Path& path)
+
4897{
+
4898 std::string enum_name = *e->name;
+
4899 std::string enum_type_name = *e->name + "Enum";
+
4900
+
4901 // Generate the output file
+
4902 CppCommon::Path output = path / (enum_name + ".kt");
+
4903 WriteBegin();
+
4904
+
4905 // Generate enum class header
+
4906 GenerateHeader(CppCommon::Path(_input).filename().string());
+
4907 GenerateImports(p);
+
4908
+
4909 std::string enum_type = (e->base && !e->base->empty()) ? *e->base : "int32";
+
4910 std::string enum_base_type = ConvertEnumType(enum_type);
+
4911 std::string enum_to = ConvertEnumTo(enum_type);
+
4912
+
4913 // Generate enum class body
+
4914 WriteLine();
+
4915 WriteLineIndent("@Suppress(\"MemberVisibilityCanBePrivate\", \"RemoveRedundantCallsOfConversionMethods\")");
+
4916 WriteLineIndent("class " + enum_name + " : Comparable<" + enum_name + ">");
+
4917 WriteLineIndent("{");
+
4918 Indent(1);
+
4919 if (e->body)
+
4920 {
+
4921 WriteLineIndent("companion object");
+
4922 WriteLineIndent("{");
+
4923 Indent(1);
+
4924 for (const auto& value : e->body->values)
+
4925 WriteLineIndent("val " + *value->name + " = " + enum_name + "(" + enum_type_name + "." + *value->name + ")");
+
4926 Indent(-1);
+
4927 WriteLineIndent("}");
+
4928 WriteLine();
+
4929 }
+
4930
+
4931 // Generate enum class value
+
4932 WriteLineIndent("var value: " + enum_type_name + "?" + " = " + enum_type_name + ".values()[0]");
+
4933 Indent(1);
+
4934 WriteLineIndent("private set");
+
4935 Indent(-1);
+
4936 WriteLine();
+
4937
+
4938 // Generate enum raw value
+
4939 WriteLineIndent("val raw: " + enum_base_type);
+
4940 Indent(1);
+
4941 WriteLineIndent("get() = value!!.raw");
+
4942 Indent(-1);
+
4943 WriteLine();
+
4944
+
4945 // Generate enum class constructors
+
4946 WriteLineIndent("constructor()");
+
4947 WriteLineIndent("constructor(value: " + enum_base_type + ") { setEnum(value) }");
+
4948 WriteLineIndent("constructor(value: " + enum_type_name + ") { setEnum(value) }");
+
4949 WriteLineIndent("constructor(value: " + enum_name + ") { setEnum(value) }");
+
4950 WriteLine();
+
4951
+
4952 // Generate enum class setDefault() method
+
4953 WriteLineIndent("fun setDefault() { setEnum(0" + enum_to + ") }");
+
4954 WriteLine();
+
4955
+
4956 // Generate enum class setEnum() methods
+
4957 WriteLineIndent("fun setEnum(value: " + enum_base_type + ") { this.value = " + enum_type_name + ".mapValue(value) }");
+
4958 WriteLineIndent("fun setEnum(value: " + enum_type_name + ") { this.value = value }");
+
4959 WriteLineIndent("fun setEnum(value: " + enum_name + ") { this.value = value.value }");
+
4960
+
4961 // Generate enum class compareTo() method
+
4962 WriteLine();
+
4963 WriteLineIndent("override fun compareTo(other: " + enum_name + "): Int");
+
4964 WriteLineIndent("{");
+
4965 Indent(1);
+
4966 WriteLineIndent("if (value == null)");
+
4967 Indent(1);
+
4968 WriteLineIndent("return -1");
+
4969 Indent(-1);
+
4970 WriteLineIndent("if (other.value == null)");
+
4971 Indent(1);
+
4972 WriteLineIndent("return 1");
+
4973 Indent(-1);
+
4974 WriteLineIndent("return (value!!.raw - other.value!!.raw).toInt()");
+
4975 Indent(-1);
+
4976 WriteLineIndent("}");
+
4977
+
4978 // Generate enum class equals() method
+
4979 WriteLine();
+
4980 WriteLineIndent("override fun equals(other: Any?): Boolean");
+
4981 WriteLineIndent("{");
+
4982 Indent(1);
+
4983 WriteLineIndent("if (other == null)");
+
4984 Indent(1);
+
4985 WriteLineIndent("return false");
+
4986 Indent(-1);
+
4987 WriteLine();
+
4988 WriteLineIndent("if (!" + enum_name + "::class.java.isAssignableFrom(other.javaClass))");
+
4989 Indent(1);
+
4990 WriteLineIndent("return false");
+
4991 Indent(-1);
+
4992 WriteLine();
+
4993 WriteLineIndent("val enm = other as " + enum_name + "? ?: return false");
+
4994 WriteLine();
+
4995 WriteLineIndent("if (enm.value == null)");
+
4996 Indent(1);
+
4997 WriteLineIndent("return false");
+
4998 Indent(-1);
+
4999 WriteLineIndent("if (value!!.raw != enm.value!!.raw)");
+
5000 Indent(1);
+
5001 WriteLineIndent("return false");
+
5002 Indent(-1);
+
5003 WriteLineIndent("return true");
+
5004 Indent(-1);
+
5005 WriteLineIndent("}");
+
5006
+
5007 // Generate enum class hashCode() method
+
5008 WriteLine();
+
5009 WriteLineIndent("override fun hashCode(): Int");
+
5010 WriteLineIndent("{");
+
5011 Indent(1);
+
5012 WriteLineIndent("var hash = 17");
+
5013 WriteLineIndent("hash = hash * 31 + if (value != null) value!!.hashCode() else 0");
+
5014 WriteLineIndent("return hash");
+
5015 Indent(-1);
+
5016 WriteLineIndent("}");
+
5017
+
5018 // Generate enum class toString() method
+
5019 WriteLine();
+
5020 WriteLineIndent("override fun toString(): String");
+
5021 WriteLineIndent("{");
+
5022 Indent(1);
+
5023 WriteLineIndent("return if (value != null) value!!.toString() else \"<unknown>\"");
+
5024 Indent(-1);
+
5025 WriteLineIndent("}");
+
5026
+
5027 Indent(-1);
+
5028 WriteLineIndent("}");
+
5029
+
5030 // Generate enum class footer
+
5031 GenerateFooter();
+
5032
+
5033 // Store the output file
+
5034 WriteEnd();
+
5035 Store(output);
+
5036}
+
5037
+
5038void GeneratorKotlin::GenerateEnumJson(const std::shared_ptr<Package>& p, const std::shared_ptr<EnumType>& e)
+
5039{
+
5040 std::string domain = (p->domain && !p->domain->empty()) ? (*p->domain + ".") : "";
+
5041 std::string package = *p->name;
+
5042 std::string enum_name = domain + package + "." + *e->name;
+
5043 std::string adapter_name = *e->name + "Json";
+
5044
+
5045 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "fbe";
+
5046
+
5047 // Create package path
+
5048 CppCommon::Directory::CreateTree(path);
+
5049
+
5050 // Generate the output file
+
5051 CppCommon::Path output = path / (adapter_name + ".kt");
+
5052 WriteBegin();
+
5053
+
5054 // Generate headers
+
5055 GenerateHeader(CppCommon::Path(_input).filename().string());
+
5056 GenerateImports(domain, package + ".fbe");
+
5057
+
5058 std::string enum_type = (e->base && !e->base->empty()) ? *e->base : "int32";
+
5059
+
5060 // Generate JSON adapter body
+
5061 WriteLine();
+
5062 WriteLineIndent("class " + adapter_name + " : com.google.gson.JsonSerializer<" + enum_name + ">, com.google.gson.JsonDeserializer<" + enum_name + ">");
+
5063 WriteLineIndent("{");
+
5064 Indent(1);
+
5065
+
5066 // Generate JSON adapter serialize() method
+
5067 WriteLineIndent("override fun serialize(src: " + enum_name + ", typeOfSrc: java.lang.reflect.Type, context: com.google.gson.JsonSerializationContext): com.google.gson.JsonElement");
+
5068 WriteLineIndent("{");
+
5069 Indent(1);
+
5070 WriteLineIndent("return com.google.gson.JsonPrimitive(src.raw" + ConvertEnumFrom(enum_type) + ")");
+
5071 Indent(-1);
+
5072 WriteLineIndent("}");
+
5073
+
5074 // Generate JSON adapter deserialize() method
+
5075 WriteLine();
+
5076 WriteLineIndent("@Throws(com.google.gson.JsonParseException::class)");
+
5077 WriteLineIndent("override fun deserialize(json: com.google.gson.JsonElement, type: java.lang.reflect.Type, context: com.google.gson.JsonDeserializationContext): " + enum_name);
+
5078 WriteLineIndent("{");
+
5079 Indent(1);
+
5080 WriteLineIndent("return " + enum_name + "(json.asJsonPrimitive." + ConvertEnumGet(enum_type) + ")");
+
5081 Indent(-1);
+
5082 WriteLineIndent("}");
+
5083
+
5084 Indent(-1);
+
5085 WriteLineIndent("}");
+
5086
+
5087 // Generate JSON adapter footer
+
5088 GenerateFooter();
+
5089
+
5090 // Store the output file
+
5091 WriteEnd();
+
5092 Store(output);
+
5093}
+
5094
+
5095void GeneratorKotlin::GenerateFlags(const std::shared_ptr<Package>& p, const std::shared_ptr<FlagsType>& f, const CppCommon::Path& path)
+
5096{
+
5097 std::string flags_name = *f->name + "Enum";
+
5098
+
5099 // Generate the output file
+
5100 CppCommon::Path output = path / (flags_name + ".kt");
+
5101 WriteBegin();
+
5102
+
5103 // Generate flags header
+
5104 GenerateHeader(CppCommon::Path(_input).filename().string());
+
5105 GenerateImports(p);
+
5106
+
5107 std::string flags_type = (f->base && !f->base->empty()) ? *f->base : "int32";
+
5108 std::string flags_base_type = ConvertEnumType(flags_type);
+
5109 std::string flags_mapping_type = ConvertEnumBase(flags_type);
+
5110 std::string flags_int = ConvertEnumFlags(flags_type);
+
5111 std::string flags_to = ConvertEnumTo(flags_type);
+
5112
+
5113 // Generate flags body
+
5114 WriteLine();
+
5115 WriteLineIndent("@Suppress(\"EnumEntryName\", \"MemberVisibilityCanBePrivate\", \"RemoveRedundantCallsOfConversionMethods\")");
+
5116 WriteLineIndent("enum class " + flags_name);
+
5117 WriteLineIndent("{");
+
5118 Indent(1);
+
5119 if (f->body)
+
5120 {
+
5121 bool first = true;
+
5122 for (const auto& value : f->body->values)
+
5123 {
+
5124 WriteIndent(std::string(first ? "" : ", ") + *value->name + "(");
+
5125 if (value->value)
+
5126 {
+
5127 if (value->value->constant && !value->value->constant->empty())
+
5128 Write(ConvertEnumConstant(flags_type, flags_type, *value->value->constant, true));
+
5129 else if (value->value->reference && !value->value->reference->empty())
+
5130 Write(ConvertEnumConstant(flags_type, "", *value->value->reference, true));
+
5131 }
+
5132 WriteLine(")");
+
5133 first = false;
+
5134 }
+
5135 WriteLineIndent(";");
+
5136 WriteLine();
+
5137 }
+
5138 else
+
5139 WriteIndent("unknown(0);");
+
5140
+
5141 // Generate flags class value
+
5142 WriteLineIndent("var raw: " + flags_mapping_type + " = " + ConvertEnumConstant(flags_type, flags_type, "0", false));
+
5143 Indent(1);
+
5144 WriteLineIndent("private set");
+
5145 Indent(-1);
+
5146
+
5147 // Generate flags class constructors
+
5148 WriteLine();
+
5149 if ((flags_type == "char") || (flags_type == "wchar"))
+
5150 WriteLineIndent("constructor(value: Char) { this.raw = value.code" + flags_to + " }");
+
5151 if (IsUnsignedType(flags_type))
+
5152 {
+
5153 WriteLineIndent("constructor(value: UByte) { this.raw = value" + flags_to + " }");
+
5154 WriteLineIndent("constructor(value: UShort) { this.raw = value" + flags_to + " }");
+
5155 WriteLineIndent("constructor(value: UInt) { this.raw = value" + flags_to + " }");
+
5156 WriteLineIndent("constructor(value: ULong) { this.raw = value" + flags_to + " }");
+
5157 }
+
5158 else
+
5159 {
+
5160 WriteLineIndent("constructor(value: Byte) { this.raw = value" + flags_to + " }");
+
5161 WriteLineIndent("constructor(value: Short) { this.raw = value" + flags_to + " }");
+
5162 WriteLineIndent("constructor(value: Int) { this.raw = value" + flags_to + " }");
+
5163 WriteLineIndent("constructor(value: Long) { this.raw = value" + flags_to + " }");
+
5164 }
+
5165 WriteLineIndent("constructor(value: " + flags_name + ") { this.raw = value.raw }");
+
5166
+
5167 // Generate flags hasFlags() methods
+
5168 WriteLine();
+
5169 WriteLineIndent("fun hasFlags(flags: " + flags_base_type + "): Boolean = ((raw" + flags_int + " and flags" + flags_int + ") != " + ConvertEnumConstant(flags_type, flags_type, "0", false) + ") && ((raw" + flags_int + " and flags" + flags_int + ") == flags" + flags_int + ")");
+
5170 WriteLineIndent("fun hasFlags(flags: " + flags_name + "): Boolean = hasFlags(flags.raw)");
+
5171
+
5172 // Generate flags getAllSet(), getNoneSet(), getCurrentSet() methods
+
5173 WriteLine();
+
5174 WriteLineIndent("val allSet: java.util.EnumSet<" + flags_name + "> get() = java.util.EnumSet.allOf(" + flags_name + "::class.java)");
+
5175 WriteLineIndent("val noneSet: java.util.EnumSet<" + flags_name + "> get() = java.util.EnumSet.noneOf(" + flags_name + "::class.java)");
+
5176 WriteLineIndent("val currentSet: java.util.EnumSet<" + flags_name + "> get()");
+
5177 WriteLineIndent("{");
+
5178 Indent(1);
+
5179 WriteLineIndent("val result = java.util.EnumSet.noneOf(" + flags_name + "::class.java)");
+
5180 if (f->body)
+
5181 {
+
5182 for (const auto& value : f->body->values)
+
5183 {
+
5184 WriteLineIndent("if ((raw" + flags_int + " and " + *value->name + ".raw" + flags_int + ") != " + ConvertEnumConstant(flags_type, flags_type, "0", false) + ")");
+
5185 WriteLineIndent("{");
+
5186 Indent(1);
+
5187 WriteLineIndent("result.add(" + *value->name + ")");
+
5188 Indent(-1);
+
5189 WriteLineIndent("}");
+
5190 }
+
5191 }
+
5192 WriteLineIndent("return result");
+
5193 Indent(-1);
+
5194 WriteLineIndent("}");
+
5195
+
5196 // Generate enum toString() method
+
5197 WriteLine();
+
5198 WriteLineIndent("override fun toString(): String");
+
5199 WriteLineIndent("{");
+
5200 Indent(1);
+
5201 WriteLineIndent("val sb = StringBuilder()");
+
5202 if (f->body && !f->body->values.empty())
+
5203 {
+
5204 WriteLineIndent("var first = true");
+
5205 for (const auto& value : f->body->values)
+
5206 {
+
5207 WriteLineIndent("if (hasFlags(" + *value->name + "))");
+
5208 WriteLineIndent("{");
+
5209 Indent(1);
+
5210 WriteLineIndent("sb.append(if (first) \"\" else \"|\").append(\"" + *value->name + "\")");
+
5211 WriteLineIndent("@Suppress(\"UNUSED_VALUE\")");
+
5212 WriteLineIndent("first = false");
+
5213 Indent(-1);
+
5214 WriteLineIndent("}");
+
5215 }
+
5216 }
+
5217 WriteLineIndent("return sb.toString()");
+
5218 Indent(-1);
+
5219 WriteLineIndent("}");
+
5220
+
5221 // Generate flags mapping
+
5222 WriteLine();
+
5223 WriteLineIndent("companion object");
+
5224 WriteLineIndent("{");
+
5225 Indent(1);
+
5226 WriteLineIndent("private val mapping = java.util.HashMap<" + flags_mapping_type + ", " + flags_name + ">()");
+
5227 WriteLine();
+
5228 WriteLineIndent("init");
+
5229 WriteLineIndent("{");
+
5230 Indent(1);
+
5231 WriteLineIndent("for (value in " + flags_name + ".values())");
+
5232 Indent(1);
+
5233 WriteLineIndent("mapping[value.raw] = value");
+
5234 Indent(-1);
+
5235 Indent(-1);
+
5236 WriteLineIndent("}");
+
5237
+
5238 // Generate flags mapValue() method
+
5239 WriteLine();
+
5240 WriteLineIndent("fun mapValue(value: " + flags_mapping_type + "): " + flags_name + "?" +" { return mapping[value] }");
+
5241
+
5242 Indent(-1);
+
5243 WriteLineIndent("}");
+
5244
+
5245 Indent(-1);
+
5246 WriteLineIndent("}");
+
5247
+
5248 // Generate flags footer
+
5249 GenerateFooter();
+
5250
+
5251 // Store the output file
+
5252 WriteEnd();
+
5253 Store(output);
+
5254
+
5255 // Generate flags wrapper class
+
5256 GenerateFlagsClass(p, f, path);
+
5257
+
5258 // Generate flags JSON adapter
+
5259 if (JSON())
+
5260 GenerateFlagsJson(p, f);
+
5261
+
5262 std::string domain = (p->domain && !p->domain->empty()) ? (*p->domain + ".") : "";
+
5263
+
5264 // Generate flags field model
+
5265 GenerateFBEFieldModelEnumFlags(domain, *p->name, *f->name, flags_type);
+
5266
+
5267 // Generate flags final model
+
5268 if (Final())
+
5269 GenerateFBEFinalModelEnumFlags(domain, *p->name, *f->name, flags_type);
+
5270}
+
5271
+
5272void GeneratorKotlin::GenerateFlagsClass(const std::shared_ptr<Package>& p, const std::shared_ptr<FlagsType>& f, const CppCommon::Path& path)
+
5273{
+
5274 std::string flags_name = *f->name;
+
5275 std::string flags_type_name = *f->name + "Enum";
+
5276
+
5277 // Generate the output file
+
5278 CppCommon::Path output = path / (flags_name + ".kt");
+
5279 WriteBegin();
+
5280
+
5281 // Generate flags class header
+
5282 GenerateHeader(CppCommon::Path(_input).filename().string());
+
5283 GenerateImports(p);
+
5284
+
5285 std::string flags_type = (f->base && !f->base->empty()) ? *f->base : "int32";
+
5286 std::string flags_base_type = ConvertEnumType(flags_type);
+
5287 std::string flags_int = ConvertEnumFlags(flags_type);
+
5288 std::string flags_to = ConvertEnumTo(flags_type);
+
5289
+
5290 // Generate flags class body
+
5291 WriteLine();
+
5292 WriteLineIndent("@Suppress(\"MemberVisibilityCanBePrivate\", \"RemoveRedundantCallsOfConversionMethods\")");
+
5293 WriteLineIndent("class " + flags_name + " : Comparable<" + flags_name + ">");
+
5294 WriteLineIndent("{");
+
5295 Indent(1);
+
5296 if (f->body)
+
5297 {
+
5298 WriteLineIndent("companion object");
+
5299 WriteLineIndent("{");
+
5300 Indent(1);
+
5301 if (!f->body->values.empty())
+
5302 {
+
5303 for (const auto& value : f->body->values)
+
5304 WriteLineIndent("val " + *value->name + " = " + flags_name + "(" + flags_type_name + "." + *value->name + ")");
+
5305 WriteLine();
+
5306 }
+
5307
+
5308 // Generate flags class fromSet() method
+
5309 if (f->body->values.empty())
+
5310 WriteLineIndent("@Suppress(\"UNUSED_PARAMETER\")");
+
5311 WriteLineIndent("fun fromSet(set: java.util.EnumSet<" + flags_type_name + ">): " + flags_name);
+
5312 WriteLineIndent("{");
+
5313 Indent(1);
+
5314 WriteLineIndent("@Suppress(\"CanBeVal\")");
+
5315 WriteLineIndent("var result = " + ConvertEnumConstant(flags_type, flags_type, "0", false));
+
5316 if (f->body)
+
5317 {
+
5318 for (const auto& value : f->body->values)
+
5319 {
+
5320 WriteLineIndent("if (set.contains(" + *value->name + ".value!!))");
+
5321 WriteLineIndent("{");
+
5322 Indent(1);
+
5323 WriteLineIndent("result = result" + flags_int + " or " + *value->name + ".raw" + flags_int);
+
5324 Indent(-1);
+
5325 WriteLineIndent("}");
+
5326 }
+
5327 }
+
5328 WriteLineIndent("return " + flags_name + "(result" + flags_to + ")");
+
5329 Indent(-1);
+
5330 WriteLineIndent("}");
+
5331
+
5332 Indent(-1);
+
5333 WriteLineIndent("}");
+
5334 WriteLine();
+
5335 }
+
5336
+
5337 // Generate flags class value
+
5338 WriteLineIndent("var value: " + flags_type_name + "?" + " = " + flags_type_name + ".values()[0]");
+
5339 Indent(1);
+
5340 WriteLineIndent("private set");
+
5341 Indent(-1);
+
5342 WriteLine();
+
5343
+
5344 // Generate flags raw value
+
5345 WriteLineIndent("var raw: " + flags_base_type + " = value!!.raw");
+
5346 Indent(1);
+
5347 WriteLineIndent("private set");
+
5348 Indent(-1);
+
5349 WriteLine();
+
5350
+
5351 // Generate flags class constructors
+
5352 WriteLineIndent("constructor()");
+
5353 WriteLineIndent("constructor(value: " + flags_base_type + ") { setEnum(value) }");
+
5354 WriteLineIndent("constructor(value: " + flags_type_name + ") { setEnum(value) }");
+
5355 WriteLineIndent("constructor(value: java.util.EnumSet<" + flags_type_name + ">) { setEnum(value) }");
+
5356 WriteLineIndent("constructor(value: " + flags_name + ") { setEnum(value) }");
+
5357 WriteLine();
+
5358
+
5359 // Generate flags class setDefault() method
+
5360 WriteLineIndent("fun setDefault() { setEnum(0" + flags_to + ") }");
+
5361 WriteLine();
+
5362
+
5363 // Generate flags class setEnum() methods
+
5364 WriteLineIndent("fun setEnum(value: " + flags_base_type + ") { this.raw = value; this.value = " + flags_type_name + ".mapValue(value) }");
+
5365 WriteLineIndent("fun setEnum(value: " + flags_type_name + ") { this.value = value; this.raw = value.raw; }");
+
5366 WriteLineIndent("fun setEnum(value: java.util.EnumSet<" + flags_type_name + ">) { setEnum(" + flags_name + ".fromSet(value)) }");
+
5367 WriteLineIndent("fun setEnum(value: " + flags_name + ") { this.value = value.value; this.raw = value.raw }");
+
5368
+
5369 // Generate flags class hasFlags() methods
+
5370 WriteLine();
+
5371 WriteLineIndent("fun hasFlags(flags: " + flags_base_type + "): Boolean = ((raw" + flags_int + " and flags" + flags_int + ") != " + ConvertEnumConstant(flags_type, flags_type, "0", false) + ") && ((raw" + flags_int + " and flags" + flags_int + ") == flags" + flags_int + ")");
+
5372 WriteLineIndent("fun hasFlags(flags: " + flags_type_name + "): Boolean = hasFlags(flags.raw)");
+
5373 WriteLineIndent("fun hasFlags(flags: " + flags_name + "): Boolean = hasFlags(flags.raw)");
+
5374
+
5375 // Generate flags class setFlags() methods
+
5376 WriteLine();
+
5377 WriteLineIndent("fun setFlags(flags: " + flags_base_type + "): " + flags_name + " { setEnum((raw" + flags_int + " or flags" + flags_int + ")" + flags_to + "); return this }");
+
5378 WriteLineIndent("fun setFlags(flags: " + flags_type_name + "): " + flags_name + " { setFlags(flags.raw); return this }");
+
5379 WriteLineIndent("fun setFlags(flags: " + flags_name + "): " + flags_name + " { setFlags(flags.raw); return this }");
+
5380
+
5381 // Generate flags class removeFlags() methods
+
5382 WriteLine();
+
5383 WriteLineIndent("fun removeFlags(flags: " + flags_base_type + "): " + flags_name + " { setEnum((raw" + flags_int + " and flags" + flags_int + ".inv())" + flags_to + "); return this }");
+
5384 WriteLineIndent("fun removeFlags(flags: " + flags_type_name + "): " + flags_name + " { removeFlags(flags.raw); return this }");
+
5385 WriteLineIndent("fun removeFlags(flags: " + flags_name + "): " + flags_name + " { removeFlags(flags.raw); return this }");
+
5386
+
5387 // Generate flags class getAllSet(), getNoneSet() and getCurrentSet() methods
+
5388 WriteLine();
+
5389 WriteLineIndent("val allSet: java.util.EnumSet<" + flags_type_name + "> get() = value!!.allSet");
+
5390 WriteLineIndent("val noneSet: java.util.EnumSet<" + flags_type_name + "> get() = value!!.noneSet");
+
5391 WriteLineIndent("val currentSet: java.util.EnumSet<" + flags_type_name + "> get() = value!!.currentSet");
+
5392
+
5393 // Generate flags class compareTo() method
+
5394 WriteLine();
+
5395 WriteLineIndent("override fun compareTo(other: " + flags_name + "): Int");
+
5396 WriteLineIndent("{");
+
5397 Indent(1);
+
5398 WriteLineIndent("return (raw - other.raw).toInt()");
+
5399 Indent(-1);
+
5400 WriteLineIndent("}");
+
5401
+
5402 // Generate flags class equals() method
+
5403 WriteLine();
+
5404 WriteLineIndent("override fun equals(other: Any?): Boolean");
+
5405 WriteLineIndent("{");
+
5406 Indent(1);
+
5407 WriteLineIndent("if (other == null)");
+
5408 Indent(1);
+
5409 WriteLineIndent("return false");
+
5410 Indent(-1);
+
5411 WriteLine();
+
5412 WriteLineIndent("if (!" + flags_name + "::class.java.isAssignableFrom(other.javaClass))");
+
5413 Indent(1);
+
5414 WriteLineIndent("return false");
+
5415 Indent(-1);
+
5416 WriteLine();
+
5417 WriteLineIndent("val flg = other as " + flags_name + "? ?: return false");
+
5418 WriteLine();
+
5419 WriteLineIndent("if (raw != flg.raw)");
+
5420 Indent(1);
+
5421 WriteLineIndent("return false");
+
5422 Indent(-1);
+
5423 WriteLineIndent("return true");
+
5424 Indent(-1);
+
5425 WriteLineIndent("}");
+
5426
+
5427 // Generate flags class hashCode() method
+
5428 WriteLine();
+
5429 WriteLineIndent("override fun hashCode(): Int");
+
5430 WriteLineIndent("{");
+
5431 Indent(1);
+
5432 WriteLineIndent("var hash = " + ConvertEnumConstant(flags_type, flags_type, "17", false));
+
5433 WriteLineIndent("hash = hash * " + ConvertEnumConstant(flags_type, flags_type, "31", false) + " + raw" + flags_int);
+
5434 WriteLineIndent("return hash.toInt()");
+
5435 Indent(-1);
+
5436 WriteLineIndent("}");
+
5437
+
5438 // Generate flags class toString() method
+
5439 WriteLine();
+
5440 WriteLineIndent("override fun toString(): String");
+
5441 WriteLineIndent("{");
+
5442 Indent(1);
+
5443 WriteLineIndent("val sb = StringBuilder()");
+
5444 if (f->body && !f->body->values.empty())
+
5445 {
+
5446 WriteLineIndent("var first = true");
+
5447 for (const auto& value : f->body->values)
+
5448 {
+
5449 WriteLineIndent("if (hasFlags(" + *value->name + ".raw))");
+
5450 WriteLineIndent("{");
+
5451 Indent(1);
+
5452 WriteLineIndent("sb.append(if (first) \"\" else \"|\").append(\"" + *value->name + "\")");
+
5453 WriteLineIndent("@Suppress(\"UNUSED_VALUE\")");
+
5454 WriteLineIndent("first = false");
+
5455 Indent(-1);
+
5456 WriteLineIndent("}");
+
5457 }
+
5458 }
+
5459 WriteLineIndent("return sb.toString()");
+
5460 Indent(-1);
+
5461 WriteLineIndent("}");
+
5462
+
5463 Indent(-1);
+
5464 WriteLineIndent("}");
+
5465
+
5466 // Generate flags class footer
+
5467 GenerateFooter();
+
5468
+
5469 // Store the output file
+
5470 WriteEnd();
+
5471 Store(output);
+
5472}
+
5473
+
5474void GeneratorKotlin::GenerateFlagsJson(const std::shared_ptr<Package>& p, const std::shared_ptr<FlagsType>& f)
+
5475{
+
5476 std::string domain = (p->domain && !p->domain->empty()) ? (*p->domain + ".") : "";
+
5477 std::string package = *p->name;
+
5478 std::string flags_name = domain + package + "." + *f->name;
+
5479 std::string adapter_name = *f->name + "Json";
+
5480
+
5481 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "fbe";
+
5482
+
5483 // Create package path
+
5484 CppCommon::Directory::CreateTree(path);
+
5485
+
5486 // Generate the output file
+
5487 CppCommon::Path output = path / (adapter_name + ".kt");
+
5488 WriteBegin();
+
5489
+
5490 // Generate headers
+
5491 GenerateHeader(CppCommon::Path(_input).filename().string());
+
5492 GenerateImports(domain, package + ".fbe");
+
5493
+
5494 std::string flags_type = (f->base && !f->base->empty()) ? *f->base : "int32";
+
5495
+
5496 // Generate JSON adapter body
+
5497 WriteLine();
+
5498 WriteLineIndent("class " + adapter_name + " : com.google.gson.JsonSerializer<" + flags_name + ">, com.google.gson.JsonDeserializer<" + flags_name + ">");
+
5499 WriteLineIndent("{");
+
5500 Indent(1);
+
5501
+
5502 // Generate JSON adapter serialize() method
+
5503 WriteLine();
+
5504 WriteLineIndent("@Override");
+
5505 WriteLineIndent("override fun serialize(src: " + flags_name + ", typeOfSrc: java.lang.reflect.Type, context: com.google.gson.JsonSerializationContext): com.google.gson.JsonElement");
+
5506 WriteLineIndent("{");
+
5507 Indent(1);
+
5508 WriteLineIndent("return com.google.gson.JsonPrimitive(src.raw" + ConvertEnumFrom(flags_type) + ")");
+
5509 Indent(-1);
+
5510 WriteLineIndent("}");
+
5511
+
5512 // Generate JSON adapter deserialize() method
+
5513 WriteLine();
+
5514 WriteLineIndent("@Throws(com.google.gson.JsonParseException::class)");
+
5515 WriteLineIndent("override fun deserialize(json: com.google.gson.JsonElement, type: java.lang.reflect.Type, context: com.google.gson.JsonDeserializationContext):" + flags_name);
+
5516 WriteLineIndent("{");
+
5517 Indent(1);
+
5518 WriteLineIndent("return " + flags_name + "(json.asJsonPrimitive." + ConvertEnumGet(flags_type) + ")");
+
5519 Indent(-1);
+
5520 WriteLineIndent("}");
+
5521
+
5522 Indent(-1);
+
5523 WriteLineIndent("}");
+
5524
+
5525 // Generate JSON adapter footer
+
5526 GenerateFooter();
+
5527
+
5528 // Store the output file
+
5529 WriteEnd();
+
5530 Store(output);
+
5531}
+
5532
+
5533void GeneratorKotlin::GenerateStruct(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s, const CppCommon::Path& path)
+
5534{
+
5535 std::string domain = (p->domain && !p->domain->empty()) ? (*p->domain + ".") : "";
+
5536 bool first;
+
5537
+
5538 // Generate the output file
+
5539 CppCommon::Path output = path / (*s->name + ".kt");
+
5540 WriteBegin();
+
5541
+
5542 // Generate struct header
+
5543 GenerateHeader(CppCommon::Path(_input).filename().string());
+
5544 GenerateImports(p);
+
5545
+
5546 // Generate struct begin
+
5547 WriteLine();
+
5548 WriteLineIndent("@Suppress(\"MemberVisibilityCanBePrivate\", \"RemoveRedundantCallsOfConversionMethods\")");
+
5549 WriteIndent("open class " + *s->name);
+
5550 if (s->base && !s->base->empty())
+
5551 Write(" : " + ConvertTypeName(domain, "", *s->base, false));
+
5552 else
+
5553 Write(" : Comparable<Any?>");
+
5554 WriteLine();
+
5555 WriteLineIndent("{");
+
5556 Indent(1);
+
5557
+
5558 // Generate struct body
+
5559 if (s->body && !s->body->fields.empty())
+
5560 {
+
5561 for (const auto& field : s->body->fields)
+
5562 WriteLineIndent("var " + *field->name + ": " + ConvertTypeName(domain, "", *field, false));
+
5563 WriteLine();
+
5564 }
+
5565
+
5566 // Generate struct FBE type property
+
5567 if (s->base && !s->base->empty() && (s->type == 0))
+
5568 WriteLineIndent("@Transient override var fbeType: Long = " + ConvertTypeName(domain, "", *s->base, false) + ".fbeTypeConst");
+
5569 else if (s->base && !s->base->empty())
+
5570 WriteLineIndent("@Transient override var fbeType: Long = " + std::to_string(s->type));
+
5571 else
+
5572 WriteLineIndent("@Transient open var fbeType: Long = " + std::to_string(s->type));
+
5573
+
5574 // Generate struct default constructor
+
5575 if ((!s->base || s->base->empty()) && (!s->body || s->body->fields.empty()))
+
5576 {
+
5577 WriteLine();
+
5578 WriteLineIndent("constructor()");
+
5579 }
+
5580
+
5581 // Generate struct initialization constructor
+
5582 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
5583 {
+
5584 first = true;
+
5585 WriteLine();
+
5586 WriteIndent("constructor(");
+
5587 if (s->base && !s->base->empty())
+
5588 {
+
5589 Write("parent: " + ConvertTypeName(domain, "", *s->base, false) + " = " + ConvertTypeName(domain, "", *s->base, false) + "()");
+
5590 first = false;
+
5591 }
+
5592 if (s->body)
+
5593 {
+
5594 for (const auto& field : s->body->fields)
+
5595 {
+
5596 Write(std::string(first ? "" : ", ") + *field->name + ": " + ConvertTypeName(domain, "", *field, false) + " = " + ConvertDefault(domain, "", *field));
+
5597 first = false;
+
5598 }
+
5599 }
+
5600 Write(")");
+
5601 if (s->base && !s->base->empty())
+
5602 WriteLine(": super(parent)");
+
5603 else
+
5604 WriteLine();
+
5605 WriteLineIndent("{");
+
5606 Indent(1);
+
5607 if (s->body)
+
5608 for (const auto& field : s->body->fields)
+
5609 WriteLineIndent("this." + *field->name + " = " + *field->name);
+
5610 Indent(-1);
+
5611 WriteLineIndent("}");
+
5612 }
+
5613
+
5614 // Generate struct copy constructor
+
5615 WriteLine();
+
5616 WriteLineIndent("@Suppress(\"UNUSED_PARAMETER\")");
+
5617 WriteIndent("constructor(other: " + *s->name + ")");
+
5618 if (s->base && !s->base->empty())
+
5619 WriteLine(": super(other)");
+
5620 else
+
5621 WriteLine();
+
5622 WriteLineIndent("{");
+
5623 Indent(1);
+
5624 if (s->body)
+
5625 for (const auto& field : s->body->fields)
+
5626 WriteLineIndent("this." + *field->name + " = other." + *field->name);
+
5627 Indent(-1);
+
5628 WriteLineIndent("}");
+
5629
+
5630 // Generate struct clone() method
+
5631 WriteLine();
+
5632 if (s->base && !s->base->empty())
+
5633 WriteLineIndent("override fun clone(): " + *s->name);
+
5634 else
+
5635 WriteLineIndent("open fun clone(): " + *s->name);
+
5636 WriteLineIndent("{");
+
5637 Indent(1);
+
5638 WriteLineIndent("// Serialize the struct to the FBE stream");
+
5639 WriteLineIndent("val writer = " + domain + *p->name + ".fbe." + *s->name + "Model()");
+
5640 WriteLineIndent("writer.serialize(this)");
+
5641 WriteLine();
+
5642 WriteLineIndent("// Deserialize the struct from the FBE stream");
+
5643 WriteLineIndent("val reader = " + domain + *p->name + ".fbe." + *s->name + "Model()");
+
5644 WriteLineIndent("reader.attach(writer.buffer)");
+
5645 WriteLineIndent("return reader.deserialize()");
+
5646 Indent(-1);
+
5647 WriteLineIndent("}");
+
5648
+
5649 // Generate struct compareTo() method
+
5650 WriteLine();
+
5651 WriteLineIndent("override fun compareTo(other: Any?): Int");
+
5652 WriteLineIndent("{");
+
5653 Indent(1);
+
5654 WriteLineIndent("if (other == null)");
+
5655 Indent(1);
+
5656 WriteLineIndent("return -1");
+
5657 Indent(-1);
+
5658 WriteLine();
+
5659 WriteLineIndent("if (!" + *s->name + "::class.java.isAssignableFrom(other.javaClass))");
+
5660 Indent(1);
+
5661 WriteLineIndent("return -1");
+
5662 Indent(-1);
+
5663 WriteLine();
+
5664 WriteLineIndent("@Suppress(\"UNUSED_VARIABLE\")");
+
5665 WriteLineIndent("val obj = other as " + *s->name + "? ?: return -1");
+
5666 WriteLine();
+
5667 WriteLineIndent("@Suppress(\"VARIABLE_WITH_REDUNDANT_INITIALIZER\", \"CanBeVal\", \"UnnecessaryVariable\")");
+
5668 WriteLineIndent("var result = 0");
+
5669 if (s->base && !s->base->empty())
+
5670 {
+
5671 WriteLineIndent("result = super.compareTo(obj)");
+
5672 WriteLineIndent("if (result != 0)");
+
5673 Indent(1);
+
5674 WriteLineIndent("return result");
+
5675 Indent(-1);
+
5676 }
+
5677 if (s->body)
+
5678 {
+
5679 for (const auto& field : s->body->fields)
+
5680 {
+
5681 if (field->keys)
+
5682 {
+
5683 WriteLineIndent("result = " + *field->name + ".compareTo(obj." + *field->name + ")");
+
5684 WriteLineIndent("if (result != 0)");
+
5685 Indent(1);
+
5686 WriteLineIndent("return result");
+
5687 Indent(-1);
+
5688 }
+
5689 }
+
5690 }
+
5691 WriteLineIndent("return result");
+
5692 Indent(-1);
+
5693 WriteLineIndent("}");
+
5694
+
5695 // Generate struct equals() method
+
5696 WriteLine();
+
5697 WriteLineIndent("override fun equals(other: Any?): Boolean");
+
5698 WriteLineIndent("{");
+
5699 Indent(1);
+
5700 WriteLineIndent("if (other == null)");
+
5701 Indent(1);
+
5702 WriteLineIndent("return false");
+
5703 Indent(-1);
+
5704 WriteLine();
+
5705 WriteLineIndent("if (!" + *s->name + "::class.java.isAssignableFrom(other.javaClass))");
+
5706 Indent(1);
+
5707 WriteLineIndent("return false");
+
5708 Indent(-1);
+
5709 WriteLine();
+
5710 WriteLineIndent("@Suppress(\"UNUSED_VARIABLE\")");
+
5711 WriteLineIndent("val obj = other as " + *s->name + "? ?: return false");
+
5712 WriteLine();
+
5713 if (s->base && !s->base->empty())
+
5714 {
+
5715 WriteLineIndent("if (!super.equals(obj))");
+
5716 Indent(1);
+
5717 WriteLineIndent("return false");
+
5718 Indent(-1);
+
5719 }
+
5720 if (s->body)
+
5721 {
+
5722 for (const auto& field : s->body->fields)
+
5723 {
+
5724 if (field->keys)
+
5725 {
+
5726 if (IsPrimitiveType(*field->type, field->optional))
+
5727 WriteLineIndent("if (" + *field->name + " != obj." + *field->name + ")");
+
5728 else
+
5729 WriteLineIndent("if (!" + *field->name + ".equals(obj." + *field->name + "))");
+
5730 Indent(1);
+
5731 WriteLineIndent("return false");
+
5732 Indent(-1);
+
5733 }
+
5734 }
+
5735 }
+
5736 WriteLineIndent("return true");
+
5737 Indent(-1);
+
5738 WriteLineIndent("}");
+
5739
+
5740 // Generate struct hashCode() method
+
5741 WriteLine();
+
5742 WriteLineIndent("override fun hashCode(): Int");
+
5743 WriteLineIndent("{");
+
5744 Indent(1);
+
5745 WriteLineIndent("@Suppress(\"CanBeVal\", \"UnnecessaryVariable\")");
+
5746 WriteLineIndent("var hash = 17");
+
5747 if (s->base && !s->base->empty())
+
5748 WriteLineIndent("hash = hash * 31 + super.hashCode()");
+
5749 if (s->body)
+
5750 {
+
5751 for (const auto& field : s->body->fields)
+
5752 if (field->keys)
+
5753 WriteLineIndent("hash = hash * 31 + " + *field->name + ".hashCode()");
+
5754 }
+
5755 WriteLineIndent("return hash");
+
5756 Indent(-1);
+
5757 WriteLineIndent("}");
+
5758
+
5759 // Generate struct toString() method
+
5760 WriteLine();
+
5761 WriteLineIndent("override fun toString(): String");
+
5762 WriteLineIndent("{");
+
5763 Indent(1);
+
5764 WriteLineIndent("val sb = StringBuilder()");
+
5765 WriteLineIndent("sb.append(\"" + *s->name + "(\")");
+
5766 first = true;
+
5767 if (s->base && !s->base->empty())
+
5768 {
+
5769 WriteLineIndent("sb.append(super.toString())");
+
5770 first = false;
+
5771 }
+
5772 if (s->body)
+
5773 {
+
5774 for (const auto& field : s->body->fields)
+
5775 {
+
5776 if (field->attributes && field->attributes->hidden)
+
5777 WriteLineIndent("sb.append(\"" + std::string(first ? "" : ",") + *field->name + "=***\");");
+
5778 else if (field->array || field->vector)
+
5779 {
+
5780 WriteLineIndent("@Suppress(\"ConstantConditionIf\")");
+
5781 WriteLineIndent("if (true)");
+
5782 WriteLineIndent("{");
+
5783 Indent(1);
+
5784 WriteLineIndent("var first = true");
+
5785 WriteLineIndent("sb.append(\"" + std::string(first ? "" : ",") + *field->name + "=[\").append(" + *field->name + ".size" + ").append(\"][\")");
+
5786 WriteLineIndent("for (item in " + *field->name + ")");
+
5787 WriteLineIndent("{");
+
5788 Indent(1);
+
5789 WriteLineIndent(ConvertOutputStreamValue(*field->type, "item", field->optional, true, false));
+
5790 WriteLineIndent("first = false");
+
5791 Indent(-1);
+
5792 WriteLineIndent("}");
+
5793 WriteLineIndent("sb.append(\"]\")");
+
5794 Indent(-1);
+
5795 WriteLineIndent("}");
+
5796 }
+
5797 else if (field->list)
+
5798 {
+
5799 WriteLineIndent("@Suppress(\"ConstantConditionIf\")");
+
5800 WriteLineIndent("if (true)");
+
5801 WriteLineIndent("{");
+
5802 Indent(1);
+
5803 WriteLineIndent("var first = true");
+
5804 WriteLineIndent("sb.append(\"" + std::string(first ? "" : ",") + *field->name + "=[\").append(" + *field->name + ".size" + ").append(\"]<\")");
+
5805 WriteLineIndent("for (item in " + *field->name + ")");
+
5806 WriteLineIndent("{");
+
5807 Indent(1);
+
5808 WriteLineIndent(ConvertOutputStreamValue(*field->type, "item", field->optional, true, false));
+
5809 WriteLineIndent("first = false");
+
5810 Indent(-1);
+
5811 WriteLineIndent("}");
+
5812 WriteLineIndent("sb.append(\">\")");
+
5813 Indent(-1);
+
5814 WriteLineIndent("}");
+
5815 }
+
5816 else if (field->set)
+
5817 {
+
5818 WriteLineIndent("@Suppress(\"ConstantConditionIf\")");
+
5819 WriteLineIndent("if (true)");
+
5820 WriteLineIndent("{");
+
5821 Indent(1);
+
5822 WriteLineIndent("var first = true");
+
5823 WriteLineIndent("sb.append(\"" + std::string(first ? "" : ",") + *field->name + "=[\").append(" + *field->name + ".size" + ").append(\"]{\")");
+
5824 WriteLineIndent("for (item in " + *field->name + ")");
+
5825 WriteLineIndent("{");
+
5826 Indent(1);
+
5827 WriteLineIndent(ConvertOutputStreamValue(*field->type, "item", field->optional, true, false));
+
5828 WriteLineIndent("first = false");
+
5829 Indent(-1);
+
5830 WriteLineIndent("}");
+
5831 WriteLineIndent("sb.append(\"}\")");
+
5832 Indent(-1);
+
5833 WriteLineIndent("}");
+
5834 }
+
5835 else if (field->map)
+
5836 {
+
5837 WriteLineIndent("@Suppress(\"ConstantConditionIf\")");
+
5838 WriteLineIndent("if (true)");
+
5839 WriteLineIndent("{");
+
5840 Indent(1);
+
5841 WriteLineIndent("var first = true");
+
5842 WriteLineIndent("sb.append(\"" + std::string(first ? "" : ",") + *field->name + "=[\").append(" + *field->name + ".size" + ").append(\"]<{\")");
+
5843 WriteLineIndent("for (item in " + *field->name + ".entries)");
+
5844 WriteLineIndent("{");
+
5845 Indent(1);
+
5846 WriteLineIndent(ConvertOutputStreamValue(*field->key, "item.key", false, true, false));
+
5847 WriteLineIndent("sb.append(\"->\")");
+
5848 WriteLineIndent(ConvertOutputStreamValue(*field->type, "item.value", field->optional, false, true));
+
5849 WriteLineIndent("first = false");
+
5850 Indent(-1);
+
5851 WriteLineIndent("}");
+
5852 WriteLineIndent("sb.append(\"}>\")");
+
5853 Indent(-1);
+
5854 WriteLineIndent("}");
+
5855 }
+
5856 else if (field->hash)
+
5857 {
+
5858 WriteLineIndent("@Suppress(\"ConstantConditionIf\")");
+
5859 WriteLineIndent("if (true)");
+
5860 WriteLineIndent("{");
+
5861 Indent(1);
+
5862 WriteLineIndent("var first = true");
+
5863 WriteLineIndent("sb.append(\"" + std::string(first ? "" : ",") + *field->name + "=[\").append(" + *field->name + ".size" + ").append(\"][{\")");
+
5864 WriteLineIndent("for (item in " + *field->name + ".entries)");
+
5865 WriteLineIndent("{");
+
5866 Indent(1);
+
5867 WriteLineIndent(ConvertOutputStreamValue(*field->key, "item.key", false, true, false));
+
5868 WriteLineIndent("sb.append(\"->\")");
+
5869 WriteLineIndent(ConvertOutputStreamValue(*field->type, "item.value", field->optional, false, true));
+
5870 WriteLineIndent("first = false");
+
5871 Indent(-1);
+
5872 WriteLineIndent("}");
+
5873 WriteLineIndent("sb.append(\"}]\")");
+
5874 Indent(-1);
+
5875 WriteLineIndent("}");
+
5876 }
+
5877 else
+
5878 WriteLineIndent("sb.append(\"" + std::string(first ? "" : ",") + *field->name + "=\"); " + ConvertOutputStreamValue(*field->type, *field->name, field->optional, false, true));
+
5879 first = false;
+
5880 }
+
5881 }
+
5882 WriteLineIndent("sb.append(\")\")");
+
5883 WriteLineIndent("return sb.toString()");
+
5884 Indent(-1);
+
5885 WriteLineIndent("}");
+
5886
+
5887 // Generate struct JSON methods
+
5888 if (JSON())
+
5889 {
+
5890 WriteLine();
+
5891 WriteLineIndent(std::string((s->base && !s->base->empty()) ? "override" : "open") + " fun toJson(): String = " + domain + *p->name + ".fbe.Json.engine.toJson(this)");
+
5892 }
+
5893
+
5894 // Generate struct companion object
+
5895 WriteLine();
+
5896 WriteLineIndent("companion object");
+
5897 WriteLineIndent("{");
+
5898 Indent(1);
+
5899 if (!s->base || s->base->empty())
+
5900 WriteLineIndent("const val fbeTypeConst: Long = " + std::to_string(s->type));
+
5901 if (JSON())
+
5902 WriteLineIndent("fun fromJson(json: String): " + *s->name + " = " + domain + *p->name + ".fbe.Json.engine.fromJson(json, " + *s->name + "::class.java)");
+
5903 Indent(-1);
+
5904 WriteLineIndent("}");
+
5905
+
5906 // Generate struct end
+
5907 Indent(-1);
+
5908 WriteLineIndent("}");
+
5909
+
5910 // Generate struct footer
+
5911 GenerateFooter();
+
5912
+
5913 // Store the output file
+
5914 WriteEnd();
+
5915 Store(output);
+
5916
+
5917 // Generate struct field models
+
5918 GenerateStructFieldModel(p, s);
+
5919 GenerateStructModel(p, s);
+
5920
+
5921 // Generate struct final models
+
5922 if (Final())
+
5923 {
+
5924 GenerateStructFinalModel(p, s);
+
5925 GenerateStructModelFinal(p, s);
+
5926 }
+
5927}
+
5928
+
5929void GeneratorKotlin::GenerateStructFieldModel(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s)
+
5930{
+
5931 std::string domain = (p->domain && !p->domain->empty()) ? (*p->domain + ".") : "";
+
5932 std::string package = *p->name;
+
5933 std::string struct_name = domain + package + "." + *s->name;
+
5934
+
5935 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "fbe";
+
5936
+
5937 // Create package path
+
5938 CppCommon::Directory::CreateTree(path);
+
5939
+
5940 // Generate the file
+
5941 CppCommon::Path file = path / ("FieldModel" + *s->name + ".kt");
+
5942 WriteBegin();
+
5943
+
5944 // Generate headers
+
5945 GenerateHeader(CppCommon::Path(_input).filename().string());
+
5946 GenerateImports(domain, package + ".fbe");
+
5947
+
5948 // Generate struct field model begin
+
5949 WriteLine();
+
5950 WriteLineIndent("// Fast Binary Encoding " + *s->name + " field model");
+
5951 WriteLineIndent("@Suppress(\"MemberVisibilityCanBePrivate\", \"RemoveRedundantCallsOfConversionMethods\", \"ReplaceGetOrSet\")");
+
5952 WriteLineIndent("class FieldModel" + *s->name + "(buffer: " + domain + "fbe.Buffer, offset: Long) : " + domain + "fbe.FieldModel(buffer, offset)");
+
5953 WriteLineIndent("{");
+
5954 Indent(1);
+
5955
+
5956 // Generate struct field model accessors
+
5957 std::string prev_offset("4");
+
5958 std::string prev_size("4");
+
5959 if (s->base && !s->base->empty())
+
5960 {
+
5961 WriteLineIndent("val parent: " + ConvertBaseFieldName(domain, *s->base, false) + " = " + ConvertBaseFieldName(domain, *s->base, false) + "(buffer, " + prev_offset + " + " + prev_size + ")");
+
5962 prev_offset = "parent.fbeOffset";
+
5963 prev_size = "parent.fbeBody - 4 - 4";
+
5964 }
+
5965 if (s->body)
+
5966 {
+
5967 for (const auto& field : s->body->fields)
+
5968 {
+
5969 WriteLineIndent("val " + *field->name + ": " + ConvertTypeFieldDeclaration(domain, *field, false) + " = " + ConvertTypeFieldInitialization(domain, *field, prev_offset + " + " + prev_size, false));
+
5970 prev_offset = *field->name + ".fbeOffset";
+
5971 prev_size = *field->name + ".fbeSize";
+
5972 }
+
5973 }
+
5974
+
5975 // Generate struct field model FBE properties
+
5976 WriteLine();
+
5977 WriteLineIndent("// Field size");
+
5978 WriteLineIndent("override val fbeSize: Long = 4");
+
5979 WriteLine();
+
5980 WriteLineIndent("// Field body size");
+
5981 WriteLineIndent("val fbeBody: Long = (4 + 4");
+
5982 Indent(1);
+
5983 if (s->base && !s->base->empty())
+
5984 WriteLineIndent("+ parent.fbeBody - 4 - 4");
+
5985 if (s->body)
+
5986 for (const auto& field : s->body->fields)
+
5987 WriteLineIndent("+ " + *field->name + ".fbeSize");
+
5988 WriteLineIndent(")");
+
5989 Indent(-1);
+
5990 WriteLine();
+
5991 WriteLineIndent("// Field extra size");
+
5992 WriteLineIndent("override val fbeExtra: Long get()");
+
5993 WriteLineIndent("{");
+
5994 Indent(1);
+
5995 WriteLineIndent("if ((_buffer.offset + fbeOffset + fbeSize) > _buffer.size)");
+
5996 Indent(1);
+
5997 WriteLineIndent("return 0");
+
5998 Indent(-1);
+
5999 WriteLine();
+
6000 WriteLineIndent("val fbeStructOffset = readUInt32(fbeOffset).toLong()");
+
6001 WriteLineIndent("if ((fbeStructOffset == 0L) || ((_buffer.offset + fbeStructOffset + 4) > _buffer.size))");
+
6002 Indent(1);
+
6003 WriteLineIndent("return 0");
+
6004 Indent(-1);
+
6005 WriteLine();
+
6006 WriteLineIndent("_buffer.shift(fbeStructOffset)");
+
6007 WriteLine();
+
6008 WriteLineIndent("val fbeResult = (fbeBody");
+
6009 Indent(1);
+
6010 if (s->base && !s->base->empty())
+
6011 WriteLineIndent("+ parent.fbeExtra");
+
6012 if (s->body)
+
6013 for (const auto& field : s->body->fields)
+
6014 WriteLineIndent("+ " + *field->name + ".fbeExtra");
+
6015 WriteLineIndent(")");
+
6016 Indent(-1);
+
6017 WriteLine();
+
6018 WriteLineIndent("_buffer.unshift(fbeStructOffset)");
+
6019 WriteLine();
+
6020 WriteLineIndent("return fbeResult");
+
6021 Indent(-1);
+
6022 WriteLineIndent("}");
+
6023 WriteLine();
+
6024 WriteLineIndent("// Field type");
+
6025 WriteLineIndent("var fbeType: Long = fbeTypeConst");
+
6026 WriteLine();
+
6027 WriteLineIndent("companion object");
+
6028 WriteLineIndent("{");
+
6029 Indent(1);
+
6030 if (s->base && !s->base->empty() && (s->type == 0))
+
6031 WriteLineIndent("const val fbeTypeConst: Long = " + ConvertBaseFieldName(domain, *s->base, false) + ".fbeTypeConst");
+
6032 else
+
6033 WriteLineIndent("const val fbeTypeConst: Long = " + std::to_string(s->type));
+
6034 Indent(-1);
+
6035 WriteLineIndent("}");
+
6036
+
6037 // Generate struct field model verify() methods
+
6038 WriteLine();
+
6039 WriteLineIndent("// Check if the struct value is valid");
+
6040 WriteLineIndent("fun verify(fbeVerifyType: Boolean = true): Boolean");
+
6041 WriteLineIndent("{");
+
6042 Indent(1);
+
6043 WriteLineIndent("if ((_buffer.offset + fbeOffset + fbeSize) > _buffer.size)");
+
6044 Indent(1);
+
6045 WriteLineIndent("return true");
+
6046 Indent(-1);
+
6047 WriteLine();
+
6048 WriteLineIndent("val fbeStructOffset = readUInt32(fbeOffset).toLong()");
+
6049 WriteLineIndent("if ((fbeStructOffset == 0L) || ((_buffer.offset + fbeStructOffset + 4 + 4) > _buffer.size))");
+
6050 Indent(1);
+
6051 WriteLineIndent("return false");
+
6052 Indent(-1);
+
6053 WriteLine();
+
6054 WriteLineIndent("val fbeStructSize = readUInt32(fbeStructOffset).toLong()");
+
6055 WriteLineIndent("if (fbeStructSize < (4 + 4))");
+
6056 Indent(1);
+
6057 WriteLineIndent("return false");
+
6058 Indent(-1);
+
6059 WriteLine();
+
6060 WriteLineIndent("val fbeStructType = readUInt32(fbeStructOffset + 4).toLong()");
+
6061 WriteLineIndent("if (fbeVerifyType && (fbeStructType != fbeType))");
+
6062 Indent(1);
+
6063 WriteLineIndent("return false");
+
6064 Indent(-1);
+
6065 WriteLine();
+
6066 WriteLineIndent("_buffer.shift(fbeStructOffset)");
+
6067 WriteLineIndent("val fbeResult = verifyFields(fbeStructSize)");
+
6068 WriteLineIndent("_buffer.unshift(fbeStructOffset)");
+
6069 WriteLineIndent("return fbeResult");
+
6070 Indent(-1);
+
6071 WriteLineIndent("}");
+
6072
+
6073 // Generate struct field model verifyFields() method
+
6074 WriteLine();
+
6075 WriteLineIndent("// Check if the struct fields are valid");
+
6076 WriteLineIndent("@Suppress(\"UNUSED_PARAMETER\")");
+
6077 WriteLineIndent("fun verifyFields(fbeStructSize: Long): Boolean");
+
6078 WriteLineIndent("{");
+
6079 Indent(1);
+
6080 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
6081 {
+
6082 WriteLineIndent("var fbeCurrentSize = 4L + 4L");
+
6083 if (s->base && !s->base->empty())
+
6084 {
+
6085 WriteLine();
+
6086 WriteLineIndent("if ((fbeCurrentSize + parent.fbeBody - 4 - 4) > fbeStructSize)");
+
6087 Indent(1);
+
6088 WriteLineIndent("return true");
+
6089 Indent(-1);
+
6090 WriteLineIndent("if (!parent.verifyFields(fbeStructSize))");
+
6091 Indent(1);
+
6092 WriteLineIndent("return false");
+
6093 Indent(-1);
+
6094 WriteLineIndent("fbeCurrentSize += parent.fbeBody - 4 - 4");
+
6095 }
+
6096 if (s->body)
+
6097 {
+
6098 for (const auto& field : s->body->fields)
+
6099 {
+
6100 WriteLine();
+
6101 WriteLineIndent("if ((fbeCurrentSize + " + *field->name + ".fbeSize) > fbeStructSize)");
+
6102 Indent(1);
+
6103 WriteLineIndent("return true");
+
6104 Indent(-1);
+
6105 WriteLineIndent("if (!" + *field->name + ".verify())");
+
6106 Indent(1);
+
6107 WriteLineIndent("return false");
+
6108 Indent(-1);
+
6109 WriteLineIndent("fbeCurrentSize += " + *field->name + ".fbeSize");
+
6110 }
+
6111 }
+
6112 WriteLine();
+
6113 }
+
6114 WriteLineIndent("return true");
+
6115 Indent(-1);
+
6116 WriteLineIndent("}");
+
6117
+
6118 // Generate struct field model getBegin() method
+
6119 WriteLine();
+
6120 WriteLineIndent("// Get the struct value (begin phase)");
+
6121 WriteLineIndent("fun getBegin(): Long");
+
6122 WriteLineIndent("{");
+
6123 Indent(1);
+
6124 WriteLineIndent("if ((_buffer.offset + fbeOffset + fbeSize) > _buffer.size)");
+
6125 Indent(1);
+
6126 WriteLineIndent("return 0");
+
6127 Indent(-1);
+
6128 WriteLine();
+
6129 WriteLineIndent("val fbeStructOffset = readUInt32(fbeOffset).toLong()");
+
6130 WriteLineIndent("assert((fbeStructOffset > 0) && ((_buffer.offset + fbeStructOffset + 4 + 4) <= _buffer.size)) { \"Model is broken!\" }");
+
6131 WriteLineIndent("if ((fbeStructOffset == 0L) || ((_buffer.offset + fbeStructOffset + 4 + 4) > _buffer.size))");
+
6132 Indent(1);
+
6133 WriteLineIndent("return 0");
+
6134 Indent(-1);
+
6135 WriteLine();
+
6136 WriteLineIndent("val fbeStructSize = readUInt32(fbeStructOffset).toLong()");
+
6137 WriteLineIndent("assert(fbeStructSize >= (4 + 4)) { \"Model is broken!\" }");
+
6138 WriteLineIndent("if (fbeStructSize < (4 + 4))");
+
6139 Indent(1);
+
6140 WriteLineIndent("return 0");
+
6141 Indent(-1);
+
6142 WriteLine();
+
6143 WriteLineIndent("_buffer.shift(fbeStructOffset)");
+
6144 WriteLineIndent("return fbeStructOffset");
+
6145 Indent(-1);
+
6146 WriteLineIndent("}");
+
6147
+
6148 // Generate struct field model getEnd() method
+
6149 WriteLine();
+
6150 WriteLineIndent("// Get the struct value (end phase)");
+
6151 WriteLineIndent("fun getEnd(fbeBegin: Long)");
+
6152 WriteLineIndent("{");
+
6153 Indent(1);
+
6154 WriteLineIndent("_buffer.unshift(fbeBegin)");
+
6155 Indent(-1);
+
6156 WriteLineIndent("}");
+
6157
+
6158 // Generate struct field model get() methods
+
6159 WriteLine();
+
6160 WriteLineIndent("// Get the struct value");
+
6161 WriteLineIndent("fun get(fbeValue: " + struct_name + " = " + struct_name + "()): " + struct_name);
+
6162 WriteLineIndent("{");
+
6163 Indent(1);
+
6164 WriteLineIndent("val fbeBegin = getBegin()");
+
6165 WriteLineIndent("if (fbeBegin == 0L)");
+
6166 Indent(1);
+
6167 WriteLineIndent("return fbeValue");
+
6168 Indent(-1);
+
6169 WriteLine();
+
6170 WriteLineIndent("val fbeStructSize = readUInt32(0).toLong()");
+
6171 WriteLineIndent("getFields(fbeValue, fbeStructSize)");
+
6172 WriteLineIndent("getEnd(fbeBegin)");
+
6173 WriteLineIndent("return fbeValue");
+
6174 Indent(-1);
+
6175 WriteLineIndent("}");
+
6176
+
6177 // Generate struct field model getFields() method
+
6178 WriteLine();
+
6179 WriteLineIndent("// Get the struct fields values");
+
6180 WriteLineIndent("@Suppress(\"UNUSED_PARAMETER\")");
+
6181 WriteLineIndent("fun getFields(fbeValue: " + struct_name + ", fbeStructSize: Long)");
+
6182 WriteLineIndent("{");
+
6183 Indent(1);
+
6184 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
6185 {
+
6186 WriteLineIndent("var fbeCurrentSize = 4L + 4L");
+
6187 if (s->base && !s->base->empty())
+
6188 {
+
6189 WriteLine();
+
6190 WriteLineIndent("if ((fbeCurrentSize + parent.fbeBody - 4 - 4) <= fbeStructSize)");
+
6191 Indent(1);
+
6192 WriteLineIndent("parent.getFields(fbeValue, fbeStructSize)");
+
6193 Indent(-1);
+
6194 WriteLineIndent("fbeCurrentSize += parent.fbeBody - 4 - 4");
+
6195 }
+
6196 if (s->body)
+
6197 {
+
6198 for (const auto& field : s->body->fields)
+
6199 {
+
6200 WriteLine();
+
6201 WriteLineIndent("if ((fbeCurrentSize + " + *field->name + ".fbeSize) <= fbeStructSize)");
+
6202 Indent(1);
+
6203 if (field->array || field->vector || field->list || field->set || field->map || field->hash)
+
6204 WriteLineIndent(*field->name + ".get(fbeValue." + *field->name + ")");
+
6205 else
+
6206 WriteLineIndent("fbeValue." + *field->name + " = " + *field->name + ".get(" + (field->value ? ConvertConstant(domain, package, *field->type, *field->value, field->optional) : "") + ")");
+
6207 Indent(-1);
+
6208 WriteLineIndent("else");
+
6209 Indent(1);
+
6210 if (field->vector || field->list || field->set || field->map || field->hash)
+
6211 WriteLineIndent("fbeValue." + *field->name + ".clear()");
+
6212 else
+
6213 WriteLineIndent("fbeValue." + *field->name + " = " + ConvertDefault(domain, package, *field));
+
6214 Indent(-1);
+
6215 WriteLineIndent("fbeCurrentSize += " + *field->name + ".fbeSize");
+
6216 }
+
6217 }
+
6218 }
+
6219 Indent(-1);
+
6220 WriteLineIndent("}");
+
6221
+
6222 // Generate struct field model setBegin() method
+
6223 WriteLine();
+
6224 WriteLineIndent("// Set the struct value (begin phase)");
+
6225 WriteLineIndent("fun setBegin(): Long");
+
6226 WriteLineIndent("{");
+
6227 Indent(1);
+
6228 WriteLineIndent("assert((_buffer.offset + fbeOffset + fbeSize) <= _buffer.size) { \"Model is broken!\" }");
+
6229 WriteLineIndent("if ((_buffer.offset + fbeOffset + fbeSize) > _buffer.size)");
+
6230 Indent(1);
+
6231 WriteLineIndent("return 0");
+
6232 Indent(-1);
+
6233 WriteLine();
+
6234 WriteLineIndent("val fbeStructSize = fbeBody");
+
6235 WriteLineIndent("val fbeStructOffset = _buffer.allocate(fbeStructSize) - _buffer.offset");
+
6236 WriteLineIndent("assert((fbeStructOffset > 0) && ((_buffer.offset + fbeStructOffset + fbeStructSize) <= _buffer.size)) { \"Model is broken!\" }");
+
6237 WriteLineIndent("if ((fbeStructOffset <= 0) || ((_buffer.offset + fbeStructOffset + fbeStructSize) > _buffer.size))");
+
6238 Indent(1);
+
6239 WriteLineIndent("return 0");
+
6240 Indent(-1);
+
6241 WriteLine();
+
6242 WriteLineIndent("write(fbeOffset, fbeStructOffset.toUInt())");
+
6243 WriteLineIndent("write(fbeStructOffset, fbeStructSize.toUInt())");
+
6244 WriteLineIndent("write(fbeStructOffset + 4, fbeType.toUInt())");
+
6245 WriteLine();
+
6246 WriteLineIndent("_buffer.shift(fbeStructOffset)");
+
6247 WriteLineIndent("return fbeStructOffset");
+
6248 Indent(-1);
+
6249 WriteLineIndent("}");
+
6250
+
6251 // Generate struct field model setEnd() method
+
6252 WriteLine();
+
6253 WriteLineIndent("// Set the struct value (end phase)");
+
6254 WriteLineIndent("fun setEnd(fbeBegin: Long)");
+
6255 WriteLineIndent("{");
+
6256 Indent(1);
+
6257 WriteLineIndent("_buffer.unshift(fbeBegin)");
+
6258 Indent(-1);
+
6259 WriteLineIndent("}");
+
6260
+
6261 // Generate struct field model set() method
+
6262 WriteLine();
+
6263 WriteLineIndent("// Set the struct value");
+
6264 WriteLineIndent("fun set(fbeValue: " + struct_name + ")");
+
6265 WriteLineIndent("{");
+
6266 Indent(1);
+
6267 WriteLineIndent("val fbeBegin = setBegin()");
+
6268 WriteLineIndent("if (fbeBegin == 0L)");
+
6269 Indent(1);
+
6270 WriteLineIndent("return");
+
6271 Indent(-1);
+
6272 WriteLine();
+
6273 WriteLineIndent("setFields(fbeValue)");
+
6274 WriteLineIndent("setEnd(fbeBegin)");
+
6275 Indent(-1);
+
6276 WriteLineIndent("}");
+
6277
+
6278 // Generate struct field model setFields() method
+
6279 WriteLine();
+
6280 WriteLineIndent("// Set the struct fields values");
+
6281 WriteLineIndent("@Suppress(\"UNUSED_PARAMETER\")");
+
6282 WriteLineIndent("fun setFields(fbeValue: " + struct_name + ")");
+
6283 WriteLineIndent("{");
+
6284 Indent(1);
+
6285 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
6286 {
+
6287 if (s->base && !s->base->empty())
+
6288 WriteLineIndent("parent.setFields(fbeValue)");
+
6289 if (s->body)
+
6290 for (const auto& field : s->body->fields)
+
6291 WriteLineIndent(*field->name + ".set(fbeValue." + *field->name + ")");
+
6292 }
+
6293 Indent(-1);
+
6294 WriteLineIndent("}");
+
6295
+
6296 // Generate struct field model end
+
6297 Indent(-1);
+
6298 WriteLineIndent("}");
+
6299
+
6300 // Generate footer
+
6301 GenerateFooter();
+
6302
+
6303 // Store the file
+
6304 WriteEnd();
+
6305 Store(file);
+
6306}
+
6307
+
6308void GeneratorKotlin::GenerateStructModel(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s)
+
6309{
+
6310 std::string domain = (p->domain && !p->domain->empty()) ? (*p->domain + ".") : "";
+
6311 std::string package = *p->name;
+
6312 std::string struct_name = domain + package + "." + *s->name;
+
6313
+
6314 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "fbe";
+
6315
+
6316 // Create package path
+
6317 CppCommon::Directory::CreateTree(path);
+
6318
+
6319 // Generate the file
+
6320 CppCommon::Path file = path / (*s->name + "Model.kt");
+
6321 WriteBegin();
+
6322
+
6323 // Generate headers
+
6324 GenerateHeader(CppCommon::Path(_input).filename().string());
+
6325 GenerateImports(domain, package + ".fbe");
+
6326
+
6327 // Generate struct model begin
+
6328 WriteLine();
+
6329 WriteLineIndent("// Fast Binary Encoding " + *s->name + " model");
+
6330 WriteLineIndent("class " + *s->name + "Model : " + domain + "fbe.Model");
+
6331 WriteLineIndent("{");
+
6332 Indent(1);
+
6333
+
6334 // Generate struct model accessor
+
6335 WriteLineIndent("val model: FieldModel" + *s->name);
+
6336
+
6337 // Generate struct model constructors
+
6338 WriteLine();
+
6339 WriteLineIndent("constructor() { model = FieldModel" + *s->name + "(buffer, 4) }");
+
6340 WriteLineIndent("constructor(buffer: " + domain + "fbe.Buffer) : super(buffer) { model = FieldModel" + *s->name + "(buffer, 4) }");
+
6341
+
6342 // Generate struct model FBE properties
+
6343 WriteLine();
+
6344 WriteLineIndent("// Model size");
+
6345 WriteLineIndent("fun fbeSize(): Long = model.fbeSize + model.fbeExtra");
+
6346 WriteLineIndent("// Model type");
+
6347 WriteLineIndent("var fbeType: Long = fbeTypeConst");
+
6348 WriteLine();
+
6349 WriteLineIndent("companion object");
+
6350 WriteLineIndent("{");
+
6351 Indent(1);
+
6352 WriteLineIndent("const val fbeTypeConst: Long = FieldModel" + *s->name + ".fbeTypeConst");
+
6353 Indent(-1);
+
6354 WriteLineIndent("}");
+
6355
+
6356 // Generate struct model verify() method
+
6357 WriteLine();
+
6358 WriteLineIndent("// Check if the struct value is valid");
+
6359 WriteLineIndent("fun verify(): Boolean");
+
6360 WriteLineIndent("{");
+
6361 Indent(1);
+
6362 WriteLineIndent("if ((buffer.offset + model.fbeOffset - 4) > buffer.size)");
+
6363 Indent(1);
+
6364 WriteLineIndent("return false");
+
6365 Indent(-1);
+
6366 WriteLine();
+
6367 WriteLineIndent("val fbeFullSize = readUInt32(model.fbeOffset - 4).toLong()");
+
6368 WriteLineIndent("if (fbeFullSize < model.fbeSize)");
+
6369 Indent(1);
+
6370 WriteLineIndent("return false");
+
6371 Indent(-1);
+
6372 WriteLine();
+
6373 WriteLineIndent("return model.verify()");
+
6374 Indent(-1);
+
6375 WriteLineIndent("}");
+
6376
+
6377 // Generate struct model createBegin() method
+
6378 WriteLine();
+
6379 WriteLineIndent("// Create a new model (begin phase)");
+
6380 WriteLineIndent("fun createBegin(): Long");
+
6381 WriteLineIndent("{");
+
6382 Indent(1);
+
6383 WriteLineIndent("return buffer.allocate(4 + model.fbeSize)");
+
6384 Indent(-1);
+
6385 WriteLineIndent("}");
+
6386
+
6387 // Generate struct model createEnd() method
+
6388 WriteLine();
+
6389 WriteLineIndent("// Create a new model (end phase)");
+
6390 WriteLineIndent("fun createEnd(fbeBegin: Long): Long");
+
6391 WriteLineIndent("{");
+
6392 Indent(1);
+
6393 WriteLineIndent("val fbeEnd = buffer.size");
+
6394 WriteLineIndent("val fbeFullSize = fbeEnd - fbeBegin");
+
6395 WriteLineIndent("write(model.fbeOffset - 4, fbeFullSize.toUInt())");
+
6396 WriteLineIndent("return fbeFullSize");
+
6397 Indent(-1);
+
6398 WriteLineIndent("}");
+
6399
+
6400 // Generate struct model serialize() method
+
6401 WriteLine();
+
6402 WriteLineIndent("// Serialize the struct value");
+
6403 WriteLineIndent("fun serialize(value: " + struct_name + "): Long");
+
6404 WriteLineIndent("{");
+
6405 Indent(1);
+
6406 WriteLineIndent("val fbeBegin = createBegin()");
+
6407 WriteLineIndent("model.set(value)");
+
6408 WriteLineIndent("return createEnd(fbeBegin)");
+
6409 Indent(-1);
+
6410 WriteLineIndent("}");
+
6411
+
6412 // Generate struct model deserialize() methods
+
6413 WriteLine();
+
6414 WriteLineIndent("// Deserialize the struct value");
+
6415 WriteLineIndent("fun deserialize(): " + struct_name + " { val value = " + struct_name + "(); deserialize(value); return value }");
+
6416 WriteLineIndent("@Suppress(\"UNUSED_VALUE\")");
+
6417 WriteLineIndent("fun deserialize(value: " + struct_name + "): Long");
+
6418 WriteLineIndent("{");
+
6419 Indent(1);
+
6420 WriteLineIndent("var valueRef = value");
+
6421 WriteLine();
+
6422 WriteLineIndent("if ((buffer.offset + model.fbeOffset - 4) > buffer.size)");
+
6423 WriteLineIndent("{");
+
6424 Indent(1);
+
6425 WriteLineIndent("valueRef = " + struct_name + "()");
+
6426 WriteLineIndent("return 0");
+
6427 Indent(-1);
+
6428 WriteLineIndent("}");
+
6429 WriteLine();
+
6430 WriteLineIndent("val fbeFullSize = readUInt32(model.fbeOffset - 4).toLong()");
+
6431 WriteLineIndent("assert(fbeFullSize >= model.fbeSize) { \"Model is broken!\" }");
+
6432 WriteLineIndent("if (fbeFullSize < model.fbeSize)");
+
6433 WriteLineIndent("{");
+
6434 Indent(1);
+
6435 WriteLineIndent("valueRef = " + struct_name + "()");
+
6436 WriteLineIndent("return 0");
+
6437 Indent(-1);
+
6438 WriteLineIndent("}");
+
6439 WriteLine();
+
6440 WriteLineIndent("valueRef = model.get(valueRef)");
+
6441 WriteLineIndent("return fbeFullSize");
+
6442 Indent(-1);
+
6443 WriteLineIndent("}");
+
6444
+
6445 // Generate struct model next() method
+
6446 WriteLine();
+
6447 WriteLineIndent("// Move to the next struct value");
+
6448 WriteLineIndent("fun next(prev: Long)");
+
6449 WriteLineIndent("{");
+
6450 Indent(1);
+
6451 WriteLineIndent("model.fbeShift(prev)");
+
6452 Indent(-1);
+
6453 WriteLineIndent("}");
+
6454
+
6455 // Generate struct model end
+
6456 Indent(-1);
+
6457 WriteLineIndent("}");
+
6458
+
6459 // Generate footer
+
6460 GenerateFooter();
+
6461
+
6462 // Store the file
+
6463 WriteEnd();
+
6464 Store(file);
+
6465}
+
6466
+
6467void GeneratorKotlin::GenerateStructFinalModel(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s)
+
6468{
+
6469 std::string domain = (p->domain && !p->domain->empty()) ? (*p->domain + ".") : "";
+
6470 std::string package = *p->name;
+
6471 std::string struct_name = domain + package + "." + *s->name;
+
6472
+
6473 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "fbe";
+
6474
+
6475 // Create package path
+
6476 CppCommon::Directory::CreateTree(path);
+
6477
+
6478 // Generate the file
+
6479 CppCommon::Path file = path / ("FinalModel" + *s->name + ".kt");
+
6480 WriteBegin();
+
6481
+
6482 // Generate headers
+
6483 GenerateHeader(CppCommon::Path(_input).filename().string());
+
6484 GenerateImports(domain, package + ".fbe");
+
6485
+
6486 // Generate struct final model begin
+
6487 WriteLine();
+
6488 WriteLineIndent("// Fast Binary Encoding " + *s->name + " final model");
+
6489 WriteLineIndent("@Suppress(\"MemberVisibilityCanBePrivate\", \"RemoveRedundantCallsOfConversionMethods\", \"ReplaceGetOrSet\")");
+
6490 WriteLineIndent("class FinalModel" + *s->name + "(buffer: " + domain + "fbe.Buffer, offset: Long) : " + domain + "fbe.FinalModel(buffer, offset)");
+
6491 WriteLineIndent("{");
+
6492 Indent(1);
+
6493
+
6494 // Generate struct final model accessors
+
6495 if (s->base && !s->base->empty())
+
6496 WriteLineIndent("val parent: " + ConvertBaseFieldName(domain, *s->base, true) + " = " + ConvertBaseFieldName(domain, *s->base, true) + "(buffer, 0)");
+
6497 if (s->body)
+
6498 for (const auto& field : s->body->fields)
+
6499 WriteLineIndent("val " + *field->name + ": " + ConvertTypeFieldDeclaration(domain, *field, true) + " = " + ConvertTypeFieldInitialization(domain, *field, "0", true));
+
6500
+
6501 // Generate struct final model FBE properties
+
6502 WriteLine();
+
6503 WriteLineIndent("// Get the allocation size");
+
6504 WriteLineIndent("@Suppress(\"UNUSED_PARAMETER\")");
+
6505 WriteLineIndent("fun fbeAllocationSize(fbeValue: " + struct_name + "): Long = (0");
+
6506 Indent(1);
+
6507 if (s->base && !s->base->empty())
+
6508 WriteLineIndent("+ parent.fbeAllocationSize(fbeValue)");
+
6509 if (s->body)
+
6510 for (const auto& field : s->body->fields)
+
6511 WriteLineIndent("+ " + *field->name + ".fbeAllocationSize(fbeValue." + *field->name + ")");
+
6512 WriteLineIndent(")");
+
6513 Indent(-1);
+
6514 WriteLine();
+
6515 WriteLineIndent("// Field type");
+
6516 WriteLineIndent("var fbeType: Long = fbeTypeConst");
+
6517 WriteLine();
+
6518 WriteLineIndent("companion object");
+
6519 WriteLineIndent("{");
+
6520 Indent(1);
+
6521 if (s->base && !s->base->empty() && (s->type == 0))
+
6522 WriteLineIndent("const val fbeTypeConst: Long = " + ConvertBaseFieldName(domain, *s->base, true) + ".fbeTypeConst");
+
6523 else
+
6524 WriteLineIndent("const val fbeTypeConst: Long = " + std::to_string(s->type));
+
6525 Indent(-1);
+
6526 WriteLineIndent("}");
+
6527
+
6528 // Generate struct final model verify() methods
+
6529 WriteLine();
+
6530 WriteLineIndent("// Check if the struct value is valid");
+
6531 WriteLineIndent("override fun verify(): Long");
+
6532 WriteLineIndent("{");
+
6533 Indent(1);
+
6534 WriteLineIndent("_buffer.shift(fbeOffset)");
+
6535 WriteLineIndent("val fbeResult = verifyFields()");
+
6536 WriteLineIndent("_buffer.unshift(fbeOffset)");
+
6537 WriteLineIndent("return fbeResult");
+
6538 Indent(-1);
+
6539 WriteLineIndent("}");
+
6540
+
6541 // Generate struct final model verifyFields() method
+
6542 WriteLine();
+
6543 WriteLineIndent("// Check if the struct fields are valid");
+
6544 WriteLineIndent("fun verifyFields(): Long");
+
6545 WriteLineIndent("{");
+
6546 Indent(1);
+
6547 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
6548 {
+
6549 WriteLineIndent("var fbeCurrentOffset = 0L");
+
6550 WriteLineIndent("@Suppress(\"VARIABLE_WITH_REDUNDANT_INITIALIZER\")");
+
6551 WriteLineIndent("var fbeFieldSize = 0L");
+
6552 if (s->base && !s->base->empty())
+
6553 {
+
6554 WriteLine();
+
6555 WriteLineIndent("parent.fbeOffset = fbeCurrentOffset");
+
6556 WriteLineIndent("fbeFieldSize = parent.verifyFields()");
+
6557 WriteLineIndent("if (fbeFieldSize == Long.MAX_VALUE)");
+
6558 Indent(1);
+
6559 WriteLineIndent("return Long.MAX_VALUE");
+
6560 Indent(-1);
+
6561 WriteLineIndent("fbeCurrentOffset += fbeFieldSize");
+
6562 }
+
6563 if (s->body)
+
6564 {
+
6565 for (const auto& field : s->body->fields)
+
6566 {
+
6567 WriteLine();
+
6568 WriteLineIndent(*field->name + ".fbeOffset = fbeCurrentOffset");
+
6569 WriteLineIndent("fbeFieldSize = " + *field->name + ".verify()");
+
6570 WriteLineIndent("if (fbeFieldSize == Long.MAX_VALUE)");
+
6571 Indent(1);
+
6572 WriteLineIndent("return Long.MAX_VALUE");
+
6573 Indent(-1);
+
6574 WriteLineIndent("fbeCurrentOffset += fbeFieldSize");
+
6575 }
+
6576 }
+
6577 WriteLine();
+
6578 WriteLineIndent("return fbeCurrentOffset");
+
6579 }
+
6580 else
+
6581 WriteLineIndent("return 0L");
+
6582 Indent(-1);
+
6583 WriteLineIndent("}");
+
6584
+
6585 // Generate struct final model get() methods
+
6586 WriteLine();
+
6587 WriteLineIndent("// Get the struct value");
+
6588 WriteLineIndent("fun get(fbeSize: " + domain + "fbe.Size, fbeValue: " + struct_name + " = " + struct_name + "()): " + struct_name);
+
6589 WriteLineIndent("{");
+
6590 Indent(1);
+
6591 WriteLineIndent("_buffer.shift(fbeOffset)");
+
6592 WriteLineIndent("fbeSize.value = getFields(fbeValue)");
+
6593 WriteLineIndent("_buffer.unshift(fbeOffset)");
+
6594 WriteLineIndent("return fbeValue");
+
6595 Indent(-1);
+
6596 WriteLineIndent("}");
+
6597
+
6598 // Generate struct final model getFields() method
+
6599 WriteLine();
+
6600 WriteLineIndent("// Get the struct fields values");
+
6601 WriteLineIndent("@Suppress(\"UNUSED_PARAMETER\")");
+
6602 WriteLineIndent("fun getFields(fbeValue: " + struct_name + "): Long");
+
6603 WriteLineIndent("{");
+
6604 Indent(1);
+
6605 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
6606 {
+
6607 WriteLineIndent("var fbeCurrentOffset = 0L");
+
6608 WriteLineIndent("var fbeCurrentSize = 0L");
+
6609 WriteLineIndent("val fbeFieldSize = " + domain + "fbe.Size()");
+
6610 if (s->base && !s->base->empty())
+
6611 {
+
6612 WriteLine();
+
6613 WriteLineIndent("parent.fbeOffset = fbeCurrentOffset");
+
6614 WriteLineIndent("fbeFieldSize.value = parent.getFields(fbeValue)");
+
6615 WriteLineIndent("fbeCurrentOffset += fbeFieldSize.value");
+
6616 WriteLineIndent("fbeCurrentSize += fbeFieldSize.value");
+
6617 }
+
6618 if (s->body)
+
6619 {
+
6620 for (const auto& field : s->body->fields)
+
6621 {
+
6622 WriteLine();
+
6623 WriteLineIndent(*field->name + ".fbeOffset = fbeCurrentOffset");
+
6624 if (field->array || field->vector || field->list || field->set || field->map || field->hash)
+
6625 WriteLineIndent("fbeFieldSize.value = " + *field->name + ".get(fbeValue." + *field->name + ")");
+
6626 else
+
6627 WriteLineIndent("fbeValue." + *field->name + " = " + *field->name + ".get(fbeFieldSize)");
+
6628 WriteLineIndent("fbeCurrentOffset += fbeFieldSize.value");
+
6629 WriteLineIndent("fbeCurrentSize += fbeFieldSize.value");
+
6630 }
+
6631 }
+
6632 WriteLine();
+
6633 WriteLineIndent("return fbeCurrentSize");
+
6634 }
+
6635 else
+
6636 WriteLineIndent("return 0L");
+
6637 Indent(-1);
+
6638 WriteLineIndent("}");
+
6639
+
6640 // Generate struct final model set() method
+
6641 WriteLine();
+
6642 WriteLineIndent("// Set the struct value");
+
6643 WriteLineIndent("fun set(fbeValue: " + struct_name + "): Long");
+
6644 WriteLineIndent("{");
+
6645 Indent(1);
+
6646 WriteLineIndent("_buffer.shift(fbeOffset)");
+
6647 WriteLineIndent("val fbeSize = setFields(fbeValue)");
+
6648 WriteLineIndent("_buffer.unshift(fbeOffset)");
+
6649 WriteLineIndent("return fbeSize");
+
6650 Indent(-1);
+
6651 WriteLineIndent("}");
+
6652
+
6653 // Generate struct final model setFields() method
+
6654 WriteLine();
+
6655 WriteLineIndent("// Set the struct fields values");
+
6656 WriteLineIndent("@Suppress(\"UNUSED_PARAMETER\")");
+
6657 WriteLineIndent("fun setFields(fbeValue: " + struct_name + "): Long");
+
6658 WriteLineIndent("{");
+
6659 Indent(1);
+
6660 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
6661 {
+
6662 WriteLineIndent("var fbeCurrentOffset = 0L");
+
6663 WriteLineIndent("var fbeCurrentSize = 0L");
+
6664 WriteLineIndent("val fbeFieldSize = " + domain + "fbe.Size()");
+
6665 if (s->base && !s->base->empty())
+
6666 {
+
6667 WriteLine();
+
6668 WriteLineIndent("parent.fbeOffset = fbeCurrentOffset");
+
6669 WriteLineIndent("fbeFieldSize.value = parent.setFields(fbeValue)");
+
6670 WriteLineIndent("fbeCurrentOffset += fbeFieldSize.value");
+
6671 WriteLineIndent("fbeCurrentSize += fbeFieldSize.value");
+
6672 }
+
6673 if (s->body)
+
6674 {
+
6675 for (const auto& field : s->body->fields)
+
6676 {
+
6677 WriteLine();
+
6678 WriteLineIndent(*field->name + ".fbeOffset = fbeCurrentOffset");
+
6679 WriteLineIndent("fbeFieldSize.value = " + *field->name + ".set(fbeValue." + *field->name + ")");
+
6680 WriteLineIndent("fbeCurrentOffset += fbeFieldSize.value");
+
6681 WriteLineIndent("fbeCurrentSize += fbeFieldSize.value");
+
6682 }
+
6683 }
+
6684 WriteLine();
+
6685 WriteLineIndent("return fbeCurrentSize");
+
6686 }
+
6687 else
+
6688 WriteLineIndent("return 0L");
+
6689 Indent(-1);
+
6690 WriteLineIndent("}");
+
6691
+
6692 // Generate struct final model end
+
6693 Indent(-1);
+
6694 WriteLineIndent("}");
+
6695
+
6696 // Generate footer
+
6697 GenerateFooter();
+
6698
+
6699 // Store the file
+
6700 WriteEnd();
+
6701 Store(file);
+
6702}
+
6703
+
6704void GeneratorKotlin::GenerateStructModelFinal(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s)
+
6705{
+
6706 std::string domain = (p->domain && !p->domain->empty()) ? (*p->domain + ".") : "";
+
6707 std::string package = *p->name;
+
6708 std::string struct_name = domain + package + "." + *s->name;
+
6709
+
6710 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "fbe";
+
6711
+
6712 // Create package path
+
6713 CppCommon::Directory::CreateTree(path);
+
6714
+
6715 // Generate the file
+
6716 CppCommon::Path file = path / (*s->name + "FinalModel.kt");
+
6717 WriteBegin();
+
6718
+
6719 // Generate headers
+
6720 GenerateHeader(CppCommon::Path(_input).filename().string());
+
6721 GenerateImports(domain, package + ".fbe");
+
6722
+
6723 // Generate struct model final begin
+
6724 WriteLine();
+
6725 WriteLineIndent("// Fast Binary Encoding " + *s->name + " final model");
+
6726 WriteLineIndent("class " + *s->name + "FinalModel : " + domain + "fbe.Model");
+
6727 WriteLineIndent("{");
+
6728 Indent(1);
+
6729
+
6730 // Generate struct model final accessor
+
6731 WriteLineIndent("private val _model: FinalModel" + *s->name);
+
6732
+
6733 // Generate struct model final constructors
+
6734 WriteLine();
+
6735 WriteLineIndent("constructor() { _model = FinalModel" + *s->name + "(buffer, 8) }");
+
6736 WriteLineIndent("constructor(buffer: " + domain + "fbe.Buffer) : super(buffer) { _model = FinalModel" + *s->name + "(buffer, 8) }");
+
6737
+
6738 // Generate struct model final FBE properties
+
6739 WriteLine();
+
6740 WriteLineIndent("// Model type");
+
6741 WriteLineIndent("var fbeType: Long = fbeTypeConst");
+
6742 WriteLine();
+
6743 WriteLineIndent("companion object");
+
6744 WriteLineIndent("{");
+
6745 Indent(1);
+
6746 WriteLineIndent("const val fbeTypeConst: Long = FinalModel" + *s->name + ".fbeTypeConst");
+
6747 Indent(-1);
+
6748 WriteLineIndent("}");
+
6749
+
6750 // Generate struct model final verify() method
+
6751 WriteLine();
+
6752 WriteLineIndent("// Check if the struct value is valid");
+
6753 WriteLineIndent("fun verify(): Boolean");
+
6754 WriteLineIndent("{");
+
6755 Indent(1);
+
6756 WriteLineIndent("if ((buffer.offset + _model.fbeOffset) > buffer.size)");
+
6757 Indent(1);
+
6758 WriteLineIndent("return false");
+
6759 Indent(-1);
+
6760 WriteLine();
+
6761 WriteLineIndent("val fbeStructSize = readUInt32(_model.fbeOffset - 8).toLong()");
+
6762 WriteLineIndent("val fbeStructType = readUInt32(_model.fbeOffset - 4).toLong()");
+
6763 WriteLineIndent("if ((fbeStructSize <= 0) || (fbeStructType != fbeType))");
+
6764 Indent(1);
+
6765 WriteLineIndent("return false");
+
6766 Indent(-1);
+
6767 WriteLine();
+
6768 WriteLineIndent("return ((8 + _model.verify()) == fbeStructSize)");
+
6769 Indent(-1);
+
6770 WriteLineIndent("}");
+
6771
+
6772 // Generate struct model final serialize() method
+
6773 WriteLine();
+
6774 WriteLineIndent("// Serialize the struct value");
+
6775 WriteLineIndent("fun serialize(value: " + struct_name + "): Long");
+
6776 WriteLineIndent("{");
+
6777 Indent(1);
+
6778 WriteLineIndent("val fbeInitialSize = buffer.size");
+
6779 WriteLine();
+
6780 WriteLineIndent("val fbeStructType = fbeType");
+
6781 WriteLineIndent("var fbeStructSize = 8 + _model.fbeAllocationSize(value)");
+
6782 WriteLineIndent("val fbeStructOffset = buffer.allocate(fbeStructSize) - buffer.offset");
+
6783 WriteLineIndent("assert((buffer.offset + fbeStructOffset + fbeStructSize) <= buffer.size) { \"Model is broken!\" }");
+
6784 WriteLineIndent("if ((buffer.offset + fbeStructOffset + fbeStructSize) > buffer.size)");
+
6785 Indent(1);
+
6786 WriteLineIndent("return 0");
+
6787 Indent(-1);
+
6788 WriteLine();
+
6789 WriteLineIndent("fbeStructSize = 8 + _model.set(value)");
+
6790 WriteLineIndent("buffer.resize(fbeInitialSize + fbeStructSize)");
+
6791 WriteLine();
+
6792 WriteLineIndent("write(_model.fbeOffset - 8, fbeStructSize.toUInt())");
+
6793 WriteLineIndent("write(_model.fbeOffset - 4, fbeStructType.toUInt())");
+
6794 WriteLine();
+
6795 WriteLineIndent("return fbeStructSize");
+
6796 Indent(-1);
+
6797 WriteLineIndent("}");
+
6798
+
6799 // Generate struct model final deserialize() methods
+
6800 WriteLine();
+
6801 WriteLineIndent("// Deserialize the struct value");
+
6802 WriteLineIndent("fun deserialize(): " + struct_name + " { val value = " + struct_name + "(); deserialize(value); return value }");
+
6803 WriteLineIndent("@Suppress(\"UNUSED_VALUE\")");
+
6804 WriteLineIndent("fun deserialize(value: " + struct_name + "): Long");
+
6805 WriteLineIndent("{");
+
6806 Indent(1);
+
6807 WriteLineIndent("var valueRef = value");
+
6808 WriteLine();
+
6809 WriteLineIndent("assert((buffer.offset + _model.fbeOffset) <= buffer.size) { \"Model is broken!\" }");
+
6810 WriteLineIndent("if ((buffer.offset + _model.fbeOffset) > buffer.size)");
+
6811 Indent(1);
+
6812 WriteLineIndent("return 0");
+
6813 Indent(-1);
+
6814 WriteLine();
+
6815 WriteLineIndent("val fbeStructSize = readUInt32(_model.fbeOffset - 8).toLong()");
+
6816 WriteLineIndent("val fbeStructType = readUInt32(_model.fbeOffset - 4).toLong()");
+
6817 WriteLineIndent("assert((fbeStructSize > 0) && (fbeStructType == fbeType)) { \"Model is broken!\" }");
+
6818 WriteLineIndent("if ((fbeStructSize <= 0) || (fbeStructType != fbeType))");
+
6819 Indent(1);
+
6820 WriteLineIndent("return 8");
+
6821 Indent(-1);
+
6822 WriteLine();
+
6823 WriteLineIndent("val fbeSize = " + domain + "fbe.Size()");
+
6824 WriteLineIndent("valueRef = _model.get(fbeSize, valueRef)");
+
6825 WriteLineIndent("return 8 + fbeSize.value");
+
6826 Indent(-1);
+
6827 WriteLineIndent("}");
+
6828
+
6829 // Generate struct model final next() method
+
6830 WriteLine();
+
6831 WriteLineIndent("// Move to the next struct value");
+
6832 WriteLineIndent("fun next(prev: Long)");
+
6833 WriteLineIndent("{");
+
6834 Indent(1);
+
6835 WriteLineIndent("_model.fbeShift(prev)");
+
6836 Indent(-1);
+
6837 WriteLineIndent("}");
+
6838
+
6839 // Generate struct model final end
+
6840 Indent(-1);
+
6841 WriteLineIndent("}");
+
6842
+
6843 // Generate footer
+
6844 GenerateFooter();
+
6845
+
6846 // Store the file
+
6847 WriteEnd();
+
6848 Store(file);
+
6849}
+
6850
+
6851void GeneratorKotlin::GenerateProtocolVersion(const std::shared_ptr<Package>& p)
+
6852{
+
6853 std::string domain = (p->domain && !p->domain->empty()) ? (*p->domain + ".") : "";
+
6854 std::string package = *p->name;
+
6855
+
6856 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "fbe";
+
6857
+
6858 // Create package path
+
6859 CppCommon::Directory::CreateTree(path);
+
6860
+
6861 // Generate the file
+
6862 CppCommon::Path file = path / ("ProtocolVersion.kt");
+
6863 WriteBegin();
+
6864
+
6865 // Generate headers
+
6866 GenerateHeader(CppCommon::Path(_input).filename().string());
+
6867 GenerateImports(domain, package + ".fbe");
+
6868
+
6869 // Generate protocol version class
+
6870 WriteLine();
+
6871 WriteLineIndent("// Fast Binary Encoding " + domain + *p->name + " protocol version");
+
6872 WriteLineIndent("object ProtocolVersion");
+
6873 WriteLineIndent("{");
+
6874 Indent(1);
+
6875 WriteLineIndent("// Protocol major version");
+
6876 WriteLineIndent("const val Major = " + std::to_string(p->version->major));
+
6877 WriteLineIndent("// Protocol minor version");
+
6878 WriteLineIndent("const val Minor = " + std::to_string(p->version->minor));
+
6879 Indent(-1);
+
6880 WriteLineIndent("}");
+
6881
+
6882 // Generate footer
+
6883 GenerateFooter();
+
6884
+
6885 // Store the file
+
6886 WriteEnd();
+
6887 Store(file);
+
6888}
+
6889
+
6890void GeneratorKotlin::GenerateSender(const std::shared_ptr<Package>& p, bool final)
+
6891{
+
6892 std::string domain = (p->domain && !p->domain->empty()) ? (*p->domain + ".") : "";
+
6893 std::string package = *p->name;
+
6894
+
6895 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "fbe";
+
6896
+
6897 // Create package path
+
6898 CppCommon::Directory::CreateTree(path);
+
6899
+
6900 std::string listener = (final ? "IFinalSenderListener" : "ISenderListener");
+
6901 std::string sender = (final ? "FinalSender" : "Sender");
+
6902 std::string model = (final ? "FinalModel" : "Model");
+
6903
+
6904 // Generate the file
+
6905 CppCommon::Path file = path / (sender + ".kt");
+
6906 WriteBegin();
+
6907
+
6908 // Generate headers
+
6909 GenerateHeader(CppCommon::Path(_input).filename().string());
+
6910 GenerateImports(domain, package + ".fbe");
+
6911
+
6912 // Generate sender begin
+
6913 WriteLine();
+
6914 if (final)
+
6915 WriteLineIndent("// Fast Binary Encoding " + domain + *p->name + " final sender");
+
6916 else
+
6917 WriteLineIndent("// Fast Binary Encoding " + domain + *p->name + " sender");
+
6918 WriteLineIndent("@Suppress(\"MemberVisibilityCanBePrivate\", \"PropertyName\")");
+
6919 WriteLineIndent("open class " + sender + " : " + domain + "fbe.Sender, " + listener);
+
6920 WriteLineIndent("{");
+
6921 Indent(1);
+
6922
+
6923 // Generate imported senders accessors
+
6924 if (p->import)
+
6925 {
+
6926 WriteLineIndent("// Imported senders");
+
6927 for (const auto& import : p->import->imports)
+
6928 WriteLineIndent("val " + *import + "Sender: " + domain + *import + ".fbe." + sender);
+
6929 WriteLine();
+
6930 }
+
6931
+
6932 // Generate sender models accessors
+
6933 if (p->body)
+
6934 {
+
6935 WriteLineIndent("// Sender models accessors");
+
6936 for (const auto& s : p->body->structs)
+
6937 if (s->message)
+
6938 WriteLineIndent("val " + *s->name + "Model: " + *s->name + model);
+
6939 WriteLine();
+
6940 }
+
6941
+
6942 // Generate sender constructors
+
6943 WriteLineIndent("constructor() : super(" + std::string(final ? "true" : "false") + ")");
+
6944 WriteLineIndent("{");
+
6945 Indent(1);
+
6946 if (p->import)
+
6947 {
+
6948 for (const auto& import : p->import->imports)
+
6949 WriteLineIndent(*import + "Sender = " + domain + *import + ".fbe." + sender + "(buffer)");
+
6950 }
+
6951 if (p->body)
+
6952 {
+
6953 for (const auto& s : p->body->structs)
+
6954 if (s->message)
+
6955 WriteLineIndent(*s->name + "Model = " + *s->name + model + "(buffer)");
+
6956 }
+
6957 Indent(-1);
+
6958 WriteLineIndent("}");
+
6959 WriteLine();
+
6960 WriteLineIndent("constructor(buffer: " + domain + "fbe.Buffer) : super(buffer, " + std::string(final ? "true" : "false") + ")");
+
6961 WriteLineIndent("{");
+
6962 Indent(1);
+
6963 if (p->import)
+
6964 {
+
6965 for (const auto& import : p->import->imports)
+
6966 WriteLineIndent(*import + "Sender = " + domain + *import + ".fbe." + sender + "(buffer)");
+
6967 }
+
6968 if (p->body)
+
6969 {
+
6970 for (const auto& s : p->body->structs)
+
6971 if (s->message)
+
6972 WriteLineIndent(*s->name + "Model = " + *s->name + model + "(buffer)");
+
6973 }
+
6974 Indent(-1);
+
6975 WriteLineIndent("}");
+
6976 WriteLine();
+
6977
+
6978 bool messages = false;
+
6979 for (const auto& s : p->body->structs)
+
6980 if (s->message)
+
6981 messages = true;
+
6982
+
6983 // Generate generic sender method
+
6984 WriteLineIndent("fun send(obj: Any): Long");
+
6985 WriteLineIndent("{");
+
6986 Indent(1);
+
6987 WriteLineIndent("return sendListener(this, obj)");
+
6988 Indent(-1);
+
6989 WriteLineIndent("}");
+
6990 WriteLine();
+
6991 WriteLineIndent("@Suppress(\"JoinDeclarationAndAssignment\", \"UNUSED_PARAMETER\")");
+
6992 WriteLineIndent("fun sendListener(listener: " + listener + ", obj: Any): Long");
+
6993 WriteLineIndent("{");
+
6994 Indent(1);
+
6995 if (p->body && messages)
+
6996 {
+
6997 WriteLineIndent("when (obj)");
+
6998 WriteLineIndent("{");
+
6999 Indent(1);
+
7000 for (const auto& s : p->body->structs)
+
7001 {
+
7002 if (s->message)
+
7003 {
+
7004 std::string struct_name = domain + *p->name + "." + *s->name;
+
7005 WriteLineIndent("is " + struct_name + " -> if (obj.fbeType == " + *s->name + "Model.fbeType) return sendListener(listener, obj)");
+
7006 }
+
7007 }
+
7008 Indent(-1);
+
7009 WriteLineIndent("}");
+
7010 }
+
7011 WriteLine();
+
7012 if (p->import)
+
7013 {
+
7014 WriteLineIndent("// Try to send using imported senders");
+
7015 WriteLineIndent("@Suppress(\"CanBeVal\")");
+
7016 WriteLineIndent("var result: Long");
+
7017 for (const auto& import : p->import->imports)
+
7018 {
+
7019 WriteLineIndent("result = " + *import + "Sender.sendListener(listener, obj)");
+
7020 WriteLineIndent("if (result > 0)");
+
7021 Indent(1);
+
7022 WriteLineIndent("return result");
+
7023 Indent(-1);
+
7024 }
+
7025 WriteLine();
+
7026 }
+
7027 WriteLineIndent("return 0");
+
7028 Indent(-1);
+
7029 WriteLineIndent("}");
+
7030 WriteLine();
+
7031
+
7032 // Generate sender methods
+
7033 if (p->body)
+
7034 {
+
7035 for (const auto& s : p->body->structs)
+
7036 {
+
7037 if (s->message)
+
7038 {
+
7039 std::string struct_name = domain + *p->name + "." + *s->name;
+
7040 WriteLineIndent("fun send(value: " + struct_name + "): Long");
+
7041 WriteLineIndent("{");
+
7042 Indent(1);
+
7043 WriteLineIndent("return sendListener(this, value)");
+
7044 Indent(-1);
+
7045 WriteLineIndent("}");
+
7046 WriteLine();
+
7047 WriteLineIndent("fun sendListener(listener: " + listener + ", value: " + struct_name + "): Long");
+
7048 WriteLineIndent("{");
+
7049 Indent(1);
+
7050 WriteLineIndent("// Serialize the value into the FBE stream");
+
7051 WriteLineIndent("val serialized = " + *s->name + "Model.serialize(value)");
+
7052 WriteLineIndent("assert(serialized > 0) { \"" + struct_name + " serialization failed!\" }");
+
7053 WriteLineIndent("assert(" + *s->name + "Model.verify()) { \"" + struct_name + " validation failed!\" }");
+
7054 WriteLine();
+
7055 WriteLineIndent("// Log the value");
+
7056 WriteLineIndent("if (logging)");
+
7057 WriteLineIndent("{");
+
7058 Indent(1);
+
7059 WriteLineIndent("val message = value.toString()");
+
7060 WriteLineIndent("listener.onSendLog(message)");
+
7061 Indent(-1);
+
7062 WriteLineIndent("}");
+
7063 WriteLine();
+
7064 WriteLineIndent("// Send the serialized value");
+
7065 WriteLineIndent("return sendSerialized(listener, serialized)");
+
7066 Indent(-1);
+
7067 WriteLineIndent("}");
+
7068 }
+
7069 }
+
7070 }
+
7071
+
7072 // Generate sender end
+
7073 Indent(-1);
+
7074 WriteLineIndent("}");
+
7075
+
7076 // Generate footer
+
7077 GenerateFooter();
+
7078
+
7079 // Store the file
+
7080 WriteEnd();
+
7081 Store(file);
+
7082}
+
7083
+
7084void GeneratorKotlin::GenerateSenderListener(const std::shared_ptr<Package>& p, bool final)
+
7085{
+
7086 std::string domain = (p->domain && !p->domain->empty()) ? (*p->domain + ".") : "";
+
7087 std::string package = *p->name;
+
7088
+
7089 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "fbe";
+
7090
+
7091 // Create package path
+
7092 CppCommon::Directory::CreateTree(path);
+
7093
+
7094 std::string listener = (final ? "IFinalSenderListener" : "ISenderListener");
+
7095
+
7096 // Generate the file
+
7097 CppCommon::Path file = path / (listener + ".kt");
+
7098 WriteBegin();
+
7099
+
7100 // Generate headers
+
7101 GenerateHeader(CppCommon::Path(_input).filename().string());
+
7102 GenerateImports(domain, package + ".fbe");
+
7103
+
7104 // Generate sender listener begin
+
7105 WriteLine();
+
7106 if (final)
+
7107 WriteLineIndent("// Fast Binary Encoding " + domain + *p->name + " final sender listener interface");
+
7108 else
+
7109 WriteLineIndent("// Fast Binary Encoding " + domain + *p->name + " sender listener interface");
+
7110 WriteIndent("interface " + listener);
+
7111 if (p->import)
+
7112 {
+
7113 bool first = true;
+
7114 Write(" : ");
+
7115 for (const auto& import : p->import->imports)
+
7116 {
+
7117 Write((first ? "" : ", ") + domain + *import + ".fbe." + listener);
+
7118 first = false;
+
7119 }
+
7120 }
+
7121 else
+
7122 Write(" : " + domain + "fbe.ISenderListener");
+
7123 WriteLine();
+
7124 WriteLineIndent("{");
+
7125 Indent(1);
+
7126
+
7127 // Generate sender listener end
+
7128 Indent(-1);
+
7129 WriteLineIndent("}");
+
7130
+
7131 // Generate footer
+
7132 GenerateFooter();
+
7133
+
7134 // Store the file
+
7135 WriteEnd();
+
7136 Store(file);
+
7137}
+
7138
+
7139void GeneratorKotlin::GenerateReceiver(const std::shared_ptr<Package>& p, bool final)
+
7140{
+
7141 std::string domain = (p->domain && !p->domain->empty()) ? (*p->domain + ".") : "";
+
7142 std::string package = *p->name;
+
7143
+
7144 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "fbe";
+
7145
+
7146 // Create package path
+
7147 CppCommon::Directory::CreateTree(path);
+
7148
+
7149 std::string listener = (final ? "IFinalReceiverListener" : "IReceiverListener");
+
7150 std::string receiver = (final ? "FinalReceiver" : "Receiver");
+
7151 std::string model = (final ? "FinalModel" : "Model");
+
7152
+
7153 // Generate the file
+
7154 CppCommon::Path file = path / (receiver + ".kt");
+
7155 WriteBegin();
+
7156
+
7157 // Generate headers
+
7158 GenerateHeader(CppCommon::Path(_input).filename().string());
+
7159 GenerateImports(domain, package + ".fbe");
+
7160
+
7161 // Generate receiver begin
+
7162 WriteLine();
+
7163 if (final)
+
7164 WriteLineIndent("// Fast Binary Encoding " + domain + *p->name + " final receiver");
+
7165 else
+
7166 WriteLineIndent("// Fast Binary Encoding " + domain + *p->name + " receiver");
+
7167 WriteLineIndent("@Suppress(\"MemberVisibilityCanBePrivate\", \"PrivatePropertyName\", \"UNUSED_PARAMETER\")");
+
7168 WriteLineIndent("open class " + receiver + " : " + domain + "fbe.Receiver, " + listener);
+
7169 WriteLineIndent("{");
+
7170 Indent(1);
+
7171
+
7172 // Generate imported receivers accessors
+
7173 if (p->import)
+
7174 {
+
7175 WriteLineIndent("// Imported receivers");
+
7176 for (const auto& import : p->import->imports)
+
7177 WriteLineIndent("var " + *import + "Receiver: " + domain + *import + ".fbe." + receiver);
+
7178 WriteLine();
+
7179 }
+
7180
+
7181 // Generate receiver models accessors
+
7182 if (p->body)
+
7183 {
+
7184 WriteLineIndent("// Receiver values accessors");
+
7185 for (const auto& s : p->body->structs)
+
7186 {
+
7187 if (s->message)
+
7188 {
+
7189 std::string struct_name = domain + *p->name + "." + *s->name;
+
7190 WriteLineIndent("private val " + *s->name + "Value: " + struct_name);
+
7191 }
+
7192 }
+
7193 WriteLine();
+
7194 WriteLineIndent("// Receiver models accessors");
+
7195 for (const auto& s : p->body->structs)
+
7196 if (s->message)
+
7197 WriteLineIndent("private val " + *s->name + "Model: " + *s->name + model);
+
7198 WriteLine();
+
7199 }
+
7200
+
7201 // Generate receiver constructors
+
7202 WriteLineIndent("constructor() : super(" + std::string(final ? "true" : "false") + ")");
+
7203 WriteLineIndent("{");
+
7204 Indent(1);
+
7205 if (p->import)
+
7206 {
+
7207 for (const auto& import : p->import->imports)
+
7208 WriteLineIndent(*import + "Receiver = " + domain + *import + ".fbe." + receiver + "(buffer)");
+
7209 }
+
7210 if (p->body)
+
7211 {
+
7212 for (const auto& s : p->body->structs)
+
7213 {
+
7214 if (s->message)
+
7215 {
+
7216 std::string struct_name = domain + *p->name + "." + *s->name;
+
7217 WriteLineIndent(*s->name + "Value = " + struct_name + "()");
+
7218 WriteLineIndent(*s->name + "Model = " + *s->name + model + "()");
+
7219 }
+
7220 }
+
7221 }
+
7222 Indent(-1);
+
7223 WriteLineIndent("}");
+
7224 WriteLine();
+
7225 WriteLineIndent("constructor(buffer: " + domain + "fbe.Buffer) : super(buffer, " + std::string(final ? "true" : "false") + ")");
+
7226 WriteLineIndent("{");
+
7227 Indent(1);
+
7228 if (p->import)
+
7229 {
+
7230 for (const auto& import : p->import->imports)
+
7231 WriteLineIndent(*import + "Receiver = " + domain + *import + ".fbe." + receiver + "(buffer)");
+
7232 }
+
7233 if (p->body)
+
7234 {
+
7235 for (const auto& s : p->body->structs)
+
7236 {
+
7237 if (s->message)
+
7238 {
+
7239 std::string struct_name = domain + *p->name + "." + *s->name;
+
7240 WriteLineIndent(*s->name + "Value = " + struct_name + "()");
+
7241 WriteLineIndent(*s->name + "Model = " + *s->name + model + "()");
+
7242 }
+
7243 }
+
7244 }
+
7245 Indent(-1);
+
7246 WriteLineIndent("}");
+
7247 WriteLine();
+
7248
+
7249 bool messages = false;
+
7250 for (const auto& s : p->body->structs)
+
7251 if (s->message)
+
7252 messages = true;
+
7253
+
7254 // Generate receiver message handler
+
7255 WriteLineIndent("override fun onReceive(type: Long, buffer: ByteArray, offset: Long, size: Long): Boolean");
+
7256 WriteLineIndent("{");
+
7257 Indent(1);
+
7258 WriteLineIndent("return onReceiveListener(this, type, buffer, offset, size)");
+
7259 Indent(-1);
+
7260 WriteLineIndent("}");
+
7261 WriteLine();
+
7262 WriteLineIndent("open fun onReceiveListener(listener: " + listener + ", type: Long, buffer: ByteArray, offset: Long, size: Long): Boolean");
+
7263 WriteLineIndent("{");
+
7264 Indent(1);
+
7265 if (p->body && messages)
+
7266 {
+
7267 WriteLineIndent("when (type)");
+
7268 WriteLineIndent("{");
+
7269 Indent(1);
+
7270 for (const auto& s : p->body->structs)
+
7271 {
+
7272 if (s->message)
+
7273 {
+
7274 WriteLineIndent(domain + package + ".fbe." + *s->name + model + ".fbeTypeConst ->");
+
7275 WriteLineIndent("{");
+
7276 Indent(1);
+
7277 WriteLineIndent("// Deserialize the value from the FBE stream");
+
7278 WriteLineIndent(*s->name + "Model.attach(buffer, offset)");
+
7279 WriteLineIndent("assert(" + *s->name + "Model.verify()) { \"" + domain + *p->name + "." + *s->name + " validation failed!\" }");
+
7280 WriteLineIndent("val deserialized = " + *s->name + "Model.deserialize(" + *s->name + "Value)");
+
7281 WriteLineIndent("assert(deserialized > 0) { \"" + domain + *p->name + "." + *s->name + " deserialization failed!\" }");
+
7282 WriteLine();
+
7283 WriteLineIndent("// Log the value");
+
7284 WriteLineIndent("if (logging)");
+
7285 WriteLineIndent("{");
+
7286 Indent(1);
+
7287 WriteLineIndent("val message = " + *s->name + "Value.toString()");
+
7288 WriteLineIndent("onReceiveLog(message)");
+
7289 Indent(-1);
+
7290 WriteLineIndent("}");
+
7291 WriteLine();
+
7292 WriteLineIndent("// Call receive handler with deserialized value");
+
7293 WriteLineIndent("listener.onReceive(" + *s->name + "Value)");
+
7294 WriteLineIndent("return true");
+
7295 Indent(-1);
+
7296 WriteLineIndent("}");
+
7297 }
+
7298 }
+
7299 Indent(-1);
+
7300 WriteLineIndent("}");
+
7301 }
+
7302 if (p->import)
+
7303 {
+
7304 WriteLine();
+
7305 for (const auto& import : p->import->imports)
+
7306 {
+
7307 WriteLineIndent("if (" + *import + "Receiver.onReceiveListener(listener, type, buffer, offset, size))");
+
7308 Indent(1);
+
7309 WriteLineIndent("return true");
+
7310 Indent(-1);
+
7311 }
+
7312 }
+
7313 WriteLine();
+
7314 WriteLineIndent("return false");
+
7315 Indent(-1);
+
7316 WriteLineIndent("}");
+
7317
+
7318 // Generate receiver end
+
7319 Indent(-1);
+
7320 WriteLineIndent("}");
+
7321
+
7322 // Generate footer
+
7323 GenerateFooter();
+
7324
+
7325 // Store the file
+
7326 WriteEnd();
+
7327 Store(file);
+
7328}
+
7329
+
7330void GeneratorKotlin::GenerateReceiverListener(const std::shared_ptr<Package>& p, bool final)
+
7331{
+
7332 std::string domain = (p->domain && !p->domain->empty()) ? (*p->domain + ".") : "";
+
7333 std::string package = *p->name;
+
7334
+
7335 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "fbe";
+
7336
+
7337 // Create package path
+
7338 CppCommon::Directory::CreateTree(path);
+
7339
+
7340 std::string listener = (final ? "IFinalReceiverListener" : "IReceiverListener");
+
7341
+
7342 // Generate the file
+
7343 CppCommon::Path file = path / (listener + ".kt");
+
7344 WriteBegin();
+
7345
+
7346 // Generate headers
+
7347 GenerateHeader(CppCommon::Path(_input).filename().string());
+
7348 GenerateImports(domain, package + ".fbe");
+
7349
+
7350 // Generate receiver listener begin
+
7351 WriteLine();
+
7352 if (final)
+
7353 WriteLineIndent("// Fast Binary Encoding " + domain + *p->name + " final receiver listener interface");
+
7354 else
+
7355 WriteLineIndent("// Fast Binary Encoding " + domain + *p->name + " receiver listener interface");
+
7356 WriteIndent("interface " + listener);
+
7357 if (p->import)
+
7358 {
+
7359 bool first = true;
+
7360 Write(" : ");
+
7361 for (const auto& import : p->import->imports)
+
7362 {
+
7363 Write((first ? "" : ", ") + domain + *import + ".fbe." + listener);
+
7364 first = false;
+
7365 }
+
7366 }
+
7367 else
+
7368 Write(" : " + domain + "fbe.IReceiverListener");
+
7369 WriteLine();
+
7370 WriteLineIndent("{");
+
7371 Indent(1);
+
7372
+
7373 // Generate receiver listener handlers
+
7374 if (p->body)
+
7375 {
+
7376 for (const auto& s : p->body->structs)
+
7377 {
+
7378 if (s->message)
+
7379 {
+
7380 std::string struct_name = domain + *p->name + "." + *s->name;
+
7381 WriteLineIndent("fun onReceive(value: " + struct_name + ") {}");
+
7382 }
+
7383 }
+
7384 }
+
7385
+
7386 // Generate receiver listener end
+
7387 Indent(-1);
+
7388 WriteLineIndent("}");
+
7389
+
7390 // Generate footer
+
7391 GenerateFooter();
+
7392
+
7393 // Store the file
+
7394 WriteEnd();
+
7395 Store(file);
+
7396}
+
7397
+
7398void GeneratorKotlin::GenerateProxy(const std::shared_ptr<Package>& p, bool final)
+
7399{
+
7400 std::string domain = (p->domain && !p->domain->empty()) ? (*p->domain + ".") : "";
+
7401 std::string package = *p->name;
+
7402
+
7403 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "fbe";
+
7404
+
7405 // Create package path
+
7406 CppCommon::Directory::CreateTree(path);
+
7407
+
7408 std::string listener = (final ? "IFinalProxyListener" : "IProxyListener");
+
7409 std::string proxy = (final ? "FinalProxy" : "Proxy");
+
7410 std::string model = (final ? "FinalModel" : "Model");
+
7411
+
7412 // Generate the file
+
7413 CppCommon::Path file = path / (proxy + ".kt");
+
7414 WriteBegin();
+
7415
+
7416 // Generate headers
+
7417 GenerateHeader(CppCommon::Path(_input).filename().string());
+
7418 GenerateImports(domain, package + ".fbe");
+
7419
+
7420 // Generate proxy begin
+
7421 WriteLine();
+
7422 if (final)
+
7423 WriteLineIndent("// Fast Binary Encoding " + domain + *p->name + " final proxy");
+
7424 else
+
7425 WriteLineIndent("// Fast Binary Encoding " + domain + *p->name + " proxy");
+
7426 WriteLineIndent("@Suppress(\"MemberVisibilityCanBePrivate\", \"PrivatePropertyName\", \"UNUSED_PARAMETER\")");
+
7427 WriteLineIndent("open class " + proxy + " : " + domain + "fbe.Receiver, " + listener);
+
7428 WriteLineIndent("{");
+
7429 Indent(1);
+
7430
+
7431 // Generate imported proxy accessors
+
7432 if (p->import)
+
7433 {
+
7434 WriteLineIndent("// Imported proxy");
+
7435 for (const auto& import : p->import->imports)
+
7436 WriteLineIndent("var " + *import + "Proxy: " + domain + *import + ".fbe." + proxy);
+
7437 WriteLine();
+
7438 }
+
7439
+
7440 // Generate proxy models accessors
+
7441 if (p->body)
+
7442 {
+
7443 WriteLineIndent("// Proxy models accessors");
+
7444 for (const auto& s : p->body->structs)
+
7445 if (s->message)
+
7446 WriteLineIndent("private val " + *s->name + "Model: " + *s->name + model);
+
7447 WriteLine();
+
7448 }
+
7449
+
7450 // Generate proxy constructors
+
7451 WriteLineIndent("constructor() : super(" + std::string(final ? "true" : "false") + ")");
+
7452 WriteLineIndent("{");
+
7453 Indent(1);
+
7454 if (p->import)
+
7455 {
+
7456 for (const auto& import : p->import->imports)
+
7457 WriteLineIndent(*import + "Proxy = " + domain + *import + ".fbe." + proxy + "(buffer)");
+
7458 }
+
7459 if (p->body)
+
7460 {
+
7461 for (const auto& s : p->body->structs)
+
7462 if (s->message)
+
7463 WriteLineIndent(*s->name + "Model = " + *s->name + model + "()");
+
7464 }
+
7465 Indent(-1);
+
7466 WriteLineIndent("}");
+
7467 WriteLine();
+
7468 WriteLineIndent("constructor(buffer: " + domain + "fbe.Buffer) : super(buffer, " + std::string(final ? "true" : "false") + ")");
+
7469 WriteLineIndent("{");
+
7470 Indent(1);
+
7471 if (p->import)
+
7472 {
+
7473 for (const auto& import : p->import->imports)
+
7474 WriteLineIndent(*import + "Proxy = " + domain + *import + ".fbe." + proxy + "(buffer)");
+
7475 }
+
7476 if (p->body)
+
7477 {
+
7478 for (const auto& s : p->body->structs)
+
7479 if (s->message)
+
7480 WriteLineIndent(*s->name + "Model = " + *s->name + model + "()");
+
7481 }
+
7482 Indent(-1);
+
7483 WriteLineIndent("}");
+
7484 WriteLine();
+
7485
+
7486 bool messages = false;
+
7487 for (const auto& s : p->body->structs)
+
7488 if (s->message)
+
7489 messages = true;
+
7490
+
7491 // Generate proxy message handler
+
7492 WriteLineIndent("override fun onReceive(type: Long, buffer: ByteArray, offset: Long, size: Long): Boolean");
+
7493 WriteLineIndent("{");
+
7494 Indent(1);
+
7495 WriteLineIndent("return onReceiveListener(this, type, buffer, offset, size)");
+
7496 Indent(-1);
+
7497 WriteLineIndent("}");
+
7498 WriteLine();
+
7499 WriteLineIndent("open fun onReceiveListener(listener: " + listener + ", type: Long, buffer: ByteArray, offset: Long, size: Long): Boolean");
+
7500 WriteLineIndent("{");
+
7501 Indent(1);
+
7502 if (p->body && messages)
+
7503 {
+
7504 WriteLineIndent("when (type)");
+
7505 WriteLineIndent("{");
+
7506 Indent(1);
+
7507 for (const auto& s : p->body->structs)
+
7508 {
+
7509 if (s->message)
+
7510 {
+
7511 WriteLineIndent(domain + package + ".fbe." + *s->name + model + ".fbeTypeConst ->");
+
7512 WriteLineIndent("{");
+
7513 Indent(1);
+
7514 WriteLineIndent("// Attach the FBE stream to the proxy model");
+
7515 WriteLineIndent(*s->name + "Model.attach(buffer, offset)");
+
7516 WriteLineIndent("assert(" + *s->name + "Model.verify()) { \"" + domain + *p->name + "." + *s->name + " validation failed!\" }");
+
7517 WriteLine();
+
7518 WriteLineIndent("val fbeBegin = " + *s->name + "Model.model.getBegin()");
+
7519 WriteLineIndent("if (fbeBegin == 0L)");
+
7520 Indent(1);
+
7521 WriteLineIndent("return false");
+
7522 Indent(-1);
+
7523 WriteLineIndent("// Call proxy handler");
+
7524 WriteLineIndent("listener.onProxy(" + *s->name + "Model, type, buffer, offset, size)");
+
7525 WriteLineIndent(*s->name + "Model.model.getEnd(fbeBegin)");
+
7526 WriteLineIndent("return true");
+
7527 Indent(-1);
+
7528 WriteLineIndent("}");
+
7529 }
+
7530 }
+
7531 Indent(-1);
+
7532 WriteLineIndent("}");
+
7533 }
+
7534 if (p->import)
+
7535 {
+
7536 WriteLine();
+
7537 for (const auto& import : p->import->imports)
+
7538 {
+
7539 WriteLineIndent("if (" + *import + "Proxy.onReceiveListener(listener, type, buffer, offset, size))");
+
7540 Indent(1);
+
7541 WriteLineIndent("return true");
+
7542 Indent(-1);
+
7543 }
+
7544 }
+
7545 WriteLine();
+
7546 WriteLineIndent("return false");
+
7547 Indent(-1);
+
7548 WriteLineIndent("}");
+
7549
+
7550 // Generate proxy end
+
7551 Indent(-1);
+
7552 WriteLineIndent("}");
+
7553
+
7554 // Generate footer
+
7555 GenerateFooter();
+
7556
+
7557 // Store the file
+
7558 WriteEnd();
+
7559 Store(file);
+
7560}
+
7561
+
7562void GeneratorKotlin::GenerateProxyListener(const std::shared_ptr<Package>& p, bool final)
+
7563{
+
7564 std::string domain = (p->domain && !p->domain->empty()) ? (*p->domain + ".") : "";
+
7565 std::string package = *p->name;
+
7566
+
7567 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "fbe";
+
7568
+
7569 // Create package path
+
7570 CppCommon::Directory::CreateTree(path);
+
7571
+
7572 std::string listener = (final ? "IFinalProxyListener" : "IProxyListener");
+
7573 std::string model = (final ? "FinalModel" : "Model");
+
7574
+
7575 // Generate the file
+
7576 CppCommon::Path file = path / (listener + ".kt");
+
7577 WriteBegin();
+
7578
+
7579 // Generate headers
+
7580 GenerateHeader(CppCommon::Path(_input).filename().string());
+
7581 GenerateImports(domain, package + ".fbe");
+
7582
+
7583 // Generate proxy listener begin
+
7584 WriteLine();
+
7585 if (final)
+
7586 WriteLineIndent("// Fast Binary Encoding " + domain + *p->name + " final proxy listener interface");
+
7587 else
+
7588 WriteLineIndent("// Fast Binary Encoding " + domain + *p->name + " proxy listener interface");
+
7589 WriteIndent("interface " + listener);
+
7590 if (p->import)
+
7591 {
+
7592 bool first = true;
+
7593 WriteIndent(" : ");
+
7594 for (const auto& import : p->import->imports)
+
7595 {
+
7596 WriteLineIndent((first ? "" : ", ") + domain + *import + ".fbe." + listener);
+
7597 first = false;
+
7598 }
+
7599 }
+
7600 else
+
7601 WriteIndent(" : " + domain + "fbe.IReceiverListener");
+
7602 WriteLine();
+
7603 WriteLineIndent("{");
+
7604 Indent(1);
+
7605
+
7606 // Generate proxy listener handlers
+
7607 if (p->body)
+
7608 {
+
7609 for (const auto& s : p->body->structs)
+
7610 {
+
7611 if (s->message)
+
7612 {
+
7613 std::string struct_model = *s->name + model;
+
7614 WriteLineIndent("fun onProxy(model: " + struct_model + ", type: Long, buffer: ByteArray, offset: Long, size: Long) {}");
+
7615 }
+
7616 }
+
7617 }
+
7618
+
7619 // Generate proxy listener end
+
7620 Indent(-1);
+
7621 WriteLineIndent("}");
+
7622
+
7623 // Generate footer
+
7624 GenerateFooter();
+
7625
+
7626 // Store the file
+
7627 WriteEnd();
+
7628 Store(file);
+
7629}
+
7630
+
7631void GeneratorKotlin::GenerateClient(const std::shared_ptr<Package>& p, bool final)
+
7632{
+
7633 std::string domain = (p->domain && !p->domain->empty()) ? (*p->domain + ".") : "";
+
7634 std::string package = *p->name;
+
7635
+
7636 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "fbe";
+
7637
+
7638 // Create package path
+
7639 CppCommon::Directory::CreateTree(path);
+
7640
+
7641 std::string listener = (final ? "IFinalClientListener" : "IClientListener");
+
7642 std::string client = (final ? "FinalClient" : "Client");
+
7643 std::string model = (final ? "FinalModel" : "Model");
+
7644
+
7645 // Generate the file
+
7646 CppCommon::Path file = path / (client + ".kt");
+
7647 WriteBegin();
+
7648
+
7649 // Generate headers
+
7650 GenerateHeader(CppCommon::Path(_input).filename().string());
+
7651 GenerateImports(domain, package + ".fbe");
+
7652
+
7653 // Generate client begin
+
7654 WriteLine();
+
7655 if (final)
+
7656 WriteLineIndent("// Fast Binary Encoding " + domain + *p->name + " final client");
+
7657 else
+
7658 WriteLineIndent("// Fast Binary Encoding " + domain + *p->name + " client");
+
7659 WriteLineIndent("@Suppress(\"MemberVisibilityCanBePrivate\", \"PropertyName\")");
+
7660 WriteLineIndent("open class " + client + " : " + domain + "fbe.Client, " + listener);
+
7661 WriteLineIndent("{");
+
7662 Indent(1);
+
7663
+
7664 // Generate imported clients accessors
+
7665 if (p->import)
+
7666 {
+
7667 WriteLineIndent("// Imported clients");
+
7668 for (const auto& import : p->import->imports)
+
7669 WriteLineIndent("val " + *import + "Client: " + domain + *import + ".fbe." + client);
+
7670 WriteLine();
+
7671 }
+
7672
+
7673 // Generate client sender models accessors
+
7674 if (p->body)
+
7675 {
+
7676 WriteLineIndent("// Client sender models accessors");
+
7677 for (const auto& s : p->body->structs)
+
7678 if (s->message)
+
7679 WriteLineIndent("val " + *s->name + "SenderModel: " + *s->name + model);
+
7680 WriteLine();
+
7681 }
+
7682
+
7683 // Generate client receiver models accessors
+
7684 if (p->body)
+
7685 {
+
7686 WriteLineIndent("// Client receiver values accessors");
+
7687 for (const auto& s : p->body->structs)
+
7688 {
+
7689 if (s->message)
+
7690 {
+
7691 std::string struct_name = domain + *p->name + "." + *s->name;
+
7692 WriteLineIndent("private val " + *s->name + "ReceiverValue: " + struct_name);
+
7693 }
+
7694 }
+
7695 WriteLine();
+
7696 WriteLineIndent("// Client receiver models accessors");
+
7697 for (const auto& s : p->body->structs)
+
7698 if (s->message)
+
7699 WriteLineIndent("private val " + *s->name + "ReceiverModel: " + *s->name + model);
+
7700 WriteLine();
+
7701 }
+
7702
+
7703 // Generate client constructors
+
7704 WriteLineIndent("constructor() : super(" + std::string(final ? "true" : "false") + ")");
+
7705 WriteLineIndent("{");
+
7706 Indent(1);
+
7707 if (p->import)
+
7708 for (const auto& import : p->import->imports)
+
7709 WriteLineIndent(*import + "Client = " + domain + *import + ".fbe." + client + "(sendBuffer, receiveBuffer)");
+
7710 if (p->body)
+
7711 {
+
7712 for (const auto& s : p->body->structs)
+
7713 {
+
7714 if (s->message)
+
7715 {
+
7716 std::string struct_name = domain + *p->name + "." + *s->name;
+
7717 WriteLineIndent(*s->name + "SenderModel = " + *s->name + model + "(sendBuffer)");
+
7718 WriteLineIndent(*s->name + "ReceiverValue = " + struct_name + "()");
+
7719 WriteLineIndent(*s->name + "ReceiverModel = " + *s->name + model + "()");
+
7720 }
+
7721 }
+
7722 }
+
7723 Indent(-1);
+
7724 WriteLineIndent("}");
+
7725 WriteLine();
+
7726 WriteLineIndent("constructor(sendBuffer: " + domain + "fbe.Buffer, receiveBuffer: " + domain + "fbe.Buffer) : super(sendBuffer, receiveBuffer, " + std::string(final ? "true" : "false") + ")");
+
7727 WriteLineIndent("{");
+
7728 Indent(1);
+
7729 if (p->import)
+
7730 for (const auto& import : p->import->imports)
+
7731 WriteLineIndent(*import + "Client = " + domain + *import + ".fbe." + client + "(sendBuffer, receiveBuffer)");
+
7732 if (p->body)
+
7733 {
+
7734 for (const auto& s : p->body->structs)
+
7735 {
+
7736 if (s->message)
+
7737 {
+
7738 std::string struct_name = domain + *p->name + "." + *s->name;
+
7739 WriteLineIndent(*s->name + "SenderModel = " + *s->name + model + "(sendBuffer)");
+
7740 WriteLineIndent(*s->name + "ReceiverValue = " + struct_name + "()");
+
7741 WriteLineIndent(*s->name + "ReceiverModel = " + *s->name + model + "()");
+
7742 }
+
7743 }
+
7744 }
+
7745 Indent(-1);
+
7746 WriteLineIndent("}");
+
7747 WriteLine();
+
7748
+
7749 bool messages = false;
+
7750 for (const auto& s : p->body->structs)
+
7751 if (s->message)
+
7752 messages = true;
+
7753
+
7754 // Generate generic client send method
+
7755 WriteLineIndent("fun send(obj: Any): Long");
+
7756 WriteLineIndent("{");
+
7757 Indent(1);
+
7758 WriteLineIndent("return sendListener(this, obj)");
+
7759 Indent(-1);
+
7760 WriteLineIndent("}");
+
7761 WriteLine();
+
7762 WriteLineIndent("@Suppress(\"JoinDeclarationAndAssignment\", \"UNUSED_PARAMETER\")");
+
7763 WriteLineIndent("fun sendListener(listener: " + listener + ", obj: Any): Long");
+
7764 WriteLineIndent("{");
+
7765 Indent(1);
+
7766 if (p->body && messages)
+
7767 {
+
7768 WriteLineIndent("when (obj)");
+
7769 WriteLineIndent("{");
+
7770 Indent(1);
+
7771 for (const auto& s : p->body->structs)
+
7772 {
+
7773 if (s->message)
+
7774 {
+
7775 std::string struct_name = domain + *p->name + "." + *s->name;
+
7776 WriteLineIndent("is " + struct_name + " -> if (obj.fbeType == " + *s->name + "SenderModel.fbeType) return sendListener(listener, obj)");
+
7777 }
+
7778 }
+
7779 Indent(-1);
+
7780 WriteLineIndent("}");
+
7781 }
+
7782 WriteLine();
+
7783 if (p->import)
+
7784 {
+
7785 WriteLineIndent("// Try to send using imported clients");
+
7786 WriteLineIndent("@Suppress(\"CanBeVal\")");
+
7787 WriteLineIndent("var result: Long");
+
7788 for (const auto& import : p->import->imports)
+
7789 {
+
7790 WriteLineIndent("result = " + *import + "Client.sendListener(listener, obj)");
+
7791 WriteLineIndent("if (result > 0)");
+
7792 Indent(1);
+
7793 WriteLineIndent("return result");
+
7794 Indent(-1);
+
7795 }
+
7796 WriteLine();
+
7797 }
+
7798 WriteLineIndent("return 0");
+
7799 Indent(-1);
+
7800 WriteLineIndent("}");
+
7801 WriteLine();
+
7802
+
7803 // Generate client send methods
+
7804 if (p->body)
+
7805 {
+
7806 for (const auto& s : p->body->structs)
+
7807 {
+
7808 if (s->message)
+
7809 {
+
7810 std::string struct_name = domain + *p->name + "." + *s->name;
+
7811 WriteLineIndent("fun send(value: " + struct_name + "): Long");
+
7812 WriteLineIndent("{");
+
7813 Indent(1);
+
7814 WriteLineIndent("return sendListener(this, value)");
+
7815 Indent(-1);
+
7816 WriteLineIndent("}");
+
7817 WriteLine();
+
7818 WriteLineIndent("fun sendListener(listener: " + listener + ", value: " + struct_name + "): Long");
+
7819 WriteLineIndent("{");
+
7820 Indent(1);
+
7821 WriteLineIndent("// Serialize the value into the FBE stream");
+
7822 WriteLineIndent("val serialized = " + *s->name + "SenderModel.serialize(value)");
+
7823 WriteLineIndent("assert(serialized > 0) { \"" + struct_name + " serialization failed!\" }");
+
7824 WriteLineIndent("assert(" + *s->name + "SenderModel.verify()) { \"" + struct_name + " validation failed!\" }");
+
7825 WriteLine();
+
7826 WriteLineIndent("// Log the value");
+
7827 WriteLineIndent("if (logging)");
+
7828 WriteLineIndent("{");
+
7829 Indent(1);
+
7830 WriteLineIndent("val message = value.toString()");
+
7831 WriteLineIndent("listener.onSendLog(message)");
+
7832 Indent(-1);
+
7833 WriteLineIndent("}");
+
7834 WriteLine();
+
7835 WriteLineIndent("// Send the serialized value");
+
7836 WriteLineIndent("return sendSerialized(listener, serialized)");
+
7837 Indent(-1);
+
7838 WriteLineIndent("}");
+
7839 }
+
7840 }
+
7841 }
+
7842
+
7843 WriteLine();
+
7844
+
7845 // Generate client receive message handler
+
7846 WriteLineIndent("override fun onReceive(type: Long, buffer: ByteArray, offset: Long, size: Long): Boolean");
+
7847 WriteLineIndent("{");
+
7848 Indent(1);
+
7849 WriteLineIndent("return onReceiveListener(this, type, buffer, offset, size)");
+
7850 Indent(-1);
+
7851 WriteLineIndent("}");
+
7852 WriteLine();
+
7853 WriteLineIndent("open fun onReceiveListener(listener: " + listener + ", type: Long, buffer: ByteArray, offset: Long, size: Long): Boolean");
+
7854 WriteLineIndent("{");
+
7855 Indent(1);
+
7856 if (p->body && messages)
+
7857 {
+
7858 WriteLineIndent("when (type)");
+
7859 WriteLineIndent("{");
+
7860 Indent(1);
+
7861 for (const auto& s : p->body->structs)
+
7862 {
+
7863 if (s->message)
+
7864 {
+
7865 WriteLineIndent(domain + package + ".fbe." + *s->name + model + ".fbeTypeConst ->");
+
7866 WriteLineIndent("{");
+
7867 Indent(1);
+
7868 WriteLineIndent("// Deserialize the value from the FBE stream");
+
7869 WriteLineIndent(*s->name + "ReceiverModel.attach(buffer, offset)");
+
7870 WriteLineIndent("assert(" + *s->name + "ReceiverModel.verify()) { \"" + domain + *p->name + "." + *s->name + " validation failed!\" }");
+
7871 WriteLineIndent("val deserialized = " + *s->name + "ReceiverModel.deserialize(" + *s->name + "ReceiverValue)");
+
7872 WriteLineIndent("assert(deserialized > 0) { \"" + domain + *p->name + "." + *s->name + " deserialization failed!\" }");
+
7873 WriteLine();
+
7874 WriteLineIndent("// Log the value");
+
7875 WriteLineIndent("if (logging)");
+
7876 WriteLineIndent("{");
+
7877 Indent(1);
+
7878 WriteLineIndent("val message = " + *s->name + "ReceiverValue.toString()");
+
7879 WriteLineIndent("onReceiveLog(message)");
+
7880 Indent(-1);
+
7881 WriteLineIndent("}");
+
7882 WriteLine();
+
7883 WriteLineIndent("// Call receive handler with deserialized value");
+
7884 WriteLineIndent("listener.onReceive(" + *s->name + "ReceiverValue)");
+
7885 WriteLineIndent("return true");
+
7886 Indent(-1);
+
7887 WriteLineIndent("}");
+
7888 }
+
7889 }
+
7890 Indent(-1);
+
7891 WriteLineIndent("}");
+
7892 }
+
7893 if (p->import)
+
7894 {
+
7895 WriteLine();
+
7896 for (const auto& import : p->import->imports)
+
7897 {
+
7898 WriteLineIndent("if (" + *import + "Client.onReceiveListener(listener, type, buffer, offset, size))");
+
7899 Indent(1);
+
7900 WriteLineIndent("return true");
+
7901 Indent(-1);
+
7902 }
+
7903 }
+
7904 WriteLine();
+
7905 WriteLineIndent("return false");
+
7906 Indent(-1);
+
7907 WriteLineIndent("}");
+
7908
+
7909 // Generate client end
+
7910 Indent(-1);
+
7911 WriteLineIndent("}");
+
7912
+
7913 // Generate footer
+
7914 GenerateFooter();
+
7915
+
7916 // Store the file
+
7917 WriteEnd();
+
7918 Store(file);
+
7919}
+
7920
+
7921void GeneratorKotlin::GenerateClientListener(const std::shared_ptr<Package>& p, bool final)
+
7922{
+
7923 std::string domain = (p->domain && !p->domain->empty()) ? (*p->domain + ".") : "";
+
7924 std::string package = *p->name;
+
7925
+
7926 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "fbe";
+
7927
+
7928 // Create package path
+
7929 CppCommon::Directory::CreateTree(path);
+
7930
+
7931 std::string listener = (final ? "IFinalClientListener" : "IClientListener");
+
7932 std::string sender = (final ? "IFinalSenderListener" : "ISenderListener");
+
7933 std::string receiver = (final ? "IFinalReceiverListener" : "IReceiverListener");
+
7934
+
7935 // Generate the file
+
7936 CppCommon::Path file = path / (listener + ".kt");
+
7937 WriteBegin();
+
7938
+
7939 // Generate headers
+
7940 GenerateHeader(CppCommon::Path(_input).filename().string());
+
7941 GenerateImports(domain, package + ".fbe");
+
7942
+
7943 // Generate client listener begin
+
7944 WriteLine();
+
7945 if (final)
+
7946 WriteLineIndent("// Fast Binary Encoding " + domain + *p->name + " final client listener interface");
+
7947 else
+
7948 WriteLineIndent("// Fast Binary Encoding " + domain + *p->name + " client listener interface");
+
7949 WriteIndent("interface " + listener);
+
7950 if (p->import)
+
7951 {
+
7952 bool first = true;
+
7953 Write(" : ");
+
7954 for (const auto& import : p->import->imports)
+
7955 {
+
7956 Write((first ? "" : ", ") + domain + *import + ".fbe." + listener);
+
7957 first = false;
+
7958 }
+
7959 }
+
7960 else
+
7961 Write(" : " + domain + "fbe.IClientListener");
+
7962 Write(", " + sender + ", " + receiver);
+
7963 WriteLine();
+
7964 WriteLineIndent("{");
+
7965 Indent(1);
+
7966
+
7967 // Generate client listener end
+
7968 Indent(-1);
+
7969 WriteLineIndent("}");
+
7970
+
7971 // Generate footer
+
7972 GenerateFooter();
+
7973
+
7974 // Store the file
+
7975 WriteEnd();
+
7976 Store(file);
+
7977}
+
7978
+
7979void GeneratorKotlin::GenerateJson(const std::shared_ptr<Package>& p)
+
7980{
+
7981 std::string domain = (p->domain && !p->domain->empty()) ? (*p->domain + ".") : "";
+
7982 std::string package = *p->name;
+
7983
+
7984 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "fbe";
+
7985
+
7986 // Create package path
+
7987 CppCommon::Directory::CreateTree(path);
+
7988
+
7989 // Generate the file
+
7990 CppCommon::Path file = path / "Json.kt";
+
7991 WriteBegin();
+
7992
+
7993 // Generate headers
+
7994 GenerateHeader(CppCommon::Path(_input).filename().string());
+
7995 GenerateImports(domain, package + ".fbe");
+
7996
+
7997 // Generate JSON engine begin
+
7998 WriteLine();
+
7999 WriteLineIndent("// Fast Binary Encoding " + *p->name + " JSON engine");
+
8000 WriteLineIndent("object Json");
+
8001 WriteLineIndent("{");
+
8002 Indent(1);
+
8003
+
8004 WriteLineIndent("// Get the JSON engine");
+
8005 WriteLineIndent("val engine: com.google.gson.Gson = register(com.google.gson.GsonBuilder()).create()");
+
8006 WriteLine();
+
8007
+
8008 // Generate JSON engine Register() method
+
8009 WriteLineIndent("@Suppress(\"MemberVisibilityCanBePrivate\")");
+
8010 WriteLineIndent("fun register(builder: com.google.gson.GsonBuilder): com.google.gson.GsonBuilder");
+
8011 WriteLineIndent("{");
+
8012 Indent(1);
+
8013 WriteLineIndent(domain + "fbe.Json.register(builder)");
+
8014 if (p->import)
+
8015 {
+
8016 for (const auto& import : p->import->imports)
+
8017 WriteLineIndent(domain + *import + ".fbe.Json.register(builder)");
+
8018 }
+
8019 if (p->body)
+
8020 {
+
8021 for (const auto& e : p->body->enums)
+
8022 WriteLineIndent("builder.registerTypeAdapter(" + domain + package + "." + *e->name + "::class.java, " + *e->name + "Json())");
+
8023 for (const auto& f : p->body->flags)
+
8024 WriteLineIndent("builder.registerTypeAdapter(" + domain + package + "." + *f->name + "::class.java, " + *f->name + "Json())");
+
8025 }
+
8026 WriteLineIndent("return builder");
+
8027 Indent(-1);
+
8028 WriteLineIndent("}");
+
8029
+
8030 // Generate JSON engine end
+
8031 Indent(-1);
+
8032 WriteLineIndent("}");
+
8033
+
8034 // Generate footer
+
8035 GenerateFooter();
+
8036
+
8037 // Store the file
+
8038 WriteEnd();
+
8039 Store(file);
+
8040}
+
8041
+
8042bool GeneratorKotlin::IsKnownType(const std::string& type)
+
8043{
+
8044 return ((type == "bool") ||
+
8045 (type == "byte") || (type == "bytes") ||
+
8046 (type == "char") || (type == "wchar") ||
+
8047 (type == "int8") || (type == "uint8") ||
+
8048 (type == "int16") || (type == "uint16") ||
+
8049 (type == "int32") || (type == "uint32") ||
+
8050 (type == "int64") || (type == "uint64") ||
+
8051 (type == "float") || (type == "double") ||
+
8052 (type == "decimal") || (type == "string") ||
+
8053 (type == "timestamp") || (type == "uuid"));
+
8054}
+
8055
+
8056bool GeneratorKotlin::IsImportedType(const std::string& type)
+
8057{
+
8058 size_t pos = type.find_last_of('.');
+
8059 return (pos != std::string::npos);
+
8060}
+
8061
+
8062bool GeneratorKotlin::IsPackageType(const std::string& type)
+
8063{
+
8064 if (IsKnownType(type) || IsImportedType(type))
+
8065 return true;
+
8066
+
8067 return ((type == "Boolean") || (type == "Boolean?") ||
+
8068 (type == "Byte") || (type == "Byte?") || (type == "ByteArray") || (type == "ByteArray?") ||
+
8069 (type == "Char") || (type == "Char?") ||
+
8070 (type == "Byte") || (type == "Byte?") || (type == "UByte") || (type == "UByte?") ||
+
8071 (type == "Short") || (type == "Short?") || (type == "UShort") || (type == "UShort?") ||
+
8072 (type == "Int") || (type == "Int?") || (type == "UInt") || (type == "UInt?") ||
+
8073 (type == "Long") || (type == "Long?") || (type == "ULong") || (type == "ULong?") ||
+
8074 (type == "Float") || (type == "Float?") || (type == "Double") || (type == "Double?") ||
+
8075 (type == "java.math.BigDecimal") || (type == "java.math.BigDecimal?") || (type == "java.math.BigInteger") || (type == "java.math.BigInteger?") ||
+
8076 (type == "String") || (type == "String?") || (type == "java.util.Date") || (type == "java.util.Date?") || (type == "java.time.Instant") || (type == "java.time.Instant?") || (type == "java.util.UUID") || (type == "java.util.UUID?"));
+
8077}
+
8078
+
8079bool GeneratorKotlin::IsPrimitiveType(const std::string& type, bool optional)
+
8080{
+
8081 return ((type == "bool") || (type == "byte") ||
+
8082 (type == "char") || (type == "wchar") ||
+
8083 (type == "int8") || (type == "uint8") ||
+
8084 (type == "int16") || (type == "uint16") ||
+
8085 (type == "int32") || (type == "uint32") ||
+
8086 (type == "int64") || (type == "uint64") ||
+
8087 (type == "float") || (type == "double") ||
+
8088 (type == "string"));
+
8089}
+
8090
+
8091bool GeneratorKotlin::IsUnsignedType(const std::string& type)
+
8092{
+
8093 return ((type == "uint8") || (type == "uint16") || (type == "uint32") || (type == "uint64"));
+
8094}
+
8095
+
8096std::string GeneratorKotlin::CreatePackagePath(const std::string& domain, const std::string& package)
+
8097{
+
8098 std::string result = domain;
+
8099 CppCommon::StringUtils::ReplaceAll(result, ".", std::string(1, CppCommon::Path::separator()));
+
8100 return result + CppCommon::Path::separator() + package;
+
8101}
+
8102
+
8103std::string GeneratorKotlin::ConvertEnumBase(const std::string& type)
+
8104{
+
8105 if (type == "byte")
+
8106 return "Byte";
+
8107 else if (type == "char")
+
8108 return "Byte";
+
8109 else if (type == "wchar")
+
8110 return "Int";
+
8111 else if (type == "int8")
+
8112 return "Byte";
+
8113 else if (type == "uint8")
+
8114 return "UByte";
+
8115 else if (type == "int16")
+
8116 return "Short";
+
8117 else if (type == "uint16")
+
8118 return "UShort";
+
8119 else if (type == "int32")
+
8120 return "Int";
+
8121 else if (type == "uint32")
+
8122 return "UInt";
+
8123 else if (type == "int64")
+
8124 return "Long";
+
8125 else if (type == "uint64")
+
8126 return "ULong";
+
8127
+
8128 yyerror("Unsupported enum base type - " + type);
+
8129 return "";
+
8130}
+
8131
+
8132std::string GeneratorKotlin::ConvertEnumType(const std::string& type)
+
8133{
+
8134 if (type == "byte")
+
8135 return "Byte";
+
8136 else if (type == "char")
+
8137 return "Byte";
+
8138 else if (type == "wchar")
+
8139 return "Int";
+
8140 else if (type == "int8")
+
8141 return "Byte";
+
8142 else if (type == "uint8")
+
8143 return "UByte";
+
8144 else if (type == "int16")
+
8145 return "Short";
+
8146 else if (type == "uint16")
+
8147 return "UShort";
+
8148 else if (type == "int32")
+
8149 return "Int";
+
8150 else if (type == "uint32")
+
8151 return "UInt";
+
8152 else if (type == "int64")
+
8153 return "Long";
+
8154 else if (type == "uint64")
+
8155 return "ULong";
+
8156
+
8157 yyerror("Unsupported enum base type - " + type);
+
8158 return "";
+
8159}
+
8160
+
8161std::string GeneratorKotlin::ConvertEnumSize(const std::string& type)
+
8162{
+
8163 if (type == "byte")
+
8164 return "1";
+
8165 else if (type == "char")
+
8166 return "1";
+
8167 else if (type == "wchar")
+
8168 return "4";
+
8169 else if (type == "int8")
+
8170 return "1";
+
8171 else if (type == "uint8")
+
8172 return "1";
+
8173 else if (type == "int16")
+
8174 return "2";
+
8175 else if (type == "uint16")
+
8176 return "2";
+
8177 else if (type == "int32")
+
8178 return "4";
+
8179 else if (type == "uint32")
+
8180 return "4";
+
8181 else if (type == "int64")
+
8182 return "8";
+
8183 else if (type == "uint64")
+
8184 return "8";
+
8185
+
8186 yyerror("Unsupported enum base type - " + type);
+
8187 return "";
+
8188}
+
8189
+
8190std::string GeneratorKotlin::ConvertEnumGet(const std::string& type)
+
8191{
+
8192 if (type == "byte")
+
8193 return "asByte";
+
8194 else if (type == "char")
+
8195 return "asByte";
+
8196 else if (type == "wchar")
+
8197 return "asInt";
+
8198 else if (type == "int8")
+
8199 return "asByte";
+
8200 else if (type == "uint8")
+
8201 return "asByte.toUByte()";
+
8202 else if (type == "int16")
+
8203 return "asShort";
+
8204 else if (type == "uint16")
+
8205 return "asShort.toUShort()";
+
8206 else if (type == "int32")
+
8207 return "asInt";
+
8208 else if (type == "uint32")
+
8209 return "asInt.toUInt()";
+
8210 else if (type == "int64")
+
8211 return "asLong";
+
8212 else if (type == "uint64")
+
8213 return "asLong.toULong()";
+
8214
+
8215 yyerror("Unsupported enum base type - " + type);
+
8216 return "";
+
8217}
+
8218
+
8219std::string GeneratorKotlin::ConvertEnumRead(const std::string& type)
+
8220{
+
8221 if (type == "byte")
+
8222 return "readByte";
+
8223 else if (type == "char")
+
8224 return "readInt8";
+
8225 else if (type == "wchar")
+
8226 return "readInt32";
+
8227 else if (type == "int8")
+
8228 return "readInt8";
+
8229 else if (type == "uint8")
+
8230 return "readUInt8";
+
8231 else if (type == "int16")
+
8232 return "readInt16";
+
8233 else if (type == "uint16")
+
8234 return "readUInt16";
+
8235 else if (type == "int32")
+
8236 return "readInt32";
+
8237 else if (type == "uint32")
+
8238 return "readUInt32";
+
8239 else if (type == "int64")
+
8240 return "readInt64";
+
8241 else if (type == "uint64")
+
8242 return "readUInt64";
+
8243
+
8244 yyerror("Unsupported enum base type - " + type);
+
8245 return "";
+
8246}
+
8247
+
8248std::string GeneratorKotlin::ConvertEnumFrom(const std::string& type)
+
8249{
+
8250 if (type == "uint8")
+
8251 return ".toByte()";
+
8252 else if (type == "uint16")
+
8253 return ".toShort()";
+
8254 else if (type == "uint32")
+
8255 return ".toInt()";
+
8256 else if (type == "uint64")
+
8257 return ".toLong()";
+
8258
+
8259 return "";
+
8260}
+
8261
+
8262std::string GeneratorKotlin::ConvertEnumTo(const std::string& type)
+
8263{
+
8264 if (type == "byte")
+
8265 return ".toByte()";
+
8266 else if (type == "char")
+
8267 return ".toByte()";
+
8268 else if (type == "wchar")
+
8269 return ".toInt()";
+
8270 else if (type == "int8")
+
8271 return ".toByte()";
+
8272 else if (type == "uint8")
+
8273 return ".toUByte()";
+
8274 else if (type == "int16")
+
8275 return ".toShort()";
+
8276 else if (type == "uint16")
+
8277 return ".toUShort()";
+
8278 else if (type == "int32")
+
8279 return ".toInt()";
+
8280 else if (type == "uint32")
+
8281 return ".toUInt()";
+
8282 else if (type == "int64")
+
8283 return ".toLong()";
+
8284 else if (type == "uint64")
+
8285 return ".toULong()";
+
8286
+
8287 yyerror("Unsupported enum base type - " + type);
+
8288 return "";
+
8289}
+
8290
+
8291std::string GeneratorKotlin::ConvertEnumFlags(const std::string& type)
+
8292{
+
8293 if (type == "byte")
+
8294 return ".toInt()";
+
8295 else if (type == "int8")
+
8296 return ".toInt()";
+
8297 else if (type == "uint8")
+
8298 return ".toUInt()";
+
8299 else if (type == "int16")
+
8300 return ".toInt()";
+
8301 else if (type == "uint16")
+
8302 return ".toUInt()";
+
8303 else if (type == "int32")
+
8304 return ".toInt()";
+
8305 else if (type == "uint32")
+
8306 return ".toUInt()";
+
8307 else if (type == "int64")
+
8308 return ".toLong()";
+
8309 else if (type == "uint64")
+
8310 return ".toULong()";
+
8311
+
8312 yyerror("Unsupported enum base type - " + type);
+
8313 return "";
+
8314}
+
8315
+
8316std::string GeneratorKotlin::ConvertEnumConstant(const std::string& base, const std::string& type, const std::string& value, bool flag)
+
8317{
+
8318 std::string result = value;
+
8319
+
8320 if (type.empty())
+
8321 {
+
8322 // Fill flags values
+
8323 std::vector<std::string> flags = CppCommon::StringUtils::Split(value, '|', true);
+
8324
+
8325 // Generate flags combination
+
8326 if (!flags.empty())
+
8327 {
+
8328 result = "";
+
8329 bool first = true;
+
8330 for (const auto& it : flags)
+
8331 {
+
8332 result += (first ? "" : " or ") + CppCommon::StringUtils::ToTrim(it) + ".raw" + (flag ? ConvertEnumFlags(base) : "");
+
8333 first = false;
+
8334 }
+
8335 }
+
8336 }
+
8337
+
8338 return ConvertEnumConstantPrefix(type) + result + ConvertEnumConstantSuffix(type);
+
8339}
+
8340
+
8341std::string GeneratorKotlin::ConvertEnumConstantPrefix(const std::string& type)
+
8342{
+
8343 return "";
+
8344}
+
8345
+
8346std::string GeneratorKotlin::ConvertEnumConstantSuffix(const std::string& type)
+
8347{
+
8348 if ((type == "uint8") || (type == "uint16") || (type == "uint32"))
+
8349 return "u";
+
8350 if (type == "int64")
+
8351 return "L";
+
8352 if (type == "uint64")
+
8353 return "uL";
+
8354
+
8355 return "";
+
8356}
+
8357
+
8358std::string GeneratorKotlin::ConvertPrimitiveTypeName(const std::string& type)
+
8359{
+
8360 if (type == "bool")
+
8361 return "Boolean";
+
8362 else if (type == "byte")
+
8363 return "Byte";
+
8364 else if (type == "char")
+
8365 return "Character";
+
8366 else if (type == "wchar")
+
8367 return "Character";
+
8368 else if (type == "int8")
+
8369 return "Byte";
+
8370 else if (type == "uint8")
+
8371 return "UByte";
+
8372 else if (type == "int16")
+
8373 return "Short";
+
8374 else if (type == "uint16")
+
8375 return "UShort";
+
8376 else if (type == "int32")
+
8377 return "Int";
+
8378 else if (type == "uint32")
+
8379 return "UInt";
+
8380 else if (type == "int64")
+
8381 return "Long";
+
8382 else if (type == "uint64")
+
8383 return "ULong";
+
8384 else if (type == "float")
+
8385 return "Float";
+
8386 else if (type == "double")
+
8387 return "Double";
+
8388
+
8389 return "";
+
8390}
+
8391
+
8392std::string GeneratorKotlin::ConvertTypeName(const std::string& domain, const std::string& package, const std::string& type, bool optional)
+
8393{
+
8394 std::string opt = optional ? "?" : "";
+
8395
+
8396 if (type == "bool")
+
8397 return "Boolean" + opt;
+
8398 else if (type == "byte")
+
8399 return "Byte" + opt;
+
8400 else if (type == "bytes")
+
8401 return "ByteArray" + opt;
+
8402 else if (type == "char")
+
8403 return "Char" + opt;
+
8404 else if (type == "wchar")
+
8405 return "Char" + opt;
+
8406 else if (type == "int8")
+
8407 return "Byte" + opt;
+
8408 else if (type == "uint8")
+
8409 return "UByte" + opt;
+
8410 else if (type == "int16")
+
8411 return "Short" + opt;
+
8412 else if (type == "uint16")
+
8413 return "UShort" + opt;
+
8414 else if (type == "int32")
+
8415 return "Int" + opt;
+
8416 else if (type == "uint32")
+
8417 return "UInt" + opt;
+
8418 else if (type == "int64")
+
8419 return "Long" + opt;
+
8420 else if (type == "uint64")
+
8421 return "ULong" + opt;
+
8422 else if (type == "float")
+
8423 return "Float" + opt;
+
8424 else if (type == "double")
+
8425 return "Double" + opt;
+
8426 else if (type == "decimal")
+
8427 return "java.math.BigDecimal" + opt;
+
8428 else if (type == "string")
+
8429 return "String" + opt;
+
8430 else if (type == "timestamp")
+
8431 return ((Version() < 8) ? "java.util.Date" : "java.time.Instant") + opt;
+
8432 else if (type == "uuid")
+
8433 return "java.util.UUID" + opt;
+
8434
+
8435 std::string ns = "";
+
8436 std::string t = type;
+
8437
+
8438 size_t pos = type.find_last_of('.');
+
8439 if (pos != std::string::npos)
+
8440 {
+
8441 ns.assign(type, 0, pos + 1);
+
8442 ns = domain + ns;
+
8443 t.assign(type, pos + 1, type.size() - pos);
+
8444 }
+
8445 else if (!package.empty())
+
8446 ns = domain + package + ".";
+
8447
+
8448 return ns + t + opt;
+
8449}
+
8450
+
8451std::string GeneratorKotlin::ConvertTypeName(const std::string& domain, const std::string& package, const StructField& field, bool typeless)
+
8452{
+
8453 if (field.array)
+
8454 return "Array" + (typeless ? "" : ("<" + ConvertTypeName(domain, package, *field.type, field.optional) + ">"));
+
8455 else if (field.vector)
+
8456 return "java.util.ArrayList" + (typeless ? "" : ("<" + ConvertTypeName(domain, package, *field.type, field.optional) + ">"));
+
8457 else if (field.list)
+
8458 return "java.util.LinkedList" + (typeless ? "" : ("<" + ConvertTypeName(domain, package, *field.type, field.optional) + ">"));
+
8459 else if (field.set)
+
8460 return "java.util.HashSet" + (typeless ? "" : ("<" + ConvertTypeName(domain, package, *field.key, field.optional) + ">"));
+
8461 else if (field.map)
+
8462 return "java.util.TreeMap" + (typeless ? "" : ("<" + ConvertTypeName(domain, package, *field.key, false) + ", " + ConvertTypeName(domain, package, *field.type, field.optional) +">"));
+
8463 else if (field.hash)
+
8464 return "java.util.HashMap" + (typeless ? "" : ("<" + ConvertTypeName(domain, package, *field.key, false) + ", " + ConvertTypeName(domain, package, *field.type, field.optional) +">"));
+
8465
+
8466 return ConvertTypeName(domain, package, *field.type, field.optional);
+
8467}
+
8468
+
8469std::string GeneratorKotlin::ConvertBaseFieldName(const std::string& domain, const std::string& type, bool final)
+
8470{
+
8471 std::string modelType = final ? "Final" : "Field";
+
8472
+
8473 std::string ns = "";
+
8474 std::string t = type;
+
8475
+
8476 size_t pos = type.find_last_of('.');
+
8477 if (pos != std::string::npos)
+
8478 {
+
8479 ns.assign(type, 0, pos + 1);
+
8480 ns.append("fbe.");
+
8481 ns = domain + ns;
+
8482 t.assign(type, pos + 1, type.size() - pos);
+
8483 }
+
8484
+
8485 return ns + modelType + "Model" + ConvertTypeFieldName(t);
+
8486}
+
8487
+
8488std::string GeneratorKotlin::ConvertTypeFieldName(const std::string& type)
+
8489{
+
8490 if (type == "bool")
+
8491 return "Boolean";
+
8492 else if (type == "byte")
+
8493 return "Byte";
+
8494 else if (type == "bytes")
+
8495 return "Bytes";
+
8496 else if (type == "char")
+
8497 return "Char";
+
8498 else if (type == "wchar")
+
8499 return "WChar";
+
8500 else if (type == "int8")
+
8501 return "Int8";
+
8502 else if (type == "uint8")
+
8503 return "UInt8";
+
8504 else if (type == "int16")
+
8505 return "Int16";
+
8506 else if (type == "uint16")
+
8507 return "UInt16";
+
8508 else if (type == "int32")
+
8509 return "Int32";
+
8510 else if (type == "uint32")
+
8511 return "UInt32";
+
8512 else if (type == "int64")
+
8513 return "Int64";
+
8514 else if (type == "uint64")
+
8515 return "UInt64";
+
8516 else if (type == "float")
+
8517 return "Float";
+
8518 else if (type == "double")
+
8519 return "Double";
+
8520 else if (type == "decimal")
+
8521 return "Decimal";
+
8522 else if (type == "string")
+
8523 return "String";
+
8524 else if (type == "timestamp")
+
8525 return ((Version() < 8) ? "Date" : "Timestamp");
+
8526 else if (type == "uuid")
+
8527 return "UUID";
+
8528
+
8529 std::string result = type;
+
8530 CppCommon::StringUtils::ReplaceAll(result, ".", "");
+
8531 return result;
+
8532}
+
8533
+
8534std::string GeneratorKotlin::ConvertTypeFieldType(const std::string& domain, const std::string& type, bool optional)
+
8535{
+
8536 std::string opt = optional ? "?" : "";
+
8537
+
8538 if (type == "bool")
+
8539 return "Boolean" + opt;
+
8540 else if (type == "byte")
+
8541 return "Byte" + opt;
+
8542 else if (type == "bytes")
+
8543 return "ByteArray" + opt;
+
8544 else if (type == "char")
+
8545 return "Char" + opt;
+
8546 else if (type == "wchar")
+
8547 return "Char" + opt;
+
8548 else if (type == "int8")
+
8549 return "Byte" + opt;
+
8550 else if (type == "uint8")
+
8551 return "UByte" + opt;
+
8552 else if (type == "int16")
+
8553 return "Short" + opt;
+
8554 else if (type == "uint16")
+
8555 return "UShort" + opt;
+
8556 else if (type == "int32")
+
8557 return "Int" + opt;
+
8558 else if (type == "uint32")
+
8559 return "UInt" + opt;
+
8560 else if (type == "int64")
+
8561 return "Long" + opt;
+
8562 else if (type == "uint64")
+
8563 return "ULong" + opt;
+
8564 else if (type == "float")
+
8565 return "Float" + opt;
+
8566 else if (type == "double")
+
8567 return "Double" + opt;
+
8568 else if (type == "decimal")
+
8569 return "java.math.BigDecimal" + opt;
+
8570 else if (type == "string")
+
8571 return "String" + opt;
+
8572 else if (type == "timestamp")
+
8573 return ((Version() < 8) ? "java.util.Date" : "java.time.Instant") + opt;
+
8574 else if (type == "uuid")
+
8575 return "java.util.UUID" + opt;
+
8576
+
8577 std::string ns = "";
+
8578 std::string t = type;
+
8579
+
8580 size_t pos = type.find_last_of('.');
+
8581 if (pos != std::string::npos)
+
8582 {
+
8583 ns.assign(type, 0, pos + 1);
+
8584 ns = domain + ns;
+
8585 t.assign(type, pos + 1, type.size() - pos);
+
8586 }
+
8587
+
8588 return ns + t + opt;
+
8589}
+
8590
+
8591std::string GeneratorKotlin::ConvertTypeFieldDeclaration(const std::string& domain, const std::string& type, bool optional, bool final)
+
8592{
+
8593 std::string modelType = final ? "Final" : "Field";
+
8594
+
8595 std::string ns = "";
+
8596 std::string opt = optional ? "Optional" : "";
+
8597 std::string t = type;
+
8598
+
8599 size_t pos = type.find_last_of('.');
+
8600 if (pos != std::string::npos)
+
8601 {
+
8602 ns.assign(type, 0, pos + 1);
+
8603 ns.append("fbe.");
+
8604 ns = domain + ns;
+
8605 t.assign(type, pos + 1, type.size() - pos);
+
8606 }
+
8607 else
+
8608 ns = (IsKnownType(type) && !optional) ? (domain + "fbe.") : "";
+
8609
+
8610 return ns + modelType + "Model" + opt + ConvertTypeFieldName(t);
+
8611}
+
8612
+
8613std::string GeneratorKotlin::ConvertTypeFieldDeclaration(const std::string& domain, const StructField& field, bool final)
+
8614{
+
8615 std::string modelType = final ? "Final" : "Field";
+
8616
+
8617 if (field.array)
+
8618 return modelType + "ModelArray" + std::string(field.optional ? "Optional" : "") + ConvertTypeFieldName(*field.type);
+
8619 else if (field.vector || field.list || field.set)
+
8620 return modelType + "ModelVector" + std::string(field.optional ? "Optional" : "") + ConvertTypeFieldName(*field.type);
+
8621 else if (field.map || field.hash)
+
8622 return modelType + "ModelMap" + ConvertTypeFieldName(*field.key) + std::string(field.optional ? "Optional" : "") + ConvertTypeFieldName(*field.type);
+
8623 else if (field.optional)
+
8624 return modelType + "ModelOptional" + ConvertTypeFieldName(*field.type);
+
8625
+
8626 return ConvertTypeFieldDeclaration(domain, *field.type, field.optional, final);
+
8627}
+
8628
+
8629std::string GeneratorKotlin::ConvertTypeFieldInitialization(const std::string& domain, const StructField& field, const std::string& offset, bool final)
+
8630{
+
8631 std::string modelType = final ? "Final" : "Field";
+
8632
+
8633 if (field.array)
+
8634 return modelType + "ModelArray" + std::string(field.optional ? "Optional" : "") + ConvertTypeFieldName(*field.type) + "(buffer, " + offset + ", " + std::to_string(field.N) + ")";
+
8635 else if (field.vector || field.list || field.set)
+
8636 return modelType + "ModelVector" + std::string(field.optional ? "Optional" : "") + ConvertTypeFieldName(*field.type) + "(buffer, " + offset + ")";
+
8637 else if (field.map || field.hash)
+
8638 return modelType + "ModelMap" + ConvertTypeFieldName(*field.key) + std::string(field.optional ? "Optional" : "") + ConvertTypeFieldName(*field.type) + "(buffer, " + offset + ")";
+
8639 else if (field.optional)
+
8640 return modelType + "ModelOptional" + ConvertTypeFieldName(*field.type) + "(buffer, " + offset + ")";
+
8641
+
8642 std::string ns = "";
+
8643 std::string t = *field.type;
+
8644 std::string type = *field.type;
+
8645
+
8646 size_t pos = type.find_last_of('.');
+
8647 if (pos != std::string::npos)
+
8648 {
+
8649 ns.assign(type, 0, pos + 1);
+
8650 ns.append("fbe.");
+
8651 ns = domain + ns;
+
8652 t.assign(type, pos + 1, type.size() - pos);
+
8653 }
+
8654 else
+
8655 ns = IsKnownType(type) ? (domain + "fbe.") : "";
+
8656
+
8657 return ns + modelType + "Model" + ConvertTypeFieldName(t) + "(buffer, " + offset + ")";
+
8658}
+
8659
+
8660std::string GeneratorKotlin::ConvertConstant(const std::string& domain, const std::string& package, const std::string& type, const std::string& value, bool optional)
+
8661{
+
8662 if (value == "true")
+
8663 return "true";
+
8664 else if (value == "false")
+
8665 return "false";
+
8666 else if (value == "null")
+
8667 return "null";
+
8668 else if (value == "min")
+
8669 {
+
8670 if (type == "byte")
+
8671 return ConvertConstantPrefix(type) + "0" + ConvertConstantSuffix(type);
+
8672 else if (type == "int8")
+
8673 return "Byte.MIN_VALUE";
+
8674 else if (type == "uint8")
+
8675 return "UByte.MIN_VALUE";
+
8676 else if (type == "int16")
+
8677 return "Short.MIN_VALUE";
+
8678 else if (type == "uint16")
+
8679 return "UShort.MIN_VALUE";
+
8680 else if (type == "int32")
+
8681 return "Int.MIN_VALUE";
+
8682 else if (type == "uint32")
+
8683 return "UInt.MIN_VALUE";
+
8684 else if (type == "int64")
+
8685 return "Long.MIN_VALUE";
+
8686 else if (type == "uint64")
+
8687 return "ULong.MIN_VALUE";
+
8688
+
8689 yyerror("Unsupported type " + type + " for 'min' constant");
+
8690 return "";
+
8691 }
+
8692 else if (value == "max")
+
8693 {
+
8694 if (type == "byte")
+
8695 return ConvertConstantPrefix(type) + "0xFF" + ConvertConstantSuffix(type);
+
8696 else if (type == "int8")
+
8697 return "Byte.MAX_VALUE";
+
8698 else if (type == "uint8")
+
8699 return "UByte.MAX_VALUE";
+
8700 else if (type == "int16")
+
8701 return "Short.MAX_VALUE";
+
8702 else if (type == "uint16")
+
8703 return "UShort.MAX_VALUE";
+
8704 else if (type == "int32")
+
8705 return "Int.MAX_VALUE";
+
8706 else if (type == "uint32")
+
8707 return "UInt.MAX_VALUE";
+
8708 else if (type == "int64")
+
8709 return "Long.MAX_VALUE";
+
8710 else if (type == "uint64")
+
8711 return "ULong.MAX_VALUE";
+
8712
+
8713 yyerror("Unsupported type " + type + " for 'max' constant");
+
8714 return "";
+
8715 }
+
8716 else if (value == "epoch")
+
8717 return ((Version() < 8) ? "java.util.Date(0)" : "java.time.Instant.EPOCH");
+
8718 else if (value == "utc")
+
8719 return ((Version() < 8) ? "java.util.Date(System.currentTimeMillis())" : "java.time.Instant.now()");
+
8720 else if (value == "uuid0")
+
8721 return domain + "fbe.UUIDGenerator.nil()";
+
8722 else if (value == "uuid1")
+
8723 return domain + "fbe.UUIDGenerator.sequential()";
+
8724 else if (value == "uuid4")
+
8725 return domain + "fbe.UUIDGenerator.random()";
+
8726
+
8727 std::string result = value;
+
8728
+
8729 if (!IsKnownType(type))
+
8730 {
+
8731 // Fill flags values
+
8732 std::vector<std::string> flags = CppCommon::StringUtils::Split(value, '|', true);
+
8733
+
8734 // Generate flags combination
+
8735 if (flags.size() > 1)
+
8736 {
+
8737 result = "";
+
8738 bool first = true;
+
8739 for (const auto& it : flags)
+
8740 {
+
8741 std::string flag = CppCommon::StringUtils::ToTrim(it);
+
8742 size_t pos = flag.find_last_of('.');
+
8743 if (pos != std::string::npos)
+
8744 {
+
8745 if (CppCommon::StringUtils::CountAll(flag, ".") > 1)
+
8746 flag = domain + flag;
+
8747 else
+
8748 flag = (package.empty() ? "" : (domain + package + ".")) + flag;
+
8749 }
+
8750 result += (first ? "" : ", ") + flag + ".value";
+
8751 first = false;
+
8752 }
+
8753 result = (package.empty() ? "" : (domain + package + ".")) + type + ".fromSet(java.util.EnumSet.of(" + result + "))";
+
8754 }
+
8755 else
+
8756 {
+
8757 size_t pos = result.find_last_of('.');
+
8758 if (pos != std::string::npos)
+
8759 {
+
8760 if (CppCommon::StringUtils::CountAll(result, ".") > 1)
+
8761 result = domain + result;
+
8762 else
+
8763 result = (package.empty() ? "" : (domain + package + ".")) + result;
+
8764 }
+
8765 }
+
8766 }
+
8767
+
8768 return ConvertConstantPrefix(type) + result + ConvertConstantSuffix(type);
+
8769}
+
8770
+
8771std::string GeneratorKotlin::ConvertConstantPrefix(const std::string& type)
+
8772{
+
8773 if (type == "decimal")
+
8774 return "java.math.BigDecimal.valueOf(";
+
8775 if (type == "uuid")
+
8776 return "java.util.UUID.fromString(";
+
8777
+
8778 return "";
+
8779}
+
8780
+
8781std::string GeneratorKotlin::ConvertConstantSuffix(const std::string& type)
+
8782{
+
8783 if (type == "byte")
+
8784 return ".toByte()";
+
8785 if ((type == "char") || (type == "wchar"))
+
8786 return ".toChar()";
+
8787 if ((type == "uint8") || (type == "uint16") || (type == "uint32"))
+
8788 return "u";
+
8789 if (type == "int64")
+
8790 return "L";
+
8791 if (type == "uint64")
+
8792 return "uL";
+
8793 if (type == "float")
+
8794 return "f";
+
8795
+
8796 if ((type == "decimal") || (type == "uuid"))
+
8797 return ")";
+
8798
+
8799 return "";
+
8800}
+
8801
+
8802std::string GeneratorKotlin::ConvertDefault(const std::string& domain, const std::string& package, const std::string& type)
+
8803{
+
8804 if (type == "bool")
+
8805 return "false";
+
8806 else if (type == "byte")
+
8807 return "0.toByte()";
+
8808 else if (type == "bytes")
+
8809 return "ByteArray(0)";
+
8810 else if ((type == "char") || (type == "wchar"))
+
8811 return "'\\u0000'";
+
8812 else if (type == "int8")
+
8813 return "0.toByte()";
+
8814 else if (type == "uint8")
+
8815 return "0.toUByte()";
+
8816 else if (type == "int16")
+
8817 return "0.toShort()";
+
8818 else if (type == "uint16")
+
8819 return "0.toUShort()";
+
8820 else if (type == "int32")
+
8821 return "0";
+
8822 else if (type == "uint32")
+
8823 return "0u";
+
8824 else if (type == "int64")
+
8825 return "0L";
+
8826 else if (type == "uint64")
+
8827 return "0uL";
+
8828 else if (type == "float")
+
8829 return "0.0f";
+
8830 else if (type == "double")
+
8831 return "0.0";
+
8832 else if (type == "decimal")
+
8833 return "java.math.BigDecimal.valueOf(0L)";
+
8834 else if (type == "string")
+
8835 return "\"\"";
+
8836 else if (type == "timestamp")
+
8837 return ((Version() < 8) ? "java.util.Date(0)" : "java.time.Instant.EPOCH");
+
8838 else if (type == "uuid")
+
8839 return domain + "fbe.UUIDGenerator.nil()";
+
8840
+
8841 std::string ns = "";
+
8842 std::string t = type;
+
8843
+
8844 size_t pos = type.find_last_of('.');
+
8845 if (pos != std::string::npos)
+
8846 {
+
8847 ns.assign(type, 0, pos + 1);
+
8848 ns = domain + ns;
+
8849 t.assign(type, pos + 1, type.size() - pos);
+
8850 }
+
8851 else if (!package.empty())
+
8852 ns = domain + package + ".";
+
8853
+
8854 return ns + t + "()";
+
8855}
+
8856
+
8857std::string GeneratorKotlin::ConvertDefault(const std::string& domain, const std::string& package, const StructField& field)
+
8858{
+
8859 if (field.value)
+
8860 return ConvertConstant(domain, package, *field.type, *field.value, field.optional);
+
8861
+
8862 if (field.array)
+
8863 if (field.optional)
+
8864 return "arrayOfNulls<" + ConvertTypeName(domain, package, *field.type, field.optional) + ">(" + std::to_string(field.N) + ")";
+
8865 else
+
8866 return "Array(" + std::to_string(field.N) + ") { " + ConvertDefault(domain, package, *field.type) + " }";
+
8867 else if (field.vector || field.list || field.set || field.map || field.hash)
+
8868 return ConvertTypeName(domain, package, field, true) + "()";
+
8869 else if (field.optional)
+
8870 return "null";
+
8871 else if (!IsPackageType(*field.type))
+
8872 return ConvertTypeName(domain, package, field, true) + "()";
+
8873
+
8874 return ConvertDefault(domain, package, *field.type);
+
8875}
+
8876
+
8877std::string GeneratorKotlin::ConvertOutputStreamType(const std::string& type, const std::string& name, bool optional)
+
8878{
+
8879 std::string opt = optional ? "!!" : "";
+
8880
+
8881 if (type == "bool")
+
8882 return ".append(if (" + name + opt + ") \"true\" else \"false\")";
+
8883 else if (type == "bytes")
+
8884 return ".append(\"bytes[\").append(" + name + opt + ".size).append(\"]\")";
+
8885 else if ((type == "char") || (type == "wchar"))
+
8886 return ".append(\"'\").append(" + name + opt + ").append(\"'\")";
+
8887 else if ((type == "string") || (type == "uuid"))
+
8888 return ".append(\"\\\"\").append(" + name + opt + ").append(\"\\\"\")";
+
8889 else if (type == "timestamp")
+
8890 return ((Version() < 8) ? ".append(" + name + opt + ".time * 1000000)" : ".append(" + name + opt + ".epochSecond * 1000000000 + " + name + opt + ".nano)");
+
8891 else
+
8892 return ".append(" + name + opt + ")";
+
8893}
+
8894
+
8895std::string GeneratorKotlin::ConvertOutputStreamValue(const std::string& type, const std::string& name, bool optional, bool separate, bool nullable)
+
8896{
+
8897 std::string comma = separate ? ".append(if (first) \"\" else \",\")" : "";
+
8898
+
8899 if (optional)
+
8900 return "if (" + name + " != null) sb" + comma + ConvertOutputStreamType(type, name, nullable) + "; else sb" + comma + ".append(\"null\")";
+
8901 else
+
8902 return "sb" + comma + ConvertOutputStreamType(type, name, false);
+
8903}
+
8904
+
8905} // namespace FBE
+
void WriteBegin()
Definition generator.inl:24
+
void Store(const CppCommon::Path &filename)
Definition generator.cpp:17
+
static std::string EndLine()
Definition generator.inl:68
+
std::string _input
Definition generator.h:25
+ +
std::string _output
Definition generator.h:26
+
void WriteLineIndent(const std::string &str)
Definition generator.inl:58
+
void Write(const std::string &str)
Definition generator.inl:29
+ +
bool Final() const noexcept
+
void Generate(const std::shared_ptr< Package > &package) override
+
int Version() const noexcept
+
bool JSON() const noexcept
+
bool Proto() const noexcept
+
int yyerror(const char *msg)
Definition fbe.l:163
+
Fast binary encoding Kotlin generator definition.
+
Definition fbe.h:33
+
const char version[]
Definition version.h:15
+
+ + +
+ + diff --git a/documents/html/generator__kotlin_8h.html b/documents/html/generator__kotlin_8h.html new file mode 100644 index 000000000..1ff3e8307 --- /dev/null +++ b/documents/html/generator__kotlin_8h.html @@ -0,0 +1,114 @@ + + + + + + + +FastBinaryEncoding: include/generator_kotlin.h File Reference + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+ +
generator_kotlin.h File Reference
+
+
+ +

Fast binary encoding Kotlin generator definition. +More...

+
#include "generator.h"
+
+

Go to the source code of this file.

+ + + +

+Classes

class  FBE::GeneratorKotlin
+ + +

+Namespaces

namespace  FBE
+

Detailed Description

+

Fast binary encoding Kotlin generator definition.

+
Author
Ivan Shynkarenka
+
Date
03.10.2018
+ + +

Definition in file generator_kotlin.h.

+
+ + +
+ + diff --git a/documents/html/generator__kotlin_8h_source.html b/documents/html/generator__kotlin_8h_source.html new file mode 100644 index 000000000..09ae0e22d --- /dev/null +++ b/documents/html/generator__kotlin_8h_source.html @@ -0,0 +1,250 @@ + + + + + + + +FastBinaryEncoding: include/generator_kotlin.h Source File + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+
generator_kotlin.h
+
+
+Go to the documentation of this file.
1
+
8
+
9#ifndef GENERATOR_KOTLIN_H
+
10#define GENERATOR_KOTLIN_H
+
11
+
12#include "generator.h"
+
13
+
14namespace FBE {
+
15
+
+ +
17{
+
18public:
+ +
20
+
21 // Final protocol code generation
+
22 bool Final() const noexcept { return _final; }
+
23 GeneratorKotlin& Final(bool final) noexcept { _final = final; return *this; }
+
24
+
25 // JSON protocol code generation
+
26 bool JSON() const noexcept { return _json; }
+
27 GeneratorKotlin& JSON(bool json) noexcept { _json = json; return *this; }
+
28
+
29 // Sender/Receiver protocol code generation
+
30 bool Proto() const noexcept { return _proto; }
+
31 GeneratorKotlin& Proto(bool proto) noexcept { _proto = proto; return *this; }
+
32
+
33 // Java version
+
34 int Version() const noexcept { return _version; }
+
35 GeneratorKotlin& Version(int v) noexcept { _version = v; return *this; }
+
36
+
37 void Generate(const std::shared_ptr<Package>& package) override;
+
38
+
39private:
+
40 bool _final{false};
+
41 bool _json{false};
+
42 bool _proto{false};
+
43 int _version{8};
+
44
+
45 void GenerateHeader(const std::string& source);
+
46 void GenerateFooter();
+
47 void GenerateImports(const std::string& domain, const std::string& package);
+
48 void GenerateImports(const std::shared_ptr<Package>& p);
+
49
+
50 void GenerateFBEPackage(const std::string& domain, const std::string& package);
+
51 void GenerateFBEUUIDGenerator(const std::string& domain, const std::string& package);
+
52 void GenerateFBEBuffer(const std::string& domain, const std::string& package);
+
53 void GenerateFBEModel(const std::string& domain, const std::string& package);
+
54 void GenerateFBESize(const std::string& domain, const std::string& package);
+
55 void GenerateFBEFieldModel(const std::string& domain, const std::string& package);
+
56 void GenerateFBEFieldModel(const std::string& domain, const std::string& package, const std::string& name, const std::string& type, const std::string& base, const std::string& size, const std::string& defaults);
+
57 void GenerateFBEFieldModelDecimal(const std::string& domain, const std::string& package);
+
58 void GenerateFBEFieldModelDate(const std::string& domain, const std::string& package);
+
59 void GenerateFBEFieldModelTimestamp(const std::string& domain, const std::string& package);
+
60 void GenerateFBEFieldModelBytes(const std::string& domain, const std::string& package);
+
61 void GenerateFBEFieldModelString(const std::string& domain, const std::string& package);
+
62 void GenerateFBEFieldModelOptional(const std::string& domain, const std::string& package, const std::string& name, const std::string& type, const std::string& model);
+
63 void GenerateFBEFieldModelArray(const std::string& domain, const std::string& package, const std::string& name, const std::string& type, const std::string& base, bool optional, const std::string& model);
+
64 void GenerateFBEFieldModelVector(const std::string& domain, const std::string& package, const std::string& name, const std::string& type, const std::string& model);
+
65 void GenerateFBEFieldModelMap(const std::string& domain, const std::string& package, const std::string& key_name, const std::string& key_type, const std::string& key_model, const std::string& value_name, const std::string& value_type, const std::string& value_model);
+
66 void GenerateFBEFieldModelEnumFlags(const std::string& domain, const std::string& package, const std::string& name, const std::string& type);
+
67 void GenerateFBEFinalModel(const std::string& domain, const std::string& package);
+
68 void GenerateFBEFinalModel(const std::string& domain, const std::string& package, const std::string& name, const std::string& type, const std::string& base, const std::string& size, const std::string& defaults);
+
69 void GenerateFBEFinalModelDecimal(const std::string& domain, const std::string& package);
+
70 void GenerateFBEFinalModelDate(const std::string& domain, const std::string& package);
+
71 void GenerateFBEFinalModelTimestamp(const std::string& domain, const std::string& package);
+
72 void GenerateFBEFinalModelBytes(const std::string& domain, const std::string& package);
+
73 void GenerateFBEFinalModelString(const std::string& domain, const std::string& package);
+
74 void GenerateFBEFinalModelOptional(const std::string& domain, const std::string& package, const std::string& name, const std::string& type, const std::string& model);
+
75 void GenerateFBEFinalModelArray(const std::string& domain, const std::string& package, const std::string& name, const std::string& type, const std::string& base, bool optional, const std::string& model);
+
76 void GenerateFBEFinalModelVector(const std::string& domain, const std::string& package, const std::string& name, const std::string& type, const std::string& model);
+
77 void GenerateFBEFinalModelMap(const std::string& domain, const std::string& package, const std::string& key_name, const std::string& key_type, const std::string& key_model, const std::string& value_name, const std::string& value_type, const std::string& value_model);
+
78 void GenerateFBEFinalModelEnumFlags(const std::string& domain, const std::string& package, const std::string& name, const std::string& type);
+
79 void GenerateFBESender(const std::string& domain, const std::string& package);
+
80 void GenerateFBESenderListener(const std::string& domain, const std::string& package);
+
81 void GenerateFBEReceiver(const std::string& domain, const std::string& package);
+
82 void GenerateFBEReceiverListener(const std::string& domain, const std::string& package);
+
83 void GenerateFBEClient(const std::string& domain, const std::string& package);
+
84 void GenerateFBEClientListener(const std::string& domain, const std::string& package);
+
85 void GenerateFBEJson(const std::string& domain, const std::string& package);
+
86
+
87 void GenerateContainers(const std::shared_ptr<Package>& p, bool final);
+
88 void GeneratePackage(const std::shared_ptr<Package>& p);
+
89 void GenerateEnum(const std::shared_ptr<Package>& p, const std::shared_ptr<EnumType>& e, const CppCommon::Path& path);
+
90 void GenerateEnumClass(const std::shared_ptr<Package>& p, const std::shared_ptr<EnumType>& e, const CppCommon::Path& path);
+
91 void GenerateEnumJson(const std::shared_ptr<Package>& p, const std::shared_ptr<EnumType>& e);
+
92 void GenerateFlags(const std::shared_ptr<Package>& p, const std::shared_ptr<FlagsType>& e, const CppCommon::Path& path);
+
93 void GenerateFlagsClass(const std::shared_ptr<Package>& p, const std::shared_ptr<FlagsType>& e, const CppCommon::Path& path);
+
94 void GenerateFlagsJson(const std::shared_ptr<Package>& p, const std::shared_ptr<FlagsType>& e);
+
95 void GenerateStruct(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s, const CppCommon::Path& path);
+
96 void GenerateStructFieldModel(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s);
+
97 void GenerateStructModel(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s);
+
98 void GenerateStructFinalModel(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s);
+
99 void GenerateStructModelFinal(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s);
+
100 void GenerateProtocolVersion(const std::shared_ptr<Package>& p);
+
101 void GenerateSender(const std::shared_ptr<Package>& p, bool final);
+
102 void GenerateSenderListener(const std::shared_ptr<Package>& p, bool final);
+
103 void GenerateReceiver(const std::shared_ptr<Package>& p, bool final);
+
104 void GenerateReceiverListener(const std::shared_ptr<Package>& p, bool final);
+
105 void GenerateProxy(const std::shared_ptr<Package>& p, bool final);
+
106 void GenerateProxyListener(const std::shared_ptr<Package>& p, bool final);
+
107 void GenerateClient(const std::shared_ptr<Package>& p, bool final);
+
108 void GenerateClientListener(const std::shared_ptr<Package>& p, bool final);
+
109 void GenerateJson(const std::shared_ptr<Package>& p);
+
110
+
111 bool IsKnownType(const std::string& type);
+
112 bool IsImportedType(const std::string& type);
+
113 bool IsPackageType(const std::string& type);
+
114 bool IsPrimitiveType(const std::string& type, bool optional);
+
115 bool IsUnsignedType(const std::string& type);
+
116
+
117 std::string CreatePackagePath(const std::string& domain, const std::string& package);
+
118
+
119 std::string ConvertEnumBase(const std::string& type);
+
120 std::string ConvertEnumType(const std::string& type);
+
121 std::string ConvertEnumSize(const std::string& type);
+
122 std::string ConvertEnumGet(const std::string& type);
+
123 std::string ConvertEnumRead(const std::string& type);
+
124 std::string ConvertEnumFrom(const std::string& type);
+
125 std::string ConvertEnumTo(const std::string& type);
+
126 std::string ConvertEnumFlags(const std::string& type);
+
127 std::string ConvertEnumConstant(const std::string& base, const std::string& type, const std::string& value, bool flag);
+
128 std::string ConvertEnumConstantPrefix(const std::string& type);
+
129 std::string ConvertEnumConstantSuffix(const std::string& type);
+
130 std::string ConvertPrimitiveTypeName(const std::string& type);
+
131 std::string ConvertTypeName(const std::string& domain, const std::string& package, const std::string& type, bool optional);
+
132 std::string ConvertTypeName(const std::string& domain, const std::string& package, const StructField& field, bool typeless);
+
133 std::string ConvertBaseFieldName(const std::string& domain, const std::string& type, bool final);
+
134 std::string ConvertTypeFieldName(const std::string& type);
+
135 std::string ConvertTypeFieldType(const std::string& domain, const std::string& type, bool optional);
+
136 std::string ConvertTypeFieldDeclaration(const std::string& domain, const std::string& type, bool optional, bool final);
+
137 std::string ConvertTypeFieldDeclaration(const std::string& domain, const StructField& field, bool final);
+
138 std::string ConvertTypeFieldInitialization(const std::string& domain, const StructField& field, const std::string& offset, bool final);
+
139 std::string ConvertConstant(const std::string& domain, const std::string& package, const std::string& type, const std::string& value, bool optional);
+
140 std::string ConvertConstantPrefix(const std::string& type);
+
141 std::string ConvertConstantSuffix(const std::string& type);
+
142 std::string ConvertDefault(const std::string& domain, const std::string& package, const std::string& type);
+
143 std::string ConvertDefault(const std::string& domain, const std::string& package, const StructField& field);
+
144
+
145 std::string ConvertOutputStreamType(const std::string& type, const std::string& name, bool optional);
+
146 std::string ConvertOutputStreamValue(const std::string& type, const std::string& name, bool optional, bool separate, bool nullable);
+
147};
+
+
148
+
149} // namespace FBE
+
150
+
151#endif // GENERATOR_KOTLIN_H
+
Generator(const std::string &input, const std::string &output, int indent, char space)
Definition generator.inl:11
+ +
bool Final() const noexcept
+
GeneratorKotlin & Final(bool final) noexcept
+
void Generate(const std::shared_ptr< Package > &package) override
+
int Version() const noexcept
+
GeneratorKotlin & Version(int v) noexcept
+
GeneratorKotlin & JSON(bool json) noexcept
+
GeneratorKotlin & Proto(bool proto) noexcept
+
bool JSON() const noexcept
+
Generator(const std::string &input, const std::string &output, int indent, char space)
Definition generator.inl:11
+
bool Proto() const noexcept
+
Fast binary encoding generator definition.
+
Definition fbe.h:33
+
+ + +
+ + diff --git a/documents/html/generator__python_8cpp.html b/documents/html/generator__python_8cpp.html new file mode 100644 index 000000000..025621b0c --- /dev/null +++ b/documents/html/generator__python_8cpp.html @@ -0,0 +1,109 @@ + + + + + + + +FastBinaryEncoding: source/generator_python.cpp File Reference + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+ +
generator_python.cpp File Reference
+
+
+ +

Fast binary encoding Python generator implementation. +More...

+
#include "generator_python.h"
+
+

Go to the source code of this file.

+ + + +

+Namespaces

namespace  FBE
+

Detailed Description

+

Fast binary encoding Python generator implementation.

+
Author
Ivan Shynkarenka
+
Date
24.04.2018
+ + +

Definition in file generator_python.cpp.

+
+ + +
+ + diff --git a/documents/html/generator__python_8cpp_source.html b/documents/html/generator__python_8cpp_source.html new file mode 100644 index 000000000..92b42f747 --- /dev/null +++ b/documents/html/generator__python_8cpp_source.html @@ -0,0 +1,5607 @@ + + + + + + + +FastBinaryEncoding: source/generator_python.cpp Source File + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+
generator_python.cpp
+
+
+Go to the documentation of this file.
1
+
8
+
9#include "generator_python.h"
+
10
+
11namespace FBE {
+
12
+
+
13void GeneratorPython::Generate(const std::shared_ptr<Package>& package)
+
14{
+
15 GeneratePackage(package);
+
16}
+
+
17
+
18void GeneratorPython::GenerateHeader(const std::string& source)
+
19{
+
20 std::string code = R"CODE(#------------------------------------------------------------------------------
+
21# Automatically generated by the Fast Binary Encoding compiler, do not modify!
+
22# https://github.com/chronoxor/FastBinaryEncoding
+
23# Source: _INPUT_
+
24# FBE version: _VERSION_
+
25#------------------------------------------------------------------------------
+
26)CODE";
+
27
+
28 // Prepare code template
+
29 code = std::regex_replace(code, std::regex("_INPUT_"), source);
+
30 code = std::regex_replace(code, std::regex("_VERSION_"), version);
+
31 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
32
+
33 Write(code);
+
34}
+
35
+
36void GeneratorPython::GenerateFooter()
+
37{
+
38
+
39}
+
40
+
41void GeneratorPython::GenerateInit(const CppCommon::Path& path)
+
42{
+
43 // Open the init file
+
44 CppCommon::Path init = path / "__init__.py";
+
45 WriteBegin();
+
46
+
47 // Generate init header
+
48 GenerateHeader("FBE");
+
49
+
50 // Generate init footer
+
51 GenerateFooter();
+
52
+
53 // Close the init file
+
54 WriteEnd();
+
55 Store(init);
+
56}
+
57
+
58void GeneratorPython::GenerateFBE(const CppCommon::Path& path)
+
59{
+
60 // Generate the common file
+
61 CppCommon::Path common = path / "fbe.py";
+
62 WriteBegin();
+
63
+
64 // Generate common header
+
65 GenerateHeader("FBE");
+
66
+
67 std::string code = R"CODE(
+
68import base64
+
69import decimal
+
70import enum
+
71import json
+
72import struct
+
73import sys
+
74import time
+
75import uuid
+
76
+
77
+
78class DefaultEnumMeta(enum.EnumMeta):
+
79 default = object()
+
80
+
81 def __call__(cls, value=default, *args, **kwargs):
+
82 if value is DefaultEnumMeta.default:
+
83 return next(iter(cls))
+
84 return super().__call__(value, *args, **kwargs)
+
85
+
86
+
87class JSONEncoder(json.JSONEncoder):
+
88 def default(self, obj):
+
89 if hasattr(obj, "__to_json__"):
+
90 return obj.__to_json__()
+
91 elif isinstance(obj, bytes) or isinstance(obj, bytearray):
+
92 return base64.b64encode(obj).decode('ascii')
+
93 elif isinstance(obj, decimal.Decimal):
+
94 return str(obj)
+
95 elif isinstance(obj, uuid.UUID):
+
96 return str(obj)
+
97 elif isinstance(obj, set):
+
98 return list(obj)
+
99 else:
+
100 return super().default(self, obj)
+
101
+
102
+
103def epoch():
+
104 return 0
+
105
+
106
+
107def utc():
+
108 return time.time_ns()
+
109)CODE";
+
110
+
111 // Prepare code template
+
112 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
113
+
114 Write(code);
+
115
+
116 // Generate common models
+
117 GenerateFBEWriteBuffer();
+
118 GenerateFBEReadBuffer();
+
119 GenerateFBEModel();
+
120 GenerateFBEFieldModelBase();
+
121 GenerateFBEFieldModel();
+
122 GenerateFBEFieldModel("Bool", "bool", "1", "False");
+
123 GenerateFBEFieldModel("Byte", "byte", "1", "0");
+
124 GenerateFBEFieldModel("Char", "char", "1", "'\\0'");
+
125 GenerateFBEFieldModel("WChar", "wchar", "4", "'\\0'");
+
126 GenerateFBEFieldModel("Int8", "int8", "1", "0");
+
127 GenerateFBEFieldModel("UInt8", "uint8", "1", "0");
+
128 GenerateFBEFieldModel("Int16", "int16", "2", "0");
+
129 GenerateFBEFieldModel("UInt16", "uint16", "2", "0");
+
130 GenerateFBEFieldModel("Int32", "int32", "4", "0");
+
131 GenerateFBEFieldModel("UInt32", "uint32", "4", "0");
+
132 GenerateFBEFieldModel("Int64", "int64", "8", "0");
+
133 GenerateFBEFieldModel("UInt64", "uint64", "8", "0");
+
134 GenerateFBEFieldModel("Float", "float", "4", "0.0");
+
135 GenerateFBEFieldModel("Double", "double", "8", "0.0");
+
136 GenerateFBEFieldModel("Timestamp", "uint64", "8", "0");
+
137 GenerateFBEFieldModel("UUID", "uuid", "16", "uuid.UUID(int=0)");
+
138 GenerateFBEFieldModelDecimal();
+
139 GenerateFBEFieldModelBytes();
+
140 GenerateFBEFieldModelString();
+
141 GenerateFBEFieldModelOptional();
+
142 GenerateFBEFieldModelArray();
+
143 GenerateFBEFieldModelVector();
+
144 GenerateFBEFieldModelSet();
+
145 GenerateFBEFieldModelMap();
+
146 if (Final())
+
147 {
+
148 GenerateFBEFinalModel();
+
149 GenerateFBEFinalModel("Bool", "bool", "1", "False");
+
150 GenerateFBEFinalModel("Byte", "byte", "1", "0");
+
151 GenerateFBEFinalModel("Char", "char", "1", "'\\0'");
+
152 GenerateFBEFinalModel("WChar", "wchar", "4", "'\\0'");
+
153 GenerateFBEFinalModel("Int8", "int8", "1", "0");
+
154 GenerateFBEFinalModel("UInt8", "uint8", "1", "0");
+
155 GenerateFBEFinalModel("Int16", "int16", "2", "0");
+
156 GenerateFBEFinalModel("UInt16", "uint16", "2", "0");
+
157 GenerateFBEFinalModel("Int32", "int32", "4", "0");
+
158 GenerateFBEFinalModel("UInt32", "uint32", "4", "0");
+
159 GenerateFBEFinalModel("Int64", "int64", "8", "0");
+
160 GenerateFBEFinalModel("UInt64", "uint64", "8", "0");
+
161 GenerateFBEFinalModel("Float", "float", "4", "0.0");
+
162 GenerateFBEFinalModel("Double", "double", "8", "0.0");
+
163 GenerateFBEFinalModel("Timestamp", "uint64", "8", "0");
+
164 GenerateFBEFinalModel("UUID", "uuid", "16", "uuid.UUID(int=0)");
+
165 GenerateFBEFinalModelDecimal();
+
166 GenerateFBEFinalModelBytes();
+
167 GenerateFBEFinalModelString();
+
168 GenerateFBEFinalModelOptional();
+
169 GenerateFBEFinalModelArray();
+
170 GenerateFBEFinalModelVector();
+
171 GenerateFBEFinalModelSet();
+
172 GenerateFBEFinalModelMap();
+
173 }
+
174 if (Proto())
+
175 {
+
176 GenerateFBESender();
+
177 GenerateFBEReceiver();
+
178 }
+
179
+
180 // Generate common footer
+
181 GenerateFooter();
+
182
+
183 // Close the common file
+
184 WriteEnd();
+
185 Store(common);
+
186}
+
187
+
188void GeneratorPython::GenerateFBEWriteBuffer()
+
189{
+
190 std::string code = R"CODE(
+
191
+
192# Fast Binary Encoding write buffer based on the dynamic byte array
+
193class WriteBuffer(object):
+
194 __slots__ = "_buffer", "_offset", "_size",
+
195
+
196 def __init__(self, capacity=0):
+
197 self._buffer = bytearray(capacity)
+
198 self._size = 0
+
199 self._offset = 0
+
200
+
201 def __bool__(self):
+
202 return not self.empty
+
203
+
204 @property
+
205 def empty(self):
+
206 return (self._buffer is None) or (self._size <= 0)
+
207
+
208 @property
+
209 def buffer(self):
+
210 return self._buffer
+
211
+
212 @property
+
213 def capacity(self):
+
214 return len(self._buffer)
+
215
+
216 @property
+
217 def size(self):
+
218 return self._size
+
219
+
220 def __len__(self):
+
221 return self._size
+
222
+
223 @property
+
224 def offset(self):
+
225 return self._offset
+
226
+
227 # Attach an empty memory buffer
+
228 def attach_new(self):
+
229 self._buffer = bytearray()
+
230 self._size = 0
+
231 self._offset = 0
+
232
+
233 # Attach an empty memory buffer with a given capacity
+
234 def attach_capacity(self, capacity):
+
235 self._buffer = bytearray(capacity)
+
236 self._size = 0
+
237 self._offset = 0
+
238
+
239 # Attach a given memory buffer
+
240 def attach_buffer(self, buffer, offset=0, size=None):
+
241 assert (buffer is not None), "Invalid buffer!"
+
242 if buffer is None:
+
243 raise ValueError("Invalid buffer!")
+
244
+
245 if size is None:
+
246 size = len(buffer)
+
247
+
248 assert (size > 0), "Invalid size!"
+
249 if size <= 0:
+
250 raise ValueError("Invalid size!")
+
251 assert (offset <= size), "Invalid offset!"
+
252 if offset > size:
+
253 raise ValueError("Invalid offset!")
+
254
+
255 if isinstance(buffer, ReadBuffer) or isinstance(buffer, WriteBuffer):
+
256 self._buffer = buffer.buffer
+
257 else:
+
258 self._buffer = buffer
+
259 self._size = size
+
260 self._offset = offset
+
261
+
262 # Allocate memory in the current write buffer and return offset to the allocated memory block
+
263 def allocate(self, size):
+
264 assert (size >= 0), "Invalid allocation size!"
+
265 if size < 0:
+
266 raise ValueError("Invalid allocation size!")
+
267
+
268 offset = self._size
+
269
+
270 # Calculate a new buffer size
+
271 total = self._size + size
+
272
+
273 if total <= len(self._buffer):
+
274 self._size = total
+
275 return offset
+
276
+
277 data = bytearray(max(total, 2 * len(self._buffer)))
+
278 data[:self._size] = self._buffer
+
279 self._buffer = data
+
280 self._size = total
+
281 return offset
+
282
+
283 # Remove some memory of the given size from the current write buffer
+
284 def remove(self, offset, size):
+
285 assert ((offset + size) <= len(self._buffer)), "Invalid offset & size!"
+
286 if (offset + size) > len(self._buffer):
+
287 raise ValueError("Invalid offset & size!")
+
288
+
289 del self._buffer[offset:offset + size]
+
290 self._size -= size
+
291 if self._offset >= (offset + size):
+
292 self._offset -= size
+
293 elif self._offset >= offset:
+
294 self._offset -= self._offset - offset
+
295 if self._offset > self._size:
+
296 self._offset = self._size
+
297
+
298 # Reserve memory of the given capacity in the current write buffer
+
299 def reserve(self, capacity):
+
300 assert (capacity >= 0), "Invalid reserve capacity!"
+
301 if capacity < 0:
+
302 raise ValueError("Invalid reserve capacity!")
+
303
+
304 if capacity > len(self._buffer):
+
305 data = bytearray(max(capacity, 2 * len(self._buffer)))
+
306 data[:self._size] = self._buffer
+
307 self._buffer = data
+
308
+
309 # Resize the current write buffer
+
310 def resize(self, size):
+
311 self.reserve(size)
+
312 self._size = size
+
313 if self._offset > self._size:
+
314 self._offset = self._size
+
315
+
316 # Reset the current write buffer and its offset
+
317 def reset(self):
+
318 self._size = 0
+
319 self._offset = 0
+
320
+
321 # Shift the current write buffer offset
+
322 def shift(self, offset):
+
323 self._offset += offset
+
324
+
325 # Unshift the current write buffer offset
+
326 def unshift(self, offset):
+
327 self._offset -= offset
+
328)CODE";
+
329
+
330 // Prepare code template
+
331 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
332
+
333 Write(code);
+
334}
+
335
+
336void GeneratorPython::GenerateFBEReadBuffer()
+
337{
+
338 std::string code = R"CODE(
+
339
+
340# Fast Binary Encoding read buffer based on the constant byte buffer
+
341class ReadBuffer(object):
+
342 __slots__ = "_buffer", "_offset", "_size",
+
343
+
344 def __init__(self):
+
345 self._buffer = None
+
346 self._size = 0
+
347 self._offset = 0
+
348
+
349 def __bool__(self):
+
350 return self._buffer is not None
+
351
+
352 @property
+
353 def buffer(self):
+
354 return self._buffer
+
355
+
356 @property
+
357 def capacity(self):
+
358 return self._size
+
359
+
360 @property
+
361 def size(self):
+
362 return self._size
+
363
+
364 def __len__(self):
+
365 return self._size
+
366
+
367 @property
+
368 def offset(self):
+
369 return self._offset
+
370
+
371 # Attach a given memory buffer
+
372 def attach_buffer(self, buffer, offset=0, size=None):
+
373 assert (buffer is not None), "Invalid buffer!"
+
374 if buffer is None:
+
375 raise ValueError("Invalid buffer!")
+
376
+
377 if size is None:
+
378 size = len(buffer)
+
379
+
380 assert (size > 0), "Invalid size!"
+
381 if size <= 0:
+
382 raise ValueError("Invalid size!")
+
383 assert (offset <= size), "Invalid offset!"
+
384 if offset > size:
+
385 raise ValueError("Invalid offset!")
+
386
+
387 if isinstance(buffer, ReadBuffer) or isinstance(buffer, WriteBuffer):
+
388 self._buffer = buffer.buffer
+
389 else:
+
390 self._buffer = buffer
+
391 self._size = size
+
392 self._offset = offset
+
393
+
394 # Reset the current read buffer and its offset
+
395 def reset(self):
+
396 self._buffer = None
+
397 self._size = 0
+
398 self._offset = 0
+
399
+
400 # Shift the current read buffer offset
+
401 def shift(self, offset):
+
402 self._offset += offset
+
403
+
404 # Unshift the current read buffer offset
+
405 def unshift(self, offset):
+
406 self._offset -= offset
+
407)CODE";
+
408
+
409 // Prepare code template
+
410 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
411
+
412 Write(code);
+
413}
+
414
+
415void GeneratorPython::GenerateFBEModel()
+
416{
+
417 std::string code = R"CODE(
+
418
+
419# Fast Binary Encoding base model
+
420class Model(object):
+
421 __slots__ = "_buffer",
+
422
+
423 def __init__(self, buffer=None):
+
424 if buffer is None:
+
425 buffer = WriteBuffer()
+
426 self._buffer = buffer
+
427
+
428 @property
+
429 def buffer(self):
+
430 return self._buffer
+
431
+
432 # Attach an empty memory buffer
+
433 def attach_new(self):
+
434 self.buffer.attach_new()
+
435
+
436 # Attach an empty memory buffer with a given capacity
+
437 def attach_capacity(self, capacity):
+
438 self.buffer.attach_capacity(capacity)
+
439
+
440 # Attach a given memory buffer
+
441 def attach_buffer(self, buffer, offset=0, size=None):
+
442 self.buffer.attach_buffer(buffer, offset, size)
+
443
+
444 # Allocate memory in the current write buffer and return offset to the allocated memory block
+
445 def allocate(self, size):
+
446 return self.buffer.allocate(size)
+
447
+
448 # Remove some memory of the given size from the current write buffer
+
449 def remove(self, offset, size):
+
450 self.buffer.remove(offset, size)
+
451
+
452 # Reserve memory of the given capacity in the current write buffer
+
453 def reserve(self, capacity):
+
454 self.buffer.reserve(capacity)
+
455
+
456 # Resize the current write buffer
+
457 def resize(self, size):
+
458 self.buffer.resize(size)
+
459
+
460 # Reset the current write buffer and its offset
+
461 def reset(self):
+
462 self.buffer.reset()
+
463
+
464 # Shift the current write buffer offset
+
465 def shift(self, offset):
+
466 self.buffer.shift(offset)
+
467
+
468 # Unshift the current write buffer offset
+
469 def unshift(self, offset):
+
470 self.buffer.unshift(offset)
+
471
+
472 # Buffer I/O methods
+
473
+
474 def read_uint32(self, offset):
+
475 return struct.unpack_from("<I", self.buffer.buffer, self.buffer.offset + offset)[0]
+
476
+
477 def write_uint32(self, offset, value):
+
478 return struct.pack_into("<I", self.buffer.buffer, self.buffer.offset + offset, value)
+
479)CODE";
+
480
+
481 // Prepare code template
+
482 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
483
+
484 Write(code);
+
485}
+
486
+
487void GeneratorPython::GenerateFBEFieldModelBase()
+
488{
+
489 std::string code = R"CODE(
+
490
+
491# Fast Binary Encoding base field model
+
492class FieldModelBase(object):
+
493 __slots__ = "_buffer", "_offset",
+
494
+
495 def __init__(self, buffer, offset):
+
496 self._buffer = buffer
+
497 self._offset = offset
+
498
+
499 # Get the field offset
+
500 @property
+
501 def fbe_offset(self):
+
502 return self._offset
+
503
+
504 # Set the field offset
+
505 @fbe_offset.setter
+
506 def fbe_offset(self, offset):
+
507 self._offset = offset
+
508
+
509 # Get the field size
+
510 @property
+
511 def fbe_size(self):
+
512 return 0
+
513
+
514 # Get the field extra size
+
515 @property
+
516 def fbe_extra(self):
+
517 return 0
+
518
+
519 # Shift the current field offset
+
520 def fbe_shift(self, offset):
+
521 self._offset += offset
+
522
+
523 # Unshift the current field offset
+
524 def fbe_unshift(self, offset):
+
525 self._offset -= offset
+
526
+
527 # Buffer I/O methods
+
528
+
529 def read_bool(self, offset):
+
530 return struct.unpack_from("<?", self._buffer.buffer, self._buffer.offset + offset)[0]
+
531
+
532 def read_byte(self, offset):
+
533 return struct.unpack_from("<B", self._buffer.buffer, self._buffer.offset + offset)[0]
+
534
+
535 def read_char(self, offset):
+
536 return chr(struct.unpack_from("<B", self._buffer.buffer, self._buffer.offset + offset)[0])
+
537
+
538 def read_wchar(self, offset):
+
539 return chr(struct.unpack_from("<I", self._buffer.buffer, self._buffer.offset + offset)[0])
+
540
+
541 def read_int8(self, offset):
+
542 return struct.unpack_from("<b", self._buffer.buffer, self._buffer.offset + offset)[0]
+
543
+
544 def read_uint8(self, offset):
+
545 return struct.unpack_from("<B", self._buffer.buffer, self._buffer.offset + offset)[0]
+
546
+
547 def read_int16(self, offset):
+
548 return struct.unpack_from("<h", self._buffer.buffer, self._buffer.offset + offset)[0]
+
549
+
550 def read_uint16(self, offset):
+
551 return struct.unpack_from("<H", self._buffer.buffer, self._buffer.offset + offset)[0]
+
552
+
553 def read_int32(self, offset):
+
554 return struct.unpack_from("<i", self._buffer.buffer, self._buffer.offset + offset)[0]
+
555
+
556 def read_uint32(self, offset):
+
557 return struct.unpack_from("<I", self._buffer.buffer, self._buffer.offset + offset)[0]
+
558
+
559 def read_int64(self, offset):
+
560 return struct.unpack_from("<q", self._buffer.buffer, self._buffer.offset + offset)[0]
+
561
+
562 def read_uint64(self, offset):
+
563 return struct.unpack_from("<Q", self._buffer.buffer, self._buffer.offset + offset)[0]
+
564
+
565 def read_uint64_be(self, offset):
+
566 return struct.unpack_from(">Q", self._buffer.buffer, self._buffer.offset + offset)[0]
+
567
+
568 def read_float(self, offset):
+
569 return struct.unpack_from("<f", self._buffer.buffer, self._buffer.offset + offset)[0]
+
570
+
571 def read_double(self, offset):
+
572 return struct.unpack_from("<d", self._buffer.buffer, self._buffer.offset + offset)[0]
+
573
+
574 def read_bytes(self, offset, size):
+
575 return self._buffer.buffer[self._buffer.offset + offset:self._buffer.offset + offset + size]
+
576
+
577 def read_uuid(self, offset):
+
578 return uuid.UUID(int=((self.read_uint64_be(offset) << 64) | self.read_uint64_be(offset + 8)))
+
579
+
580 def write_bool(self, offset, value):
+
581 struct.pack_into("<?", self._buffer.buffer, self._buffer.offset + offset, value)
+
582
+
583 def write_byte(self, offset, value):
+
584 struct.pack_into("<B", self._buffer.buffer, self._buffer.offset + offset, value)
+
585
+
586 def write_char(self, offset, value):
+
587 struct.pack_into("<B", self._buffer.buffer, self._buffer.offset + offset, ord(value))
+
588
+
589 def write_wchar(self, offset, value):
+
590 struct.pack_into("<I", self._buffer.buffer, self._buffer.offset + offset, ord(value))
+
591
+
592 def write_int8(self, offset, value):
+
593 struct.pack_into("<b", self._buffer.buffer, self._buffer.offset + offset, value)
+
594
+
595 def write_uint8(self, offset, value):
+
596 struct.pack_into("<B", self._buffer.buffer, self._buffer.offset + offset, value)
+
597
+
598 def write_int16(self, offset, value):
+
599 struct.pack_into("<h", self._buffer.buffer, self._buffer.offset + offset, value)
+
600
+
601 def write_uint16(self, offset, value):
+
602 struct.pack_into("<H", self._buffer.buffer, self._buffer.offset + offset, value)
+
603
+
604 def write_int32(self, offset, value):
+
605 struct.pack_into("<i", self._buffer.buffer, self._buffer.offset + offset, value)
+
606
+
607 def write_uint32(self, offset, value):
+
608 struct.pack_into("<I", self._buffer.buffer, self._buffer.offset + offset, value)
+
609
+
610 def write_int64(self, offset, value):
+
611 struct.pack_into("<q", self._buffer.buffer, self._buffer.offset + offset, value)
+
612
+
613 def write_uint64(self, offset, value):
+
614 struct.pack_into("<Q", self._buffer.buffer, self._buffer.offset + offset, value)
+
615
+
616 def write_float(self, offset, value):
+
617 struct.pack_into("<f", self._buffer.buffer, self._buffer.offset + offset, value)
+
618
+
619 def write_double(self, offset, value):
+
620 struct.pack_into("<d", self._buffer.buffer, self._buffer.offset + offset, value)
+
621
+
622 def write_bytes(self, offset, buffer):
+
623 self._buffer.buffer[self._buffer.offset + offset:self._buffer.offset + offset + len(buffer)] = buffer
+
624
+
625 def write_count(self, offset, value, value_count):
+
626 for i in range(value_count):
+
627 self._buffer.buffer[self._buffer.offset + offset + i] = value
+
628
+
629 def write_uuid(self, offset, value):
+
630 self._buffer.buffer[self._buffer.offset + offset:self._buffer.offset + offset + 16] = value.bytes
+
631)CODE";
+
632
+
633 // Prepare code template
+
634 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
635
+
636 Write(code);
+
637}
+
638
+
639void GeneratorPython::GenerateFBEFieldModel()
+
640{
+
641 std::string code = R"CODE(
+
642
+
643# Fast Binary Encoding field model
+
644class FieldModel(FieldModelBase):
+
645 def __init__(self, buffer, offset):
+
646 super().__init__(buffer, offset)
+
647
+
648 # Check if the value is valid
+
649 def verify(self):
+
650 return True
+
651)CODE";
+
652
+
653 // Prepare code template
+
654 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
655
+
656 Write(code);
+
657}
+
658
+
659void GeneratorPython::GenerateFBEFieldModel(const std::string& name, const std::string& type, const std::string& size, const std::string& defaults)
+
660{
+
661 std::string code = R"CODE(
+
662
+
663# Fast Binary Encoding _TYPE_ field model
+
664class FieldModel_NAME_(FieldModel):
+
665 def __init__(self, buffer, offset):
+
666 super().__init__(buffer, offset)
+
667
+
668 # Get the field size
+
669 @property
+
670 def fbe_size(self):
+
671 return _SIZE_
+
672
+
673 # Get the value
+
674 def get(self, defaults=None):
+
675 if defaults is None:
+
676 defaults = _DEFAULTS_
+
677
+
678 if (self._buffer.offset + self.fbe_offset + self.fbe_size) > self._buffer.size:
+
679 return defaults
+
680
+
681 return self.read__TYPE_(self.fbe_offset)
+
682
+
683 # Set the value
+
684 def set(self, value):
+
685 assert ((self._buffer.offset + self.fbe_offset + self.fbe_size) <= self._buffer.size), "Model is broken!"
+
686 if (self._buffer.offset + self.fbe_offset + self.fbe_size) > self._buffer.size:
+
687 return
+
688
+
689 self.write__TYPE_(self.fbe_offset, value)
+
690)CODE";
+
691
+
692 // Prepare code template
+
693 code = std::regex_replace(code, std::regex("_NAME_"), name);
+
694 code = std::regex_replace(code, std::regex("_TYPE_"), type);
+
695 code = std::regex_replace(code, std::regex("_SIZE_"), size);
+
696 code = std::regex_replace(code, std::regex("_DEFAULTS_"), defaults);
+
697 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
698
+
699 Write(code);
+
700}
+
701
+
702void GeneratorPython::GenerateFBEFieldModelDecimal()
+
703{
+
704 std::string code = R"CODE(
+
705
+
706# Fast Binary Encoding decimal field model
+
707class FieldModelDecimal(FieldModel):
+
708 def __init__(self, buffer, offset):
+
709 super().__init__(buffer, offset)
+
710
+
711 # Get the field size
+
712 @property
+
713 def fbe_size(self):
+
714 return 16
+
715
+
716 # Get the decimal value
+
717 def get(self, defaults=None):
+
718 if defaults is None:
+
719 defaults = decimal.Decimal(0)
+
720
+
721 if (self._buffer.offset + self.fbe_offset + self.fbe_size) > self._buffer.size:
+
722 return defaults
+
723
+
724 # Read decimal parts
+
725 low = self.read_uint32(self.fbe_offset)
+
726 mid = self.read_uint32(self.fbe_offset + 4)
+
727 high = self.read_uint32(self.fbe_offset + 8)
+
728 flags = self.read_uint32(self.fbe_offset + 12)
+
729
+
730 # Calculate decimal value
+
731 negative = (flags & 0x80000000) != 0
+
732 scale = (flags & 0x7FFFFFFF) >> 16
+
733 result = decimal.Decimal(high) * 18446744073709551616
+
734 result += decimal.Decimal(mid) * 4294967296
+
735 result += decimal.Decimal(low)
+
736 result /= pow(10, scale)
+
737 if negative:
+
738 result = -result
+
739
+
740 return result
+
741
+
742 # Set the decimal value
+
743 def set(self, value):
+
744 assert ((self._buffer.offset + self.fbe_offset + self.fbe_size) <= self._buffer.size), "Model is broken!"
+
745 if (self._buffer.offset + self.fbe_offset + self.fbe_size) > self._buffer.size:
+
746 return
+
747
+
748 # Extract decimal parts
+
749 parts = value.as_tuple()
+
750 negative = True if parts.sign == 1 else False
+
751 number = int(''.join(map(str, parts.digits)))
+
752 scale = -parts.exponent
+
753
+
754 # Check for decimal number overflow
+
755 bits = number.bit_length()
+
756 if (bits < 0) or (bits > 96):
+
757 # Value too big for .NET Decimal (bit length is limited to [0, 96])
+
758 self.write_count(self.fbe_offset, 0, self.fbe_size)
+
759 return
+
760
+
761 # Check for decimal scale overflow
+
762 if (scale < 0) or (scale > 28):
+
763 # Value scale exceeds .NET Decimal limit of [0, 28]
+
764 self.write_count(self.fbe_offset, 0, self.fbe_size)
+
765 return
+
766
+
767 # Write unscaled value to bytes 0-11
+
768 self.write_bytes(self.fbe_offset, number.to_bytes(12, "little"))
+
769
+
770 # Write scale at byte 14
+
771 self.write_byte(self.fbe_offset + 14, scale)
+
772
+
773 # Write signum at byte 15
+
774 self.write_byte(self.fbe_offset + 15, 0x80 if negative else 0)
+
775)CODE";
+
776
+
777 // Prepare code template
+
778 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
779
+
780 Write(code);
+
781}
+
782
+
783void GeneratorPython::GenerateFBEFieldModelBytes()
+
784{
+
785 std::string code = R"CODE(
+
786
+
787# Fast Binary Encoding bytes field model
+
788class FieldModelBytes(FieldModel):
+
789 def __init__(self, buffer, offset):
+
790 super().__init__(buffer, offset)
+
791
+
792 # Get the field size
+
793 @property
+
794 def fbe_size(self):
+
795 return 4
+
796
+
797 # Get the field extra size
+
798 @property
+
799 def fbe_extra(self):
+
800 if (self._buffer.offset + self.fbe_offset + self.fbe_size) > self._buffer.size:
+
801 return 0
+
802
+
803 fbe_bytes_offset = self.read_uint32(self.fbe_offset)
+
804 if (fbe_bytes_offset == 0) or ((self._buffer.offset + fbe_bytes_offset + 4) > self._buffer.size):
+
805 return 0
+
806
+
807 fbe_bytes_size = self.read_uint32(fbe_bytes_offset)
+
808 return 4 + fbe_bytes_size
+
809
+
810 # Check if the bytes value is valid
+
811 def verify(self):
+
812 if (self._buffer.offset + self.fbe_offset + self.fbe_size) > self._buffer.size:
+
813 return True
+
814
+
815 fbe_bytes_offset = self.read_uint32(self.fbe_offset)
+
816 if fbe_bytes_offset == 0:
+
817 return True
+
818
+
819 if (self._buffer.offset + fbe_bytes_offset + 4) > self._buffer.size:
+
820 return False
+
821
+
822 fbe_bytes_size = self.read_uint32(fbe_bytes_offset)
+
823 if (self._buffer.offset + fbe_bytes_offset + 4 + fbe_bytes_size) > self._buffer.size:
+
824 return False
+
825
+
826 return True
+
827
+
828 # Get the bytes value
+
829 def get(self, defaults=None):
+
830 if defaults is None:
+
831 defaults = bytearray()
+
832
+
833 if (self._buffer.offset + self.fbe_offset + self.fbe_size) > self._buffer.size:
+
834 return defaults
+
835
+
836 fbe_bytes_offset = self.read_uint32(self.fbe_offset)
+
837 if fbe_bytes_offset == 0:
+
838 return defaults
+
839
+
840 assert ((self._buffer.offset + fbe_bytes_offset + 4) <= self._buffer.size), "Model is broken!"
+
841 if (self._buffer.offset + fbe_bytes_offset + 4) > self._buffer.size:
+
842 return defaults
+
843
+
844 fbe_bytes_size = self.read_uint32(fbe_bytes_offset)
+
845 assert ((self._buffer.offset + fbe_bytes_offset + 4 + fbe_bytes_size) <= self._buffer.size), "Model is broken!"
+
846 if (self._buffer.offset + fbe_bytes_offset + 4 + fbe_bytes_size) > self._buffer.size:
+
847 return defaults
+
848
+
849 return self.read_bytes(fbe_bytes_offset + 4, fbe_bytes_size)
+
850
+
851 # Set the bytes value
+
852 def set(self, value):
+
853 assert (value is not None), "Invalid bytes value!"
+
854 if value is None:
+
855 raise ValueError("Invalid bytes value!")
+
856
+
857 assert ((self._buffer.offset + self.fbe_offset + self.fbe_size) <= self._buffer.size), "Model is broken!"
+
858 if (self._buffer.offset + self.fbe_offset + self.fbe_size) > self._buffer.size:
+
859 return
+
860
+
861 fbe_bytes_size = len(value)
+
862 fbe_bytes_offset = self._buffer.allocate(4 + fbe_bytes_size) - self._buffer.offset
+
863 assert ((fbe_bytes_offset > 0) and ((self._buffer.offset + fbe_bytes_offset + 4 + fbe_bytes_size) <= self._buffer.size)), "Model is broken!"
+
864 if (fbe_bytes_offset <= 0) or ((self._buffer.offset + fbe_bytes_offset + 4 + fbe_bytes_size) > self._buffer.size):
+
865 return
+
866
+
867 self.write_uint32(self.fbe_offset, fbe_bytes_offset)
+
868 self.write_uint32(fbe_bytes_offset, fbe_bytes_size)
+
869 self.write_bytes(fbe_bytes_offset + 4, value)
+
870)CODE";
+
871
+
872 // Prepare code template
+
873 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
874
+
875 Write(code);
+
876}
+
877
+
878void GeneratorPython::GenerateFBEFieldModelString()
+
879{
+
880 std::string code = R"CODE(
+
881
+
882# Fast Binary Encoding string field model
+
883class FieldModelString(FieldModel):
+
884 def __init__(self, buffer, offset):
+
885 super().__init__(buffer, offset)
+
886
+
887 # Get the field size
+
888 @property
+
889 def fbe_size(self):
+
890 return 4
+
891
+
892 # Get the field extra size
+
893 @property
+
894 def fbe_extra(self):
+
895 if (self._buffer.offset + self.fbe_offset + self.fbe_size) > self._buffer.size:
+
896 return 0
+
897
+
898 fbe_string_offset = self.read_uint32(self.fbe_offset)
+
899 if (fbe_string_offset == 0) or ((self._buffer.offset + fbe_string_offset + 4) > self._buffer.size):
+
900 return 0
+
901
+
902 fbe_string_size = self.read_uint32(fbe_string_offset)
+
903 return 4 + fbe_string_size
+
904
+
905 # Check if the string value is valid
+
906 def verify(self):
+
907 if (self._buffer.offset + self.fbe_offset + self.fbe_size) > self._buffer.size:
+
908 return True
+
909
+
910 fbe_string_offset = self.read_uint32(self.fbe_offset)
+
911 if fbe_string_offset == 0:
+
912 return True
+
913
+
914 if (self._buffer.offset + fbe_string_offset + 4) > self._buffer.size:
+
915 return False
+
916
+
917 fbe_string_size = self.read_uint32(fbe_string_offset)
+
918 if (self._buffer.offset + fbe_string_offset + 4 + fbe_string_size) > self._buffer.size:
+
919 return False
+
920
+
921 return True
+
922
+
923 # Get the string value
+
924 def get(self, defaults=None):
+
925 if defaults is None:
+
926 defaults = ""
+
927
+
928 if (self._buffer.offset + self.fbe_offset + self.fbe_size) > self._buffer.size:
+
929 return defaults
+
930
+
931 fbe_string_offset = self.read_uint32(self.fbe_offset)
+
932 if fbe_string_offset == 0:
+
933 return defaults
+
934
+
935 assert ((self._buffer.offset + fbe_string_offset + 4) <= self._buffer.size), "Model is broken!"
+
936 if (self._buffer.offset + fbe_string_offset + 4) > self._buffer.size:
+
937 return defaults
+
938
+
939 fbe_string_size = self.read_uint32(fbe_string_offset)
+
940 assert ((self._buffer.offset + fbe_string_offset + 4 + fbe_string_size) <= self._buffer.size), "Model is broken!"
+
941 if (self._buffer.offset + fbe_string_offset + 4 + fbe_string_size) > self._buffer.size:
+
942 return defaults
+
943
+
944 data = self.read_bytes(fbe_string_offset + 4, fbe_string_size)
+
945 return data.decode("utf-8")
+
946
+
947 # Set the string value
+
948 def set(self, value):
+
949 assert (value is not None), "Invalid string value!"
+
950 if value is None:
+
951 raise ValueError("Invalid string value!")
+
952
+
953 assert ((self._buffer.offset + self.fbe_offset + self.fbe_size) <= self._buffer.size), "Model is broken!"
+
954 if (self._buffer.offset + self.fbe_offset + self.fbe_size) > self._buffer.size:
+
955 return
+
956
+
957 data = value.encode("utf-8")
+
958
+
959 fbe_string_size = len(data)
+
960 fbe_string_offset = self._buffer.allocate(4 + fbe_string_size) - self._buffer.offset
+
961 assert ((fbe_string_offset > 0) and ((self._buffer.offset + fbe_string_offset + 4 + fbe_string_size) <= self._buffer.size)), "Model is broken!"
+
962 if (fbe_string_offset <= 0) or ((self._buffer.offset + fbe_string_offset + 4 + fbe_string_size) > self._buffer.size):
+
963 return
+
964
+
965 self.write_uint32(self.fbe_offset, fbe_string_offset)
+
966 self.write_uint32(fbe_string_offset, fbe_string_size)
+
967 self.write_bytes(fbe_string_offset + 4, data)
+
968)CODE";
+
969
+
970 // Prepare code template
+
971 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
972
+
973 Write(code);
+
974}
+
975
+
976void GeneratorPython::GenerateFBEFieldModelOptional()
+
977{
+
978 std::string code = R"CODE(
+
979
+
980# Fast Binary Encoding optional field model
+
981class FieldModelOptional(FieldModel):
+
982 __slots__ = "_model",
+
983
+
984 def __init__(self, model, buffer, offset):
+
985 super().__init__(buffer, offset)
+
986 self._model = model
+
987 self._model.fbe_offset = 0
+
988
+
989 # Get the field size
+
990 @property
+
991 def fbe_size(self):
+
992 return 1 + 4
+
993
+
994 # Get the field extra size
+
995 @property
+
996 def fbe_extra(self):
+
997 if not self.has_value:
+
998 return 0
+
999
+
1000 fbe_optional_offset = self.read_uint32(self.fbe_offset + 1)
+
1001 if (fbe_optional_offset == 0) or ((self._buffer.offset + fbe_optional_offset + 4) > self._buffer.size):
+
1002 return 0
+
1003
+
1004 self._buffer.shift(fbe_optional_offset)
+
1005 fbe_result = self.value.fbe_size + self.value.fbe_extra
+
1006 self._buffer.unshift(fbe_optional_offset)
+
1007 return fbe_result
+
1008
+
1009 # Checks if the object contains a value
+
1010 def __bool__(self):
+
1011 return self.has_value()
+
1012
+
1013 # Checks if the object contains a value
+
1014 @property
+
1015 def has_value(self):
+
1016 if (self._buffer.offset + self.fbe_offset + self.fbe_size) > self._buffer.size:
+
1017 return False
+
1018
+
1019 fbe_has_value = self.read_uint8(self.fbe_offset)
+
1020 return fbe_has_value != 0
+
1021
+
1022 # Get the base field model value
+
1023 @property
+
1024 def value(self):
+
1025 return self._model
+
1026
+
1027 # Check if the optional value is valid
+
1028 def verify(self):
+
1029 if (self._buffer.offset + self.fbe_offset + self.fbe_size) > self._buffer.size:
+
1030 return True
+
1031
+
1032 fbe_has_value = self.read_uint8(self.fbe_offset)
+
1033 if fbe_has_value == 0:
+
1034 return True
+
1035
+
1036 fbe_optional_offset = self.read_uint32(self.fbe_offset + 1)
+
1037 if fbe_optional_offset == 0:
+
1038 return False
+
1039
+
1040 self._buffer.shift(fbe_optional_offset)
+
1041 fbe_result = self.value.verify()
+
1042 self._buffer.unshift(fbe_optional_offset)
+
1043 return fbe_result
+
1044
+
1045 # Get the optional value (being phase)
+
1046 def get_begin(self):
+
1047 if not self.has_value:
+
1048 return 0
+
1049
+
1050 fbe_optional_offset = self.read_uint32(self.fbe_offset + 1)
+
1051 assert (fbe_optional_offset > 0), "Model is broken!"
+
1052 if fbe_optional_offset <= 0:
+
1053 return 0
+
1054
+
1055 self._buffer.shift(fbe_optional_offset)
+
1056 return fbe_optional_offset
+
1057
+
1058 # Get the optional value (end phase)
+
1059 def get_end(self, fbe_begin):
+
1060 self._buffer.unshift(fbe_begin)
+
1061
+
1062 # Get the optional value
+
1063 def get(self, defaults=None):
+
1064 fbe_begin = self.get_begin()
+
1065 if fbe_begin == 0:
+
1066 return defaults
+
1067 optional = self.value.get()
+
1068 self.get_end(fbe_begin)
+
1069 return optional
+
1070
+
1071 # Set the optional value (begin phase)
+
1072 def set_begin(self, has_value):
+
1073 assert ((self._buffer.offset + self.fbe_offset + self.fbe_size) <= self._buffer.size), "Model is broken!"
+
1074 if (self._buffer.offset + self.fbe_offset + self.fbe_size) > self._buffer.size:
+
1075 return 0
+
1076
+
1077 fbe_has_value = 1 if has_value else 0
+
1078 self.write_uint8(self.fbe_offset, fbe_has_value)
+
1079 if fbe_has_value == 0:
+
1080 return 0
+
1081
+
1082 fbe_optional_size = self.value.fbe_size
+
1083 fbe_optional_offset = self._buffer.allocate(fbe_optional_size) - self._buffer.offset
+
1084 assert ((fbe_optional_offset > 0) and ((self._buffer.offset + fbe_optional_offset + fbe_optional_size) <= self._buffer.size)), "Model is broken!"
+
1085 if (fbe_optional_offset <= 0) or ((self._buffer.offset + fbe_optional_offset + fbe_optional_size) > self._buffer.size):
+
1086 return 0
+
1087
+
1088 self.write_uint32(self.fbe_offset + 1, fbe_optional_offset)
+
1089
+
1090 self._buffer.shift(fbe_optional_offset)
+
1091 return fbe_optional_offset
+
1092
+
1093 # Set the optional value (end phase)
+
1094 def set_end(self, fbe_begin):
+
1095 self._buffer.unshift(fbe_begin)
+
1096
+
1097 # Set the optional value
+
1098 def set(self, optional):
+
1099 fbe_begin = self.set_begin(optional is not None)
+
1100 if fbe_begin == 0:
+
1101 return
+
1102 self.value.set(optional)
+
1103 self.set_end(fbe_begin)
+
1104)CODE";
+
1105
+
1106 // Prepare code template
+
1107 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
1108
+
1109 Write(code);
+
1110}
+
1111
+
1112void GeneratorPython::GenerateFBEFieldModelArray()
+
1113{
+
1114 std::string code = R"CODE(
+
1115
+
1116# Fast Binary Encoding array field model
+
1117class FieldModelArray(FieldModel):
+
1118 __slots__ = "_model", "_size",
+
1119
+
1120 def __init__(self, model, buffer, offset, size):
+
1121 super().__init__(buffer, offset)
+
1122 self._model = model
+
1123 self._size = size
+
1124
+
1125 # Get the field size
+
1126 @property
+
1127 def fbe_size(self):
+
1128 return self._size * self._model.fbe_size
+
1129
+
1130 # Get the field extra size
+
1131 @property
+
1132 def fbe_extra(self):
+
1133 return 0
+
1134
+
1135 # Get the array offset
+
1136 @property
+
1137 def offset(self):
+
1138 return 0
+
1139
+
1140 # Get the array size
+
1141 @property
+
1142 def size(self):
+
1143 return self._size
+
1144
+
1145 # Array index operator
+
1146 def __getitem__(self, index):
+
1147 assert ((self._buffer.offset + self.fbe_offset + self.fbe_size) <= self._buffer.size), "Model is broken!"
+
1148 assert (index < self._size), "Index is out of bounds!"
+
1149 if index >= self._size:
+
1150 raise IndexError("Index is out of bounds!")
+
1151
+
1152 self._model.fbe_offset = self.fbe_offset
+
1153 self._model.fbe_shift(index * self._model.fbe_size)
+
1154 return self._model
+
1155
+
1156 # Check if the array is valid
+
1157 def verify(self):
+
1158 if (self._buffer.offset + self.fbe_offset + self.fbe_size) > self._buffer.size:
+
1159 return False
+
1160
+
1161 self._model.fbe_offset = self.fbe_offset
+
1162 for i in range(self._size):
+
1163 if not self._model.verify():
+
1164 return False
+
1165 self._model.fbe_shift(self._model.fbe_size)
+
1166
+
1167 return True
+
1168
+
1169 # Get the array
+
1170 def get(self, values=None):
+
1171 if values is None:
+
1172 values = list()
+
1173
+
1174 values.clear()
+
1175
+
1176 fbe_model = self[0]
+
1177 for i in range(self._size):
+
1178 value = fbe_model.get()
+
1179 values.append(value)
+
1180 fbe_model.fbe_shift(fbe_model.fbe_size)
+
1181
+
1182 return values
+
1183
+
1184 # Set the array
+
1185 def set(self, values):
+
1186 assert (values is not None), "Invalid values parameter!"
+
1187 if values is None:
+
1188 raise ValueError("Invalid values parameter!")
+
1189
+
1190 assert ((self._buffer.offset + self.fbe_offset + self.fbe_size) <= self._buffer.size), "Model is broken!"
+
1191 if (self._buffer.offset + self.fbe_offset + self.fbe_size) > self._buffer.size:
+
1192 return
+
1193
+
1194 fbe_model = self[0]
+
1195 for i in range(min(len(values), self._size)):
+
1196 fbe_model.set(values[i])
+
1197 fbe_model.fbe_shift(fbe_model.fbe_size)
+
1198)CODE";
+
1199
+
1200 // Prepare code template
+
1201 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
1202
+
1203 Write(code);
+
1204}
+
1205
+
1206void GeneratorPython::GenerateFBEFieldModelVector()
+
1207{
+
1208 std::string code = R"CODE(
+
1209
+
1210# Fast Binary Encoding vector field model
+
1211class FieldModelVector(FieldModel):
+
1212 __slots__ = "_model",
+
1213
+
1214 def __init__(self, model, buffer, offset):
+
1215 super().__init__(buffer, offset)
+
1216 self._model = model
+
1217
+
1218 # Get the field size
+
1219 @property
+
1220 def fbe_size(self):
+
1221 return 4
+
1222
+
1223 # Get the field extra size
+
1224 @property
+
1225 def fbe_extra(self):
+
1226 if (self._buffer.offset + self.fbe_offset + self.fbe_size) > self._buffer.size:
+
1227 return 0
+
1228
+
1229 fbe_vector_offset = self.read_uint32(self.fbe_offset)
+
1230 if (fbe_vector_offset == 0) or ((self._buffer.offset + fbe_vector_offset + 4) > self._buffer.size):
+
1231 return 0
+
1232
+
1233 fbe_vector_size = self.read_uint32(fbe_vector_offset)
+
1234
+
1235 fbe_result = 4
+
1236 self._model.fbe_offset = fbe_vector_offset + 4
+
1237 for i in range(fbe_vector_size):
+
1238 fbe_result += self._model.fbe_size + self._model.fbe_extra
+
1239 self._model.fbe_shift(self._model.fbe_size)
+
1240 return fbe_result
+
1241
+
1242 # Get the vector offset
+
1243 @property
+
1244 def offset(self):
+
1245 if (self._buffer.offset + self.fbe_offset + self.fbe_size) > self._buffer.size:
+
1246 return 0
+
1247
+
1248 fbe_vector_offset = self.read_uint32(self.fbe_offset)
+
1249 return fbe_vector_offset
+
1250
+
1251 # Get the vector size
+
1252 @property
+
1253 def size(self):
+
1254 if (self._buffer.offset + self.fbe_offset + self.fbe_size) > self._buffer.size:
+
1255 return 0
+
1256
+
1257 fbe_vector_offset = self.read_uint32(self.fbe_offset)
+
1258 if (fbe_vector_offset == 0) or ((self._buffer.offset + fbe_vector_offset + 4) > self._buffer.size):
+
1259 return 0
+
1260
+
1261 fbe_vector_size = self.read_uint32(fbe_vector_offset)
+
1262 return fbe_vector_size
+
1263
+
1264 # Vector index operator
+
1265 def __getitem__(self, index):
+
1266 assert ((self._buffer.offset + self.fbe_offset + self.fbe_size) <= self._buffer.size), "Model is broken!"
+
1267
+
1268 fbe_vector_offset = self.read_uint32(self.fbe_offset)
+
1269 assert ((fbe_vector_offset > 0) and ((self._buffer.offset + fbe_vector_offset + 4) <= self._buffer.size)), "Model is broken!"
+
1270
+
1271 fbe_vector_size = self.read_uint32(fbe_vector_offset)
+
1272 assert (index < fbe_vector_size), "Index is out of bounds!"
+
1273 if index >= fbe_vector_size:
+
1274 raise IndexError("Index is out of bounds!")
+
1275
+
1276 self._model.fbe_offset = fbe_vector_offset + 4
+
1277 self._model.fbe_shift(index * self._model.fbe_size)
+
1278 return self._model
+
1279
+
1280 # Resize the vector and get its first model
+
1281 def resize(self, size):
+
1282 fbe_vector_size = size * self._model.fbe_size
+
1283 fbe_vector_offset = self._buffer.allocate(4 + fbe_vector_size) - self._buffer.offset
+
1284 assert ((fbe_vector_offset > 0) and ((self._buffer.offset + fbe_vector_offset + 4) <= self._buffer.size)), "Model is broken!"
+
1285
+
1286 self.write_uint32(self.fbe_offset, fbe_vector_offset)
+
1287 self.write_uint32(fbe_vector_offset, size)
+
1288 self.write_count(fbe_vector_offset + 4, 0, fbe_vector_size)
+
1289
+
1290 self._model.fbe_offset = fbe_vector_offset + 4
+
1291 return self._model
+
1292
+
1293 # Check if the vector is valid
+
1294 def verify(self):
+
1295 if (self._buffer.offset + self.fbe_offset + self.fbe_size) > self._buffer.size:
+
1296 return True
+
1297
+
1298 fbe_vector_offset = self.read_uint32(self.fbe_offset)
+
1299 if fbe_vector_offset == 0:
+
1300 return True
+
1301
+
1302 if (self._buffer.offset + fbe_vector_offset + 4) > self._buffer.size:
+
1303 return False
+
1304
+
1305 fbe_vector_size = self.read_uint32(fbe_vector_offset)
+
1306
+
1307 self._model.fbe_offset = fbe_vector_offset + 4
+
1308 for i in range(fbe_vector_size):
+
1309 if not self._model.verify():
+
1310 return False
+
1311 self._model.fbe_shift(self._model.fbe_size)
+
1312
+
1313 return True
+
1314
+
1315 # Get the vector
+
1316 def get(self, values=None):
+
1317 if values is None:
+
1318 values = list()
+
1319
+
1320 values.clear()
+
1321
+
1322 fbe_vector_size = self.size
+
1323 if fbe_vector_size == 0:
+
1324 return values
+
1325
+
1326 fbe_model = self[0]
+
1327 for i in range(fbe_vector_size):
+
1328 value = fbe_model.get()
+
1329 values.append(value)
+
1330 fbe_model.fbe_shift(fbe_model.fbe_size)
+
1331
+
1332 return values
+
1333
+
1334 # Set the vector
+
1335 def set(self, values):
+
1336 assert (values is not None), "Invalid values parameter!"
+
1337 if values is None:
+
1338 raise ValueError("Invalid values parameter!")
+
1339
+
1340 assert ((self._buffer.offset + self.fbe_offset + self.fbe_size) <= self._buffer.size), "Model is broken!"
+
1341 if (self._buffer.offset + self.fbe_offset + self.fbe_size) > self._buffer.size:
+
1342 return
+
1343
+
1344 fbe_model = self.resize(len(values))
+
1345 for value in values:
+
1346 fbe_model.set(value)
+
1347 fbe_model.fbe_shift(fbe_model.fbe_size)
+
1348)CODE";
+
1349
+
1350 // Prepare code template
+
1351 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
1352
+
1353 Write(code);
+
1354}
+
1355
+
1356void GeneratorPython::GenerateFBEFieldModelSet()
+
1357{
+
1358 std::string code = R"CODE(
+
1359
+
1360# Fast Binary Encoding set field model
+
1361class FieldModelSet(FieldModel):
+
1362 __slots__ = "_model",
+
1363
+
1364 def __init__(self, model, buffer, offset):
+
1365 super().__init__(buffer, offset)
+
1366 self._model = model
+
1367
+
1368 # Get the field size
+
1369 @property
+
1370 def fbe_size(self):
+
1371 return 4
+
1372
+
1373 # Get the field extra size
+
1374 @property
+
1375 def fbe_extra(self):
+
1376 if (self._buffer.offset + self.fbe_offset + self.fbe_size) > self._buffer.size:
+
1377 return 0
+
1378
+
1379 fbe_set_offset = self.read_uint32(self.fbe_offset)
+
1380 if (fbe_set_offset == 0) or ((self._buffer.offset + fbe_set_offset + 4) > self._buffer.size):
+
1381 return 0
+
1382
+
1383 fbe_set_size = self.read_uint32(fbe_set_offset)
+
1384
+
1385 fbe_result = 4
+
1386 self._model.fbe_offset = fbe_set_offset + 4
+
1387 for i in range(fbe_set_size):
+
1388 fbe_result += self._model.fbe_size + self._model.fbe_extra
+
1389 self._model.fbe_shift(self._model.fbe_size)
+
1390 return fbe_result
+
1391
+
1392 # Get the set value offset
+
1393 @property
+
1394 def offset(self):
+
1395 if (self._buffer.offset + self.fbe_offset + self.fbe_size) > self._buffer.size:
+
1396 return 0
+
1397
+
1398 fbe_set_offset = self.read_uint32(self.fbe_offset)
+
1399 return fbe_set_offset
+
1400
+
1401 # Get the set value size
+
1402 @property
+
1403 def size(self):
+
1404 if (self._buffer.offset + self.fbe_offset + self.fbe_size) > self._buffer.size:
+
1405 return 0
+
1406
+
1407 fbe_set_offset = self.read_uint32(self.fbe_offset)
+
1408 if (fbe_set_offset == 0) or ((self._buffer.offset + fbe_set_offset + 4) > self._buffer.size):
+
1409 return 0
+
1410
+
1411 fbe_set_size = self.read_uint32(fbe_set_offset)
+
1412 return fbe_set_size
+
1413
+
1414 # Set index operator
+
1415 def __getitem__(self, index):
+
1416 assert ((self._buffer.offset + self.fbe_offset + self.fbe_size) <= self._buffer.size), "Model is broken!"
+
1417
+
1418 fbe_set_offset = self.read_uint32(self.fbe_offset)
+
1419 assert ((fbe_set_offset > 0) and ((self._buffer.offset + fbe_set_offset + 4) <= self._buffer.size)), "Model is broken!"
+
1420
+
1421 fbe_set_size = self.read_uint32(fbe_set_offset)
+
1422 assert (index < fbe_set_size), "Index is out of bounds!"
+
1423 if index >= fbe_set_size:
+
1424 raise IndexError("Index is out of bounds!")
+
1425
+
1426 self._model.fbe_offset = fbe_set_offset + 4
+
1427 self._model.fbe_shift(index * self._model.fbe_size)
+
1428 return self._model
+
1429
+
1430 # Resize the set and get its first model
+
1431 def resize(self, size):
+
1432 fbe_set_size = size * self._model.fbe_size
+
1433 fbe_set_offset = self._buffer.allocate(4 + fbe_set_size) - self._buffer.offset
+
1434 assert ((fbe_set_offset > 0) and ((self._buffer.offset + fbe_set_offset + 4) <= self._buffer.size)), "Model is broken!"
+
1435
+
1436 self.write_uint32(self.fbe_offset, fbe_set_offset)
+
1437 self.write_uint32(fbe_set_offset, size)
+
1438 self.write_count(fbe_set_offset + 4, 0, fbe_set_size)
+
1439
+
1440 self._model.fbe_offset = fbe_set_offset + 4
+
1441 return self._model
+
1442
+
1443 # Check if the set value is valid
+
1444 def verify(self):
+
1445 if (self._buffer.offset + self.fbe_offset + self.fbe_size) > self._buffer.size:
+
1446 return True
+
1447
+
1448 fbe_set_offset = self.read_uint32(self.fbe_offset)
+
1449 if fbe_set_offset == 0:
+
1450 return True
+
1451
+
1452 if (self._buffer.offset + fbe_set_offset + 4) > self._buffer.size:
+
1453 return False
+
1454
+
1455 fbe_set_size = self.read_uint32(fbe_set_offset)
+
1456
+
1457 self._model.fbe_offset = fbe_set_offset + 4
+
1458 for i in range(fbe_set_size):
+
1459 if not self._model.verify():
+
1460 return False
+
1461 self._model.fbe_shift(self._model.fbe_size)
+
1462
+
1463 return True
+
1464
+
1465 # Get the set value
+
1466 def get(self, values=None):
+
1467 if values is None:
+
1468 values = set()
+
1469
+
1470 values.clear()
+
1471
+
1472 fbe_set_size = self.size
+
1473 if fbe_set_size == 0:
+
1474 return values
+
1475
+
1476 fbe_model = self[0]
+
1477 for i in range(fbe_set_size):
+
1478 value = fbe_model.get()
+
1479 values.add(value)
+
1480 fbe_model.fbe_shift(fbe_model.fbe_size)
+
1481
+
1482 return values
+
1483
+
1484 # Set the set value
+
1485 def set(self, values):
+
1486 assert (values is not None), "Invalid values parameter!"
+
1487 if values is None:
+
1488 raise ValueError("Invalid values parameter!")
+
1489
+
1490 assert ((self._buffer.offset + self.fbe_offset + self.fbe_size) <= self._buffer.size), "Model is broken!"
+
1491 if (self._buffer.offset + self.fbe_offset + self.fbe_size) > self._buffer.size:
+
1492 return
+
1493
+
1494 fbe_model = self.resize(len(values))
+
1495 for value in values:
+
1496 fbe_model.set(value)
+
1497 fbe_model.fbe_shift(fbe_model.fbe_size)
+
1498)CODE";
+
1499
+
1500 // Prepare code template
+
1501 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
1502
+
1503 Write(code);
+
1504}
+
1505
+
1506void GeneratorPython::GenerateFBEFieldModelMap()
+
1507{
+
1508 std::string code = R"CODE(
+
1509
+
1510# Fast Binary Encoding map field model
+
1511class FieldModelMap(FieldModel):
+
1512 __slots__ = "_model_key", "_model_value",
+
1513
+
1514 def __init__(self, model_key, model_value, buffer, offset):
+
1515 super().__init__(buffer, offset)
+
1516 self._model_key = model_key
+
1517 self._model_value = model_value
+
1518
+
1519 # Get the field size
+
1520 @property
+
1521 def fbe_size(self):
+
1522 return 4
+
1523
+
1524 # Get the field extra size
+
1525 @property
+
1526 def fbe_extra(self):
+
1527 if (self._buffer.offset + self.fbe_offset + self.fbe_size) > self._buffer.size:
+
1528 return 0
+
1529
+
1530 fbe_map_offset = self.read_uint32(self.fbe_offset)
+
1531 if (fbe_map_offset == 0) or ((self._buffer.offset + fbe_map_offset + 4) > self._buffer.size):
+
1532 return 0
+
1533
+
1534 fbe_map_size = self.read_uint32(fbe_map_offset)
+
1535
+
1536 fbe_result = 4
+
1537 self._model_key.fbe_offset = fbe_map_offset + 4
+
1538 self._model_value.fbe_offset = fbe_map_offset + 4 + self._model_key.fbe_size
+
1539 for i in range(fbe_map_size):
+
1540 fbe_result += self._model_key.fbe_size + self._model_key.fbe_extra
+
1541 self._model_key.fbe_shift(self._model_key.fbe_size + self._model_value.fbe_size)
+
1542 fbe_result += self._model_value.fbe_size + self._model_value.fbe_extra
+
1543 self._model_value.fbe_shift(self._model_key.fbe_size + self._model_value.fbe_size)
+
1544 return fbe_result
+
1545
+
1546 # Get the map offset
+
1547 @property
+
1548 def offset(self):
+
1549 if (self._buffer.offset + self.fbe_offset + self.fbe_size) > self._buffer.size:
+
1550 return 0
+
1551
+
1552 fbe_map_offset = self.read_uint32(self.fbe_offset)
+
1553 return fbe_map_offset
+
1554
+
1555 # Get the map size
+
1556 @property
+
1557 def size(self):
+
1558 if (self._buffer.offset + self.fbe_offset + self.fbe_size) > self._buffer.size:
+
1559 return 0
+
1560
+
1561 fbe_map_offset = self.read_uint32(self.fbe_offset)
+
1562 if (fbe_map_offset == 0) or ((self._buffer.offset + fbe_map_offset + 4) > self._buffer.size):
+
1563 return 0
+
1564
+
1565 fbe_map_size = self.read_uint32(fbe_map_offset)
+
1566 return fbe_map_size
+
1567
+
1568 # Map index operator
+
1569 def __getitem__(self, index):
+
1570 assert ((self._buffer.offset + self.fbe_offset + self.fbe_size) <= self._buffer.size), "Model is broken!"
+
1571
+
1572 fbe_map_offset = self.read_uint32(self.fbe_offset)
+
1573 assert ((fbe_map_offset > 0) and ((self._buffer.offset + fbe_map_offset + 4) <= self._buffer.size)), "Model is broken!"
+
1574
+
1575 fbe_map_size = self.read_uint32(fbe_map_offset)
+
1576 assert (index < fbe_map_size), "Index is out of bounds!"
+
1577 if index >= fbe_map_size:
+
1578 raise IndexError("Index is out of bounds!")
+
1579
+
1580 self._model_key.fbe_offset = fbe_map_offset + 4
+
1581 self._model_value.fbe_offset = fbe_map_offset + 4 + self._model_key.fbe_size
+
1582 self._model_key.fbe_shift(index * (self._model_key.fbe_size + self._model_value.fbe_size))
+
1583 self._model_value.fbe_shift(index * (self._model_key.fbe_size + self._model_value.fbe_size))
+
1584 return self._model_key, self._model_value
+
1585
+
1586 # Resize the map and get its first model
+
1587 def resize(self, size):
+
1588 fbe_map_size = size * (self._model_key.fbe_size + self._model_value.fbe_size)
+
1589 fbe_map_offset = self._buffer.allocate(4 + fbe_map_size) - self._buffer.offset
+
1590 assert ((fbe_map_offset > 0) and ((self._buffer.offset + fbe_map_offset + 4) <= self._buffer.size)), "Model is broken!"
+
1591
+
1592 self.write_uint32(self.fbe_offset, fbe_map_offset)
+
1593 self.write_uint32(fbe_map_offset, size)
+
1594 self.write_count(fbe_map_offset + 4, 0, fbe_map_size)
+
1595
+
1596 self._model_key.fbe_offset = fbe_map_offset + 4
+
1597 self._model_value.fbe_offset = fbe_map_offset + 4 + self._model_key.fbe_size
+
1598 return self._model_key, self._model_value
+
1599
+
1600 # Check if the map is valid
+
1601 def verify(self):
+
1602 if (self._buffer.offset + self.fbe_offset + self.fbe_size) > self._buffer.size:
+
1603 return True
+
1604
+
1605 fbe_map_offset = self.read_uint32(self.fbe_offset)
+
1606 if fbe_map_offset == 0:
+
1607 return True
+
1608
+
1609 if (self._buffer.offset + fbe_map_offset + 4) > self._buffer.size:
+
1610 return False
+
1611
+
1612 fbe_map_size = self.read_uint32(fbe_map_offset)
+
1613
+
1614 self._model_key.fbe_offset = fbe_map_offset + 4
+
1615 self._model_value.fbe_offset = fbe_map_offset + 4 + self._model_key.fbe_size
+
1616 for i in range(fbe_map_size):
+
1617 if not self._model_key.verify():
+
1618 return False
+
1619 self._model_key.fbe_shift(self._model_key.fbe_size + self._model_value.fbe_size)
+
1620 if not self._model_value.verify():
+
1621 return False
+
1622 self._model_value.fbe_shift(self._model_key.fbe_size + self._model_value.fbe_size)
+
1623
+
1624 return True
+
1625
+
1626 # Get the map
+
1627 def get(self, values=None):
+
1628 if values is None:
+
1629 values = dict()
+
1630
+
1631 values.clear()
+
1632
+
1633 fbe_map_size = self.size
+
1634 if fbe_map_size == 0:
+
1635 return values
+
1636
+
1637 (fbe_model_key, fbe_model_value) = self[0]
+
1638 for i in range(fbe_map_size):
+
1639 key = fbe_model_key.get()
+
1640 value = fbe_model_value.get()
+
1641 values[key] = value
+
1642 fbe_model_key.fbe_shift(fbe_model_key.fbe_size + fbe_model_value.fbe_size)
+
1643 fbe_model_value.fbe_shift(fbe_model_key.fbe_size + fbe_model_value.fbe_size)
+
1644
+
1645 return values
+
1646
+
1647 # Set the map
+
1648 def set(self, values):
+
1649 assert (values is not None), "Invalid values parameter!"
+
1650 if values is None:
+
1651 raise ValueError("Invalid values parameter!")
+
1652
+
1653 assert ((self._buffer.offset + self.fbe_offset + self.fbe_size) <= self._buffer.size), "Model is broken!"
+
1654 if (self._buffer.offset + self.fbe_offset + self.fbe_size) > self._buffer.size:
+
1655 return
+
1656
+
1657 (fbe_model_key, fbe_model_value) = self.resize(len(values))
+
1658 for (key, value) in values.items():
+
1659 fbe_model_key.set(key)
+
1660 fbe_model_key.fbe_shift(fbe_model_key.fbe_size + fbe_model_value.fbe_size)
+
1661 fbe_model_value.set(value)
+
1662 fbe_model_value.fbe_shift(fbe_model_key.fbe_size + fbe_model_value.fbe_size)
+
1663)CODE";
+
1664
+
1665 // Prepare code template
+
1666 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
1667
+
1668 Write(code);
+
1669}
+
1670
+
1671void GeneratorPython::GenerateFBEFinalModel()
+
1672{
+
1673 std::string code = R"CODE(
+
1674
+
1675# Fast Binary Encoding final model
+
1676class FinalModel(FieldModelBase):
+
1677 def __init__(self, buffer, offset):
+
1678 super().__init__(buffer, offset)
+
1679
+
1680 # Check if the value is valid
+
1681 def verify(self):
+
1682 raise NotImplementedError("verify() method not implemented!")
+
1683)CODE";
+
1684
+
1685 // Prepare code template
+
1686 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
1687
+
1688 Write(code);
+
1689}
+
1690
+
1691void GeneratorPython::GenerateFBEFinalModel(const std::string& name, const std::string& type, const std::string& size, const std::string& defaults)
+
1692{
+
1693 std::string code = R"CODE(
+
1694
+
1695# Fast Binary Encoding _TYPE_ final model
+
1696class FinalModel_NAME_(FinalModel):
+
1697 def __init__(self, buffer, offset):
+
1698 super().__init__(buffer, offset)
+
1699
+
1700 # Get the allocation size
+
1701 # noinspection PyUnusedLocal
+
1702 def fbe_allocation_size(self, value):
+
1703 return self.fbe_size
+
1704
+
1705 # Get the final size
+
1706 @property
+
1707 def fbe_size(self):
+
1708 return _SIZE_
+
1709
+
1710 # Check if the value is valid
+
1711 def verify(self):
+
1712 if (self._buffer.offset + self.fbe_offset + self.fbe_size) > self._buffer.size:
+
1713 return sys.maxsize
+
1714
+
1715 return self.fbe_size
+
1716
+
1717 # Get the value
+
1718 def get(self):
+
1719 if (self._buffer.offset + self.fbe_offset + self.fbe_size) > self._buffer.size:
+
1720 return _DEFAULTS_, 0
+
1721
+
1722 return self.read__TYPE_(self.fbe_offset), self.fbe_size
+
1723
+
1724 # Set the value
+
1725 def set(self, value):
+
1726 assert ((self._buffer.offset + self.fbe_offset + self.fbe_size) <= self._buffer.size), "Model is broken!"
+
1727 if (self._buffer.offset + self.fbe_offset + self.fbe_size) > self._buffer.size:
+
1728 return 0
+
1729
+
1730 self.write__TYPE_(self.fbe_offset, value)
+
1731 return self.fbe_size
+
1732)CODE";
+
1733
+
1734 // Prepare code template
+
1735 code = std::regex_replace(code, std::regex("_NAME_"), name);
+
1736 code = std::regex_replace(code, std::regex("_TYPE_"), type);
+
1737 code = std::regex_replace(code, std::regex("_SIZE_"), size);
+
1738 code = std::regex_replace(code, std::regex("_DEFAULTS_"), defaults);
+
1739 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
1740
+
1741 Write(code);
+
1742}
+
1743
+
1744void GeneratorPython::GenerateFBEFinalModelDecimal()
+
1745{
+
1746 std::string code = R"CODE(
+
1747
+
1748# Fast Binary Encoding decimal final model
+
1749class FinalModelDecimal(FieldModel):
+
1750 def __init__(self, buffer, offset):
+
1751 super().__init__(buffer, offset)
+
1752
+
1753 # Get the allocation size
+
1754 # noinspection PyUnusedLocal
+
1755 def fbe_allocation_size(self, value):
+
1756 return self.fbe_size
+
1757
+
1758 # Get the final size
+
1759 @property
+
1760 def fbe_size(self):
+
1761 return 16
+
1762
+
1763 # Check if the decimal value is valid
+
1764 def verify(self):
+
1765 if (self._buffer.offset + self.fbe_offset + self.fbe_size) > self._buffer.size:
+
1766 return sys.maxsize
+
1767
+
1768 return self.fbe_size
+
1769
+
1770 # Get the decimal value
+
1771 def get(self):
+
1772 if (self._buffer.offset + self.fbe_offset + self.fbe_size) > self._buffer.size:
+
1773 return decimal.Decimal(0), 0
+
1774
+
1775 # Read decimal parts
+
1776 low = self.read_uint32(self.fbe_offset)
+
1777 mid = self.read_uint32(self.fbe_offset + 4)
+
1778 high = self.read_uint32(self.fbe_offset + 8)
+
1779 flags = self.read_uint32(self.fbe_offset + 12)
+
1780
+
1781 # Calculate decimal value
+
1782 negative = (flags & 0x80000000) != 0
+
1783 scale = (flags & 0x7FFFFFFF) >> 16
+
1784 result = decimal.Decimal(high) * 18446744073709551616
+
1785 result += decimal.Decimal(mid) * 4294967296
+
1786 result += decimal.Decimal(low)
+
1787 result /= pow(10, scale)
+
1788 if negative:
+
1789 result = -result
+
1790
+
1791 return result, self.fbe_size
+
1792
+
1793 # Set the decimal value
+
1794 def set(self, value):
+
1795 assert ((self._buffer.offset + self.fbe_offset + self.fbe_size) <= self._buffer.size), "Model is broken!"
+
1796 if (self._buffer.offset + self.fbe_offset + self.fbe_size) > self._buffer.size:
+
1797 return 0
+
1798
+
1799 # Extract decimal parts
+
1800 parts = value.as_tuple()
+
1801 negative = True if parts.sign == 1 else False
+
1802 number = int(''.join(map(str, parts.digits)))
+
1803 scale = -parts.exponent
+
1804
+
1805 # Check for decimal number overflow
+
1806 if (number.bit_length() < 0) or (number.bit_length() > 96):
+
1807 # Value too big for .NET Decimal (bit length is limited to [0, 96])
+
1808 self.write_count(self.fbe_offset, 0, self.fbe_size)
+
1809 return self.fbe_size
+
1810
+
1811 # Check for decimal scale overflow
+
1812 if (scale < 0) or (scale > 28):
+
1813 # Value scale exceeds .NET Decimal limit of [0, 28]
+
1814 self.write_count(self.fbe_offset, 0, self.fbe_size)
+
1815 return self.fbe_size
+
1816
+
1817 # Write unscaled value to bytes 0-11
+
1818 self.write_bytes(self.fbe_offset, number.to_bytes(12, "little"))
+
1819
+
1820 # Write scale at byte 14
+
1821 self.write_byte(self.fbe_offset + 14, scale)
+
1822
+
1823 # Write signum at byte 15
+
1824 self.write_byte(self.fbe_offset + 15, 0x80 if negative else 0)
+
1825 return self.fbe_size
+
1826)CODE";
+
1827
+
1828 // Prepare code template
+
1829 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
1830
+
1831 Write(code);
+
1832}
+
1833
+
1834void GeneratorPython::GenerateFBEFinalModelBytes()
+
1835{
+
1836 std::string code = R"CODE(
+
1837
+
1838# Fast Binary Encoding bytes final model
+
1839class FinalModelBytes(FinalModel):
+
1840 def __init__(self, buffer, offset):
+
1841 super().__init__(buffer, offset)
+
1842
+
1843 # Get the allocation size
+
1844 # noinspection PyMethodMayBeStatic
+
1845 def fbe_allocation_size(self, value):
+
1846 return 4 + len(value)
+
1847
+
1848 # Check if the bytes value is valid
+
1849 def verify(self):
+
1850 if (self._buffer.offset + self.fbe_offset + 4) > self._buffer.size:
+
1851 return sys.maxsize
+
1852
+
1853 fbe_bytes_size = self.read_uint32(self.fbe_offset)
+
1854 if (self._buffer.offset + self.fbe_offset + 4 + fbe_bytes_size) > self._buffer.size:
+
1855 return sys.maxsize
+
1856
+
1857 return 4 + fbe_bytes_size
+
1858
+
1859 # Get the bytes value
+
1860 def get(self):
+
1861 if (self._buffer.offset + self.fbe_offset + 4) > self._buffer.size:
+
1862 return bytearray(), 0
+
1863
+
1864 fbe_bytes_size = self.read_uint32(self.fbe_offset)
+
1865 assert ((self._buffer.offset + self.fbe_offset + 4 + fbe_bytes_size) <= self._buffer.size), "Model is broken!"
+
1866 if (self._buffer.offset + self.fbe_offset + 4 + fbe_bytes_size) > self._buffer.size:
+
1867 return bytearray(), 4
+
1868
+
1869 return self.read_bytes(self.fbe_offset + 4, fbe_bytes_size), (4 + fbe_bytes_size)
+
1870
+
1871 # Set the bytes value
+
1872 def set(self, value):
+
1873 assert (value is not None), "Invalid bytes value!"
+
1874 if value is None:
+
1875 raise ValueError("Invalid bytes value!")
+
1876
+
1877 assert ((self._buffer.offset + self.fbe_offset + 4) <= self._buffer.size), "Model is broken!"
+
1878 if (self._buffer.offset + self.fbe_offset + 4) > self._buffer.size:
+
1879 return 0
+
1880
+
1881 fbe_bytes_size = len(value)
+
1882 assert ((self._buffer.offset + self.fbe_offset + 4 + fbe_bytes_size) <= self._buffer.size), "Model is broken!"
+
1883 if (self._buffer.offset + self.fbe_offset + 4 + fbe_bytes_size) > self._buffer.size:
+
1884 return 4
+
1885
+
1886 self.write_uint32(self.fbe_offset, fbe_bytes_size)
+
1887 self.write_bytes(self.fbe_offset + 4, value)
+
1888 return 4 + fbe_bytes_size
+
1889)CODE";
+
1890
+
1891 // Prepare code template
+
1892 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
1893
+
1894 Write(code);
+
1895}
+
1896
+
1897void GeneratorPython::GenerateFBEFinalModelString()
+
1898{
+
1899 std::string code = R"CODE(
+
1900
+
1901# Fast Binary Encoding string final model
+
1902class FinalModelString(FinalModel):
+
1903 def __init__(self, buffer, offset):
+
1904 super().__init__(buffer, offset)
+
1905
+
1906 # Get the allocation size
+
1907 # noinspection PyMethodMayBeStatic
+
1908 def fbe_allocation_size(self, value):
+
1909 return 4 + 3 * (len(value) + 1)
+
1910
+
1911 # Check if the string value is valid
+
1912 def verify(self):
+
1913 if (self._buffer.offset + self.fbe_offset + 4) > self._buffer.size:
+
1914 return sys.maxsize
+
1915
+
1916 fbe_string_size = self.read_uint32(self.fbe_offset)
+
1917 if (self._buffer.offset + self.fbe_offset + 4 + fbe_string_size) > self._buffer.size:
+
1918 return sys.maxsize
+
1919
+
1920 return 4 + fbe_string_size
+
1921
+
1922 # Get the string value
+
1923 def get(self):
+
1924 if (self._buffer.offset + self.fbe_offset + 4) > self._buffer.size:
+
1925 return '', 0
+
1926
+
1927 fbe_string_size = self.read_uint32(self.fbe_offset)
+
1928 assert ((self._buffer.offset + self.fbe_offset + 4 + fbe_string_size) <= self._buffer.size), "Model is broken!"
+
1929 if (self._buffer.offset + self.fbe_offset + 4 + fbe_string_size) > self._buffer.size:
+
1930 return '', 4
+
1931
+
1932 data = self.read_bytes(self.fbe_offset + 4, fbe_string_size)
+
1933 return data.decode("utf-8"), (4 + fbe_string_size)
+
1934
+
1935 # Set the string value
+
1936 def set(self, value):
+
1937 assert (value is not None), "Invalid string value!"
+
1938 if value is None:
+
1939 raise ValueError("Invalid string value!")
+
1940
+
1941 assert ((self._buffer.offset + self.fbe_offset + 4) <= self._buffer.size), "Model is broken!"
+
1942 if (self._buffer.offset + self.fbe_offset + 4) > self._buffer.size:
+
1943 return 0
+
1944
+
1945 data = value.encode("utf-8")
+
1946
+
1947 fbe_string_size = len(data)
+
1948 assert ((self._buffer.offset + self.fbe_offset + 4 + fbe_string_size) <= self._buffer.size), "Model is broken!"
+
1949 if (self._buffer.offset + self.fbe_offset + 4 + fbe_string_size) > self._buffer.size:
+
1950 return 4
+
1951
+
1952 self.write_uint32(self.fbe_offset, fbe_string_size)
+
1953 self.write_bytes(self.fbe_offset + 4, data)
+
1954 return 4 + fbe_string_size
+
1955)CODE";
+
1956
+
1957 // Prepare code template
+
1958 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
1959
+
1960 Write(code);
+
1961}
+
1962
+
1963void GeneratorPython::GenerateFBEFinalModelOptional()
+
1964{
+
1965 std::string code = R"CODE(
+
1966
+
1967# Fast Binary Encoding optional final model
+
1968class FinalModelOptional(FinalModel):
+
1969 __slots__ = "_model",
+
1970
+
1971 def __init__(self, model, buffer, offset):
+
1972 super().__init__(buffer, offset)
+
1973 self._model = model
+
1974 self._model.fbe_offset = 0
+
1975
+
1976 # Get the allocation size
+
1977 # noinspection PyMethodMayBeStatic
+
1978 def fbe_allocation_size(self, optional):
+
1979 return 1 + (self.value.fbe_allocation_size(optional) if optional else 0)
+
1980
+
1981 # Checks if the object contains a value
+
1982 def __bool__(self):
+
1983 return self.has_value()
+
1984
+
1985 # Checks if the object contains a value
+
1986 @property
+
1987 def has_value(self):
+
1988 if (self._buffer.offset + self.fbe_offset + 1) > self._buffer.size:
+
1989 return False
+
1990
+
1991 fbe_has_value = self.read_uint8(self.fbe_offset)
+
1992 return fbe_has_value != 0
+
1993
+
1994 # Get the base final model value
+
1995 @property
+
1996 def value(self):
+
1997 return self._model
+
1998
+
1999 # Check if the optional value is valid
+
2000 def verify(self):
+
2001 if (self._buffer.offset + self.fbe_offset + 1) > self._buffer.size:
+
2002 return sys.maxsize
+
2003
+
2004 fbe_has_value = self.read_uint8(self.fbe_offset)
+
2005 if fbe_has_value == 0:
+
2006 return 1
+
2007
+
2008 self._buffer.shift(self.fbe_offset + 1)
+
2009 fbe_result = self.value.verify()
+
2010 self._buffer.unshift(self.fbe_offset + 1)
+
2011 return 1 + fbe_result
+
2012
+
2013 # Get the optional value
+
2014 def get(self):
+
2015 if (self._buffer.offset + self.fbe_offset + 1) > self._buffer.size:
+
2016 return None, 0
+
2017
+
2018 if not self.has_value:
+
2019 return None, 1
+
2020
+
2021 self._buffer.shift(self.fbe_offset + 1)
+
2022 optional = self.value.get()
+
2023 self._buffer.unshift(self.fbe_offset + 1)
+
2024 return optional[0], (1 + optional[1])
+
2025
+
2026 # Set the optional value
+
2027 def set(self, optional):
+
2028 assert ((self._buffer.offset + self.fbe_offset + 1) <= self._buffer.size), "Model is broken!"
+
2029 if (self._buffer.offset + self.fbe_offset + 1) > self._buffer.size:
+
2030 return 0
+
2031
+
2032 fbe_has_value = 1 if optional else 0
+
2033 self.write_uint8(self.fbe_offset, fbe_has_value)
+
2034 if fbe_has_value == 0:
+
2035 return 1
+
2036
+
2037 self._buffer.shift(self.fbe_offset + 1)
+
2038 size = self.value.set(optional)
+
2039 self._buffer.unshift(self.fbe_offset + 1)
+
2040 return 1 + size
+
2041)CODE";
+
2042
+
2043 // Prepare code template
+
2044 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2045
+
2046 Write(code);
+
2047}
+
2048
+
2049void GeneratorPython::GenerateFBEFinalModelArray()
+
2050{
+
2051 std::string code = R"CODE(
+
2052
+
2053# Fast Binary Encoding array final model
+
2054class FinalModelArray(FinalModel):
+
2055 __slots__ = "_model", "_size",
+
2056
+
2057 def __init__(self, model, buffer, offset, size):
+
2058 super().__init__(buffer, offset)
+
2059 self._model = model
+
2060 self._size = size
+
2061
+
2062 # Get the allocation size
+
2063 # noinspection PyMethodMayBeStatic
+
2064 def fbe_allocation_size(self, values):
+
2065 size = 0
+
2066 for i in range(min(len(values), self._size)):
+
2067 size += self._model.fbe_allocation_size(values[i])
+
2068 return size
+
2069
+
2070 # Check if the array is valid
+
2071 def verify(self):
+
2072 if (self._buffer.offset + self.fbe_offset) > self._buffer.size:
+
2073 return sys.maxsize
+
2074
+
2075 size = 0
+
2076 self._model.fbe_offset = self.fbe_offset
+
2077 for i in range(self._size):
+
2078 offset = self._model.verify()
+
2079 if offset == sys.maxsize:
+
2080 return sys.maxsize
+
2081 self._model.fbe_shift(offset)
+
2082 size += offset
+
2083 return size
+
2084
+
2085 # Get the array
+
2086 def get(self, values=None):
+
2087 if values is None:
+
2088 values = list()
+
2089
+
2090 values.clear()
+
2091
+
2092 assert ((self._buffer.offset + self.fbe_offset) <= self._buffer.size), "Model is broken!"
+
2093 if (self._buffer.offset + self.fbe_offset) > self._buffer.size:
+
2094 return values, 0
+
2095
+
2096 size = 0
+
2097 self._model.fbe_offset = self.fbe_offset
+
2098 for i in range(self._size):
+
2099 value = self._model.get()
+
2100 values.append(value[0])
+
2101 self._model.fbe_shift(value[1])
+
2102 size += value[1]
+
2103 return values, size
+
2104
+
2105 # Set the array
+
2106 def set(self, values):
+
2107 assert (values is not None), "Invalid values parameter!"
+
2108 if values is None:
+
2109 raise ValueError("Invalid values parameter!")
+
2110
+
2111 assert ((self._buffer.offset + self.fbe_offset) <= self._buffer.size), "Model is broken!"
+
2112 if (self._buffer.offset + self.fbe_offset) > self._buffer.size:
+
2113 return 0
+
2114
+
2115 size = 0
+
2116 self._model.fbe_offset = self.fbe_offset
+
2117 for i in range(min(len(values), self._size)):
+
2118 offset = self._model.set(values[i])
+
2119 self._model.fbe_shift(offset)
+
2120 size += offset
+
2121 return size
+
2122)CODE";
+
2123
+
2124 // Prepare code template
+
2125 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2126
+
2127 Write(code);
+
2128}
+
2129
+
2130void GeneratorPython::GenerateFBEFinalModelVector()
+
2131{
+
2132 std::string code = R"CODE(
+
2133
+
2134# Fast Binary Encoding vector final model
+
2135class FinalModelVector(FinalModel):
+
2136 __slots__ = "_model",
+
2137
+
2138 def __init__(self, model, buffer, offset):
+
2139 super().__init__(buffer, offset)
+
2140 self._model = model
+
2141
+
2142 # Get the allocation size
+
2143 # noinspection PyMethodMayBeStatic
+
2144 def fbe_allocation_size(self, values):
+
2145 size = 4
+
2146 for value in values:
+
2147 size += self._model.fbe_allocation_size(value)
+
2148 return size
+
2149
+
2150 # Check if the vector is valid
+
2151 def verify(self):
+
2152 if (self._buffer.offset + self.fbe_offset + 4) > self._buffer.size:
+
2153 return sys.maxsize
+
2154
+
2155 fbe_vector_size = self.read_uint32(self.fbe_offset)
+
2156
+
2157 size = 4
+
2158 self._model.fbe_offset = self.fbe_offset + 4
+
2159 for i in range(fbe_vector_size):
+
2160 offset = self._model.verify()
+
2161 if offset == sys.maxsize:
+
2162 return sys.maxsize
+
2163 self._model.fbe_shift(offset)
+
2164 size += offset
+
2165 return size
+
2166
+
2167 # Get the vector
+
2168 def get(self, values=None):
+
2169 if values is None:
+
2170 values = list()
+
2171
+
2172 values.clear()
+
2173
+
2174 assert ((self._buffer.offset + self.fbe_offset + 4) <= self._buffer.size), "Model is broken!"
+
2175 if (self._buffer.offset + self.fbe_offset + 4) > self._buffer.size:
+
2176 return values, 0
+
2177
+
2178 fbe_vector_size = self.read_uint32(self.fbe_offset)
+
2179 if fbe_vector_size == 0:
+
2180 return values, 4
+
2181
+
2182 size = 4
+
2183 self._model.fbe_offset = self.fbe_offset + 4
+
2184 for i in range(fbe_vector_size):
+
2185 value = self._model.get()
+
2186 values.append(value[0])
+
2187 self._model.fbe_shift(value[1])
+
2188 size += value[1]
+
2189 return values, size
+
2190
+
2191 # Set the vector
+
2192 def set(self, values):
+
2193 assert (values is not None), "Invalid values parameter!"
+
2194 if values is None:
+
2195 raise ValueError("Invalid values parameter!")
+
2196
+
2197 assert ((self._buffer.offset + self.fbe_offset + 4) <= self._buffer.size), "Model is broken!"
+
2198 if (self._buffer.offset + self.fbe_offset + 4) > self._buffer.size:
+
2199 return 0
+
2200
+
2201 self.write_uint32(self.fbe_offset, len(values))
+
2202
+
2203 size = 4
+
2204 self._model.fbe_offset = self.fbe_offset + 4
+
2205 for value in values:
+
2206 offset = self._model.set(value)
+
2207 self._model.fbe_shift(offset)
+
2208 size += offset
+
2209 return size
+
2210)CODE";
+
2211
+
2212 // Prepare code template
+
2213 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2214
+
2215 Write(code);
+
2216}
+
2217
+
2218void GeneratorPython::GenerateFBEFinalModelSet()
+
2219{
+
2220 std::string code = R"CODE(
+
2221
+
2222# Fast Binary Encoding set final model
+
2223class FinalModelSet(FinalModel):
+
2224 __slots__ = "_model",
+
2225
+
2226 def __init__(self, model, buffer, offset):
+
2227 super().__init__(buffer, offset)
+
2228 self._model = model
+
2229
+
2230 # Get the allocation size
+
2231 # noinspection PyMethodMayBeStatic
+
2232 def fbe_allocation_size(self, values):
+
2233 size = 4
+
2234 for value in values:
+
2235 size += self._model.fbe_allocation_size(value)
+
2236 return size
+
2237
+
2238 # Check if the set value is valid
+
2239 def verify(self):
+
2240 if (self._buffer.offset + self.fbe_offset + 4) > self._buffer.size:
+
2241 return sys.maxsize
+
2242
+
2243 fbe_set_size = self.read_uint32(self.fbe_offset)
+
2244
+
2245 size = 4
+
2246 self._model.fbe_offset = self.fbe_offset + 4
+
2247 for i in range(fbe_set_size):
+
2248 offset = self._model.verify()
+
2249 if offset == sys.maxsize:
+
2250 return sys.maxsize
+
2251 self._model.fbe_shift(offset)
+
2252 size += offset
+
2253 return size
+
2254
+
2255 # Get the set value
+
2256 def get(self, values=None):
+
2257 if values is None:
+
2258 values = set()
+
2259
+
2260 values.clear()
+
2261
+
2262 assert ((self._buffer.offset + self.fbe_offset + 4) <= self._buffer.size), "Model is broken!"
+
2263 if (self._buffer.offset + self.fbe_offset + 4) > self._buffer.size:
+
2264 return values, 0
+
2265
+
2266 fbe_set_size = self.read_uint32(self.fbe_offset)
+
2267 if fbe_set_size == 0:
+
2268 return values, 4
+
2269
+
2270 size = 4
+
2271 self._model.fbe_offset = self.fbe_offset + 4
+
2272 for i in range(fbe_set_size):
+
2273 value = self._model.get()
+
2274 values.add(value[0])
+
2275 self._model.fbe_shift(value[1])
+
2276 size += value[1]
+
2277 return values, size
+
2278
+
2279 # Set the set value
+
2280 def set(self, values):
+
2281 assert (values is not None), "Invalid values parameter!"
+
2282 if values is None:
+
2283 raise ValueError("Invalid values parameter!")
+
2284
+
2285 assert ((self._buffer.offset + self.fbe_offset + 4) <= self._buffer.size), "Model is broken!"
+
2286 if (self._buffer.offset + self.fbe_offset + 4) > self._buffer.size:
+
2287 return 0
+
2288
+
2289 self.write_uint32(self.fbe_offset, len(values))
+
2290
+
2291 size = 4
+
2292 self._model.fbe_offset = self.fbe_offset + 4
+
2293 for value in values:
+
2294 offset = self._model.set(value)
+
2295 self._model.fbe_shift(offset)
+
2296 size += offset
+
2297 return size
+
2298)CODE";
+
2299
+
2300 // Prepare code template
+
2301 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2302
+
2303 Write(code);
+
2304}
+
2305
+
2306void GeneratorPython::GenerateFBEFinalModelMap()
+
2307{
+
2308 std::string code = R"CODE(
+
2309
+
2310# Fast Binary Encoding map final model
+
2311class FinalModelMap(FinalModel):
+
2312 __slots__ = "_model_key", "_model_value",
+
2313
+
2314 def __init__(self, model_key, model_value, buffer, offset):
+
2315 super().__init__(buffer, offset)
+
2316 self._model_key = model_key
+
2317 self._model_value = model_value
+
2318
+
2319 # Get the allocation size
+
2320 # noinspection PyMethodMayBeStatic
+
2321 def fbe_allocation_size(self, values):
+
2322 size = 4
+
2323 for (key, value) in values.items():
+
2324 size += self._model_key.fbe_allocation_size(key)
+
2325 size += self._model_value.fbe_allocation_size(value)
+
2326 return size
+
2327
+
2328 # Check if the map is valid
+
2329 def verify(self):
+
2330 if (self._buffer.offset + self.fbe_offset + 4) > self._buffer.size:
+
2331 return sys.maxsize
+
2332
+
2333 fbe_map_size = self.read_uint32(self.fbe_offset)
+
2334
+
2335 size = 4
+
2336 self._model_key.fbe_offset = self.fbe_offset + 4
+
2337 self._model_value.fbe_offset = self.fbe_offset + 4
+
2338 for i in range(fbe_map_size):
+
2339 offset_key = self._model_key.verify()
+
2340 if offset_key == sys.maxsize:
+
2341 return sys.maxsize
+
2342 self._model_key.fbe_shift(offset_key)
+
2343 self._model_value.fbe_shift(offset_key)
+
2344 size += offset_key
+
2345 offset_value = self._model_value.verify()
+
2346 if offset_value == sys.maxsize:
+
2347 return sys.maxsize
+
2348 self._model_key.fbe_shift(offset_value)
+
2349 self._model_value.fbe_shift(offset_value)
+
2350 size += offset_value
+
2351 return size
+
2352
+
2353 # Get the map
+
2354 def get(self, values=None):
+
2355 if values is None:
+
2356 values = dict()
+
2357
+
2358 values.clear()
+
2359
+
2360 assert ((self._buffer.offset + self.fbe_offset + 4) <= self._buffer.size), "Model is broken!"
+
2361 if (self._buffer.offset + self.fbe_offset + 4) > self._buffer.size:
+
2362 return values, 0
+
2363
+
2364 fbe_map_size = self.read_uint32(self.fbe_offset)
+
2365 if fbe_map_size == 0:
+
2366 return values, 4
+
2367
+
2368 size = 4
+
2369 self._model_key.fbe_offset = self.fbe_offset + 4
+
2370 self._model_value.fbe_offset = self.fbe_offset + 4
+
2371 for i in range(fbe_map_size):
+
2372 key = self._model_key.get()
+
2373 self._model_key.fbe_shift(key[1])
+
2374 self._model_value.fbe_shift(key[1])
+
2375 size += key[1]
+
2376 value = self._model_value.get()
+
2377 self._model_key.fbe_shift(value[1])
+
2378 self._model_value.fbe_shift(value[1])
+
2379 size += value[1]
+
2380 values[key[0]] = value[0]
+
2381 return values, size
+
2382
+
2383 # Set the map
+
2384 def set(self, values):
+
2385 assert (values is not None), "Invalid values parameter!"
+
2386 if values is None:
+
2387 raise ValueError("Invalid values parameter!")
+
2388
+
2389 assert ((self._buffer.offset + self.fbe_offset + 4) <= self._buffer.size), "Model is broken!"
+
2390 if (self._buffer.offset + self.fbe_offset + 4) > self._buffer.size:
+
2391 return 0
+
2392
+
2393 self.write_uint32(self.fbe_offset, len(values))
+
2394
+
2395 size = 4
+
2396 self._model_key.fbe_offset = self.fbe_offset + 4
+
2397 self._model_value.fbe_offset = self.fbe_offset + 4
+
2398 for (key, value) in values.items():
+
2399 offset_key = self._model_key.set(key)
+
2400 self._model_key.fbe_shift(offset_key)
+
2401 self._model_value.fbe_shift(offset_key)
+
2402 size += offset_key
+
2403 offset_value = self._model_value.set(value)
+
2404 self._model_key.fbe_shift(offset_value)
+
2405 self._model_value.fbe_shift(offset_value)
+
2406 size += offset_value
+
2407 return size
+
2408)CODE";
+
2409
+
2410 // Prepare code template
+
2411 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2412
+
2413 Write(code);
+
2414}
+
2415
+
2416void GeneratorPython::GenerateFBESender()
+
2417{
+
2418 std::string code = R"CODE(
+
2419
+
2420# Fast Binary Encoding base sender
+
2421class Sender(object):
+
2422 __slots__ = "_buffer", "_logging", "_final",
+
2423
+
2424 def __init__(self, buffer=None, final=False):
+
2425 if buffer is None:
+
2426 buffer = WriteBuffer()
+
2427 self._buffer = buffer
+
2428 self._logging = False
+
2429 self._final = final
+
2430
+
2431 # Get the bytes buffer
+
2432 @property
+
2433 def buffer(self):
+
2434 return self._buffer
+
2435
+
2436 # Get the final protocol flag
+
2437 @property
+
2438 def final(self):
+
2439 return self._final
+
2440
+
2441 # Get the logging flag
+
2442 @property
+
2443 def logging(self):
+
2444 return self._logging
+
2445
+
2446 # Set the logging flag
+
2447 @logging.setter
+
2448 def logging(self, logging):
+
2449 self._logging = logging
+
2450
+
2451 # Reset the sender buffer
+
2452 def reset(self):
+
2453 self._buffer.reset()
+
2454
+
2455 # Send serialized buffer.
+
2456 # Direct call of the method requires knowledge about internals of FBE models serialization.
+
2457 # Use it with care!
+
2458 def send_serialized(self, serialized):
+
2459 assert (serialized > 0), "Invalid size of the serialized buffer!"
+
2460 if serialized <= 0:
+
2461 return 0
+
2462
+
2463 # Shift the send buffer
+
2464 self._buffer.shift(serialized)
+
2465
+
2466 # Send the value
+
2467 sent = self.on_send(self._buffer.buffer, 0, self._buffer.size)
+
2468 self._buffer.remove(0, sent)
+
2469 return sent
+
2470
+
2471 # Send message handler
+
2472 def on_send(self, buffer, offset, size):
+
2473 raise NotImplementedError("Abstract method call!")
+
2474
+
2475 # Send log message handler
+
2476 def on_send_log(self, message):
+
2477 pass
+
2478)CODE";
+
2479
+
2480 // Prepare code template
+
2481 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2482
+
2483 Write(code);
+
2484}
+
2485
+
2486void GeneratorPython::GenerateFBEReceiver()
+
2487{
+
2488 std::string code = R"CODE(
+
2489
+
2490# Fast Binary Encoding base receiver
+
2491class Receiver(object):
+
2492 __slots__ = "_buffer", "_logging", "_final",
+
2493
+
2494 def __init__(self, buffer=None, final=False):
+
2495 if buffer is None:
+
2496 buffer = WriteBuffer()
+
2497 self._buffer = buffer
+
2498 self._logging = False
+
2499 self._final = final
+
2500
+
2501 # Get the bytes buffer
+
2502 @property
+
2503 def buffer(self):
+
2504 return self._buffer
+
2505
+
2506 # Get the final protocol flag
+
2507 @property
+
2508 def final(self):
+
2509 return self._final
+
2510
+
2511 # Get the logging flag
+
2512 @property
+
2513 def logging(self):
+
2514 return self._logging
+
2515
+
2516 # Set the logging flag
+
2517 @logging.setter
+
2518 def logging(self, logging):
+
2519 self._logging = logging
+
2520
+
2521 # Reset the receiver buffer
+
2522 def reset(self):
+
2523 self._buffer.reset()
+
2524
+
2525 # Receive data
+
2526 def receive(self, buffer, offset=0, size=None):
+
2527 assert (buffer is not None), "Invalid buffer!"
+
2528 if buffer is None:
+
2529 raise ValueError("Invalid buffer!")
+
2530
+
2531 if size is None:
+
2532 size = len(buffer)
+
2533
+
2534 assert ((offset + size) <= len(buffer)), "Invalid offset & size!"
+
2535 if (offset + size) > len(buffer):
+
2536 raise ValueError("Invalid offset & size!")
+
2537
+
2538 if size == 0:
+
2539 return
+
2540
+
2541 if isinstance(buffer, ReadBuffer) or isinstance(buffer, WriteBuffer):
+
2542 buffer = buffer.buffer
+
2543
+
2544 # Storage buffer
+
2545 offset0 = self._buffer.offset
+
2546 offset1 = self._buffer.size
+
2547 size1 = self._buffer.size
+
2548
+
2549 # Receive buffer
+
2550 offset2 = 0
+
2551 size2 = size
+
2552
+
2553 # While receive buffer is available to handle...
+
2554 while offset2 < size2:
+
2555 message_buffer = None
+
2556 message_offset = 0
+
2557 message_size = 0
+
2558
+
2559 # Try to receive message size
+
2560 message_size_copied = False
+
2561 message_size_found = False
+
2562 while not message_size_found:
+
2563 # Look into the storage buffer
+
2564 if offset0 < size1:
+
2565 count = min(size1 - offset0, 4)
+
2566 if count == 4:
+
2567 message_size_copied = True
+
2568 message_size_found = True
+
2569 message_size = Receiver.read_uint32(self._buffer.buffer, self._buffer.offset + offset0)
+
2570 offset0 += 4
+
2571 break
+
2572 else:
+
2573 # Fill remaining data from the receive buffer
+
2574 if offset2 < size2:
+
2575 count = min(size2 - offset2, 4 - count)
+
2576
+
2577 # Allocate and refresh the storage buffer
+
2578 self._buffer.allocate(count)
+
2579 size1 += count
+
2580
+
2581 self._buffer.buffer[offset1:offset1 + count] = buffer[offset + offset2:offset + offset2 + count]
+
2582 offset1 += count
+
2583 offset2 += count
+
2584 continue
+
2585 else:
+
2586 break
+
2587
+
2588 # Look into the receive buffer
+
2589 if offset2 < size2:
+
2590 count = min(size2 - offset2, 4)
+
2591 if count == 4:
+
2592 message_size_found = True
+
2593 message_size = Receiver.read_uint32(buffer, offset + offset2)
+
2594 offset2 += 4
+
2595 break
+
2596 else:
+
2597 # Allocate and refresh the storage buffer
+
2598 self._buffer.allocate(count)
+
2599 size1 += count
+
2600
+
2601 self._buffer.buffer[offset1:offset1 + count] = buffer[offset + offset2:offset + offset2 + count]
+
2602 offset1 += count
+
2603 offset2 += count
+
2604 continue
+
2605 else:
+
2606 break
+
2607
+
2608 if not message_size_found:
+
2609 return
+
2610
+
2611 # Check the message full size
+
2612 min_size = (4 + 4) if self._final else (4 + 4 + 4 + 4)
+
2613 assert (message_size >= min_size), "Invalid receive data!"
+
2614 if message_size < min_size:
+
2615 return
+
2616
+
2617 # Try to receive message body
+
2618 message_found = False
+
2619 while not message_found:
+
2620 # Look into the storage buffer
+
2621 if offset0 < size1:
+
2622 count = min(size1 - offset0, message_size - 4)
+
2623 if count == (message_size - 4):
+
2624 message_found = True
+
2625 message_buffer = self._buffer.buffer
+
2626 message_offset = offset0 - 4
+
2627 offset0 += message_size - 4
+
2628 break
+
2629 else:
+
2630 # Fill remaining data from the receive buffer
+
2631 if offset2 < size2:
+
2632 # Copy message size into the storage buffer
+
2633 if not message_size_copied:
+
2634 # Allocate and refresh the storage buffer
+
2635 self._buffer.allocate(4)
+
2636 size1 += 4
+
2637
+
2638 Receiver.write_uint32(self._buffer.buffer, self._buffer.offset + offset0, message_size)
+
2639 offset0 += 4
+
2640 offset1 += 4
+
2641
+
2642 message_size_copied = True
+
2643
+
2644 count = min(size2 - offset2, message_size - 4 - count)
+
2645
+
2646 # Allocate and refresh the storage buffer
+
2647 self._buffer.allocate(count)
+
2648 size1 += count
+
2649
+
2650 self._buffer.buffer[offset1:offset1 + count] = buffer[offset + offset2:offset + offset2 + count]
+
2651 offset1 += count
+
2652 offset2 += count
+
2653 continue
+
2654 else:
+
2655 break
+
2656
+
2657 # Look into the receive buffer
+
2658 if offset2 < size2:
+
2659 count = min(size2 - offset2, message_size - 4)
+
2660 if not message_size_copied and (count == (message_size - 4)):
+
2661 message_found = True
+
2662 message_buffer = buffer
+
2663 message_offset = offset + offset2 - 4
+
2664 offset2 += message_size - 4
+
2665 break
+
2666 else:
+
2667 # Copy message size into the storage buffer
+
2668 if not message_size_copied:
+
2669 # Allocate and refresh the storage buffer
+
2670 self._buffer.allocate(4)
+
2671 size1 += 4
+
2672
+
2673 Receiver.write_uint32(self._buffer.buffer, self._buffer.offset + offset0, message_size)
+
2674 offset0 += 4
+
2675 offset1 += 4
+
2676
+
2677 message_size_copied = True
+
2678
+
2679 # Allocate and refresh the storage buffer
+
2680 self._buffer.allocate(count)
+
2681 size1 += count
+
2682
+
2683 self._buffer.buffer[offset1:offset1 + count] = buffer[offset + offset2:offset + offset2 + count]
+
2684 offset1 += count
+
2685 offset2 += count
+
2686 continue
+
2687 else:
+
2688 break
+
2689
+
2690 if not message_found:
+
2691 # Copy message size into the storage buffer
+
2692 if not message_size_copied:
+
2693 # Allocate and refresh the storage buffer
+
2694 self._buffer.allocate(4)
+
2695 size1 += 4
+
2696
+
2697 Receiver.write_uint32(self._buffer.buffer, self._buffer.offset + offset0, message_size)
+
2698 offset0 += 4
+
2699 offset1 += 4
+
2700
+
2701 # noinspection PyUnusedLocal
+
2702 message_size_copied = True
+
2703 return
+
2704
+
2705 # Read the message parameters
+
2706 if self._final:
+
2707 # noinspection PyUnusedLocal
+
2708 fbe_struct_size = Receiver.read_uint32(message_buffer, message_offset)
+
2709 fbe_struct_type = Receiver.read_uint32(message_buffer, message_offset + 4)
+
2710 else:
+
2711 fbe_struct_offset = Receiver.read_uint32(message_buffer, message_offset + 4)
+
2712 # noinspection PyUnusedLocal
+
2713 fbe_struct_size = Receiver.read_uint32(message_buffer, message_offset + fbe_struct_offset)
+
2714 fbe_struct_type = Receiver.read_uint32(message_buffer, message_offset + fbe_struct_offset + 4)
+
2715
+
2716 # Handle the message
+
2717 self.on_receive(fbe_struct_type, message_buffer, message_offset, message_size)
+
2718
+
2719 # Reset the storage buffer
+
2720 self._buffer.reset()
+
2721
+
2722 # Refresh the storage buffer
+
2723 offset0 = self._buffer.offset
+
2724 offset1 = self._buffer.size
+
2725 size1 = self._buffer.size
+
2726
+
2727 # Receive message handler
+
2728 def on_receive(self, type, buffer, offset, size):
+
2729 raise NotImplementedError("Abstract method call!")
+
2730
+
2731 # Receive log message handler
+
2732 def on_receive_log(self, message):
+
2733 pass
+
2734
+
2735 # Buffer I/O methods
+
2736
+
2737 @staticmethod
+
2738 def read_uint32(buffer, offset):
+
2739 return struct.unpack_from("<I", buffer, offset)[0]
+
2740
+
2741 @staticmethod
+
2742 def write_uint32(buffer, offset, value):
+
2743 return struct.pack_into("<I", buffer, offset, value)
+
2744)CODE";
+
2745
+
2746 // Prepare code template
+
2747 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2748
+
2749 Write(code);
+
2750}
+
2751
+
2752void GeneratorPython::GenerateImports(const std::shared_ptr<Package>& p)
+
2753{
+
2754 // Generate common import
+
2755 WriteLine();
+
2756 if (JSON())
+
2757 WriteLineIndent("import base64");
+
2758 WriteLineIndent("import decimal");
+
2759 WriteLineIndent("import enum");
+
2760 WriteLineIndent("import functools");
+
2761 if (JSON())
+
2762 WriteLineIndent("import json");
+
2763 WriteLineIndent("import sys");
+
2764 WriteLineIndent("import uuid");
+
2765
+
2766 // Generate FBE import
+
2767 WriteLine();
+
2768 WriteLineIndent("import fbe");
+
2769
+
2770 // Generate packages import
+
2771 if (p->import)
+
2772 for (const auto& import : p->import->imports)
+
2773 WriteLineIndent("from . import " + *import);
+
2774}
+
2775
+
2776void GeneratorPython::GeneratePackage(const std::shared_ptr<Package>& p)
+
2777{
+
2778 CppCommon::Path output = _output;
+
2779
+
2780 // Create package path
+
2781 CppCommon::Directory::CreateTree(output);
+
2782
+
2783 // Generate __init__ file
+
2784 GenerateInit(output);
+
2785
+
2786 // Generate FBE file
+
2787 GenerateFBE(output);
+
2788
+
2789 // Generate the output file
+
2790 output /= *p->name + ".py";
+
2791 WriteBegin();
+
2792
+
2793 // Generate package header
+
2794 GenerateHeader(CppCommon::Path(_input).filename().string());
+
2795 GenerateImports(p);
+
2796
+
2797 // Generate namespace
+
2798 if (p->body)
+
2799 {
+
2800 // Generate child enums
+
2801 for (const auto& child_e : p->body->enums)
+
2802 GenerateEnum(child_e);
+
2803
+
2804 // Generate child flags
+
2805 for (const auto& child_f : p->body->flags)
+
2806 GenerateFlags(child_f);
+
2807
+
2808 // Generate child structs
+
2809 for (const auto& child_s : p->body->structs)
+
2810 GenerateStruct(child_s);
+
2811 }
+
2812
+
2813 // Generate protocol
+
2814 if (Proto())
+
2815 {
+
2816 // Generate protocol version
+
2817 GenerateProtocolVersion(p);
+
2818
+
2819 // Generate sender & receiver
+
2820 GenerateSender(p, false);
+
2821 GenerateReceiver(p, false);
+
2822 GenerateProxy(p, false);
+
2823 if (Final())
+
2824 {
+
2825 GenerateSender(p, true);
+
2826 GenerateReceiver(p, true);
+
2827 }
+
2828 }
+
2829
+
2830 // Generate package footer
+
2831 GenerateFooter();
+
2832
+
2833 // Store the output file
+
2834 WriteEnd();
+
2835 Store(output);
+
2836}
+
2837
+
2838void GeneratorPython::GenerateEnum(const std::shared_ptr<EnumType>& e)
+
2839{
+
2840 // Generate enum begin
+
2841 WriteLine();
+
2842 WriteLine();
+
2843 WriteLineIndent("class " + *e->name + "(enum.IntEnum, metaclass=fbe.DefaultEnumMeta):");
+
2844 Indent(1);
+
2845
+
2846 std::string enum_type = (e->base && !e->base->empty()) ? *e->base : "int32";
+
2847
+
2848 // Generate enum body
+
2849 if (e->body)
+
2850 {
+
2851 int index = 0;
+
2852 std::string last = ConvertEnumConstant("int32", "0");
+
2853 for (const auto& value : e->body->values)
+
2854 {
+
2855 WriteIndent(*value->name + " = ");
+
2856 if (value->value)
+
2857 {
+
2858 if (value->value->constant && !value->value->constant->empty())
+
2859 {
+
2860 index = 0;
+
2861 last = ConvertEnumConstant(enum_type, *value->value->constant);
+
2862 Write(last + " + " + std::to_string(index++));
+
2863 }
+
2864 else if (value->value->reference && !value->value->reference->empty())
+
2865 {
+
2866 index = 0;
+
2867 last = ConvertEnumConstant("", *value->value->reference);
+
2868 Write(last);
+
2869 }
+
2870 }
+
2871 else
+
2872 Write(last + " + " + std::to_string(index++));
+
2873 WriteLine();
+
2874 }
+
2875 WriteLineIndent("unknown = ~0");
+
2876 }
+
2877
+
2878 // Generate enum __slots__
+
2879 WriteLine();
+
2880 WriteLineIndent("__slots__ = ()");
+
2881
+
2882 // Generate enum __format__ method
+
2883 WriteLine();
+
2884 WriteLineIndent("def __format__(self, format_spec):");
+
2885 Indent(1);
+
2886 WriteLineIndent("return self.__str__()");
+
2887 Indent(-1);
+
2888
+
2889 // Generate enum __str__ method
+
2890 WriteLine();
+
2891 WriteLineIndent("def __str__(self):");
+
2892 Indent(1);
+
2893 if (e->body && !e->body->values.empty())
+
2894 {
+
2895 for (auto it = e->body->values.begin(); it != e->body->values.end(); ++it)
+
2896 {
+
2897 WriteLineIndent("if self.value == " + *e->name + "." + *(*it)->name + ":");
+
2898 Indent(1);
+
2899 WriteLineIndent("return \"" + *(*it)->name + "\"");
+
2900 Indent(-1);
+
2901 }
+
2902 WriteLineIndent("return \"<unknown>\"");
+
2903 }
+
2904 else
+
2905 WriteLineIndent("return \"<empty>\"");
+
2906 Indent(-1);
+
2907
+
2908 // Generate enum __format__ method
+
2909 WriteLine();
+
2910 WriteLineIndent("@classmethod");
+
2911 WriteLineIndent("def _missing_(cls, value):");
+
2912 Indent(1);
+
2913 WriteLineIndent("return " + *e->name + ".unknown");
+
2914 Indent(-1);
+
2915
+
2916 if (JSON())
+
2917 {
+
2918 // Generate enum __from_json__ method
+
2919 WriteLine();
+
2920 WriteLineIndent("@staticmethod");
+
2921 WriteLineIndent("def __from_json__(value):");
+
2922 Indent(1);
+
2923 WriteLineIndent("if value is None:");
+
2924 Indent(1);
+
2925 WriteLineIndent("return None");
+
2926 Indent(-1);
+
2927 WriteLineIndent("return " + *e->name + "(value)");
+
2928 Indent(-1);
+
2929 }
+
2930
+
2931 // Generate enum end
+
2932 Indent(-1);
+
2933
+
2934 // Generate enum field model
+
2935 GenerateEnumFieldModel(e);
+
2936
+
2937 // Generate enum final model
+
2938 if (Final())
+
2939 GenerateEnumFinalModel(e);
+
2940}
+
2941
+
2942void GeneratorPython::GenerateEnumFieldModel(const std::shared_ptr<EnumType>& e)
+
2943{
+
2944 std::string code = R"CODE(
+
2945
+
2946# Fast Binary Encoding _ENUM_NAME_ field model
+
2947class FieldModel_ENUM_NAME_(fbe.FieldModel):
+
2948 def __init__(self, buffer, offset):
+
2949 super().__init__(buffer, offset)
+
2950
+
2951 # Get the field size
+
2952 @property
+
2953 def fbe_size(self):
+
2954 return _ENUM_SIZE_
+
2955
+
2956 # Get the value
+
2957 def get(self, defaults=None):
+
2958 if defaults is None:
+
2959 defaults = _ENUM_NAME_()
+
2960
+
2961 if (self._buffer.offset + self.fbe_offset + self.fbe_size) > self._buffer.size:
+
2962 return defaults
+
2963
+
2964 return _ENUM_NAME_(self.read__ENUM_TYPE_(self.fbe_offset))
+
2965
+
2966 # Set the value
+
2967 def set(self, value):
+
2968 assert ((self._buffer.offset + self.fbe_offset + self.fbe_size) <= self._buffer.size), "Model is broken!"
+
2969 if (self._buffer.offset + self.fbe_offset + self.fbe_size) > self._buffer.size:
+
2970 return
+
2971
+
2972 self.write__ENUM_TYPE_(self.fbe_offset, value)
+
2973)CODE";
+
2974
+
2975 std::string enum_type = (e->base && !e->base->empty()) ? *e->base : "int32";
+
2976
+
2977 // Prepare code template
+
2978 code = std::regex_replace(code, std::regex("_ENUM_NAME_"), *e->name);
+
2979 code = std::regex_replace(code, std::regex("_ENUM_TYPE_"), ConvertEnumType(enum_type));
+
2980 code = std::regex_replace(code, std::regex("_ENUM_SIZE_"), ConvertEnumSize(enum_type));
+
2981 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2982
+
2983 Write(code);
+
2984}
+
2985
+
2986void GeneratorPython::GenerateEnumFinalModel(const std::shared_ptr<EnumType>& e)
+
2987{
+
2988 std::string code = R"CODE(
+
2989
+
2990# Fast Binary Encoding _ENUM_NAME_ final model
+
2991class FinalModel_ENUM_NAME_(fbe.FinalModel):
+
2992 def __init__(self, buffer, offset):
+
2993 super().__init__(buffer, offset)
+
2994
+
2995 # Get the allocation size
+
2996 # noinspection PyUnusedLocal
+
2997 def fbe_allocation_size(self, value):
+
2998 return self.fbe_size
+
2999
+
3000 # Get the final size
+
3001 @property
+
3002 def fbe_size(self):
+
3003 return _ENUM_SIZE_
+
3004
+
3005 # Check if the value is valid
+
3006 def verify(self):
+
3007 if (self._buffer.offset + self.fbe_offset + self.fbe_size) > self._buffer.size:
+
3008 return sys.maxsize
+
3009
+
3010 return self.fbe_size
+
3011
+
3012 # Get the value
+
3013 def get(self):
+
3014 if (self._buffer.offset + self.fbe_offset + self.fbe_size) > self._buffer.size:
+
3015 return _ENUM_NAME_(), 0
+
3016
+
3017 return _ENUM_NAME_(self.read__ENUM_TYPE_(self.fbe_offset)), self.fbe_size
+
3018
+
3019 # Set the value
+
3020 def set(self, value):
+
3021 assert ((self._buffer.offset + self.fbe_offset + self.fbe_size) <= self._buffer.size), "Model is broken!"
+
3022 if (self._buffer.offset + self.fbe_offset + self.fbe_size) > self._buffer.size:
+
3023 return 0
+
3024
+
3025 self.write__ENUM_TYPE_(self.fbe_offset, value)
+
3026 return self.fbe_size
+
3027)CODE";
+
3028
+
3029 std::string enum_type = (e->base && !e->base->empty()) ? *e->base : "int32";
+
3030
+
3031 // Prepare code template
+
3032 code = std::regex_replace(code, std::regex("_ENUM_NAME_"), *e->name);
+
3033 code = std::regex_replace(code, std::regex("_ENUM_TYPE_"), ConvertEnumType(enum_type));
+
3034 code = std::regex_replace(code, std::regex("_ENUM_SIZE_"), ConvertEnumSize(enum_type));
+
3035 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
3036
+
3037 Write(code);
+
3038}
+
3039
+
3040void GeneratorPython::GenerateFlags(const std::shared_ptr<FlagsType>& f)
+
3041{
+
3042 // Generate flags begin
+
3043 WriteLine();
+
3044 WriteLine();
+
3045 WriteLineIndent("class " + *f->name + "(enum.IntFlag, metaclass=fbe.DefaultEnumMeta):");
+
3046 Indent(1);
+
3047
+
3048 std::string enum_type = (f->base && !f->base->empty()) ? *f->base : "int32";
+
3049
+
3050 // Generate flags body
+
3051 if (f->body && !f->body->values.empty())
+
3052 {
+
3053 for (const auto& value : f->body->values)
+
3054 {
+
3055 WriteIndent(*value->name + " = ");
+
3056 if (value->value)
+
3057 {
+
3058 if (value->value->constant && !value->value->constant->empty())
+
3059 Write(ConvertEnumConstant(enum_type, *value->value->constant));
+
3060 else if (value->value->reference && !value->value->reference->empty())
+
3061 Write(ConvertEnumConstant("", *value->value->reference));
+
3062 }
+
3063 WriteLine();
+
3064 }
+
3065 WriteLine();
+
3066 }
+
3067
+
3068 // Generate flags __slots__
+
3069 WriteLineIndent("__slots__ = ()");
+
3070
+
3071 // Generate flags has_flags() method
+
3072 WriteLine();
+
3073 WriteLineIndent("# Is flags set?");
+
3074 WriteLineIndent("def has_flags(self, flags):");
+
3075 Indent(1);
+
3076 WriteLineIndent("return ((self.value & flags.value) != 0) and ((self.value & flags.value) == flags.value)");
+
3077 Indent(-1);
+
3078
+
3079 // Generate flags set_flags() method
+
3080 WriteLine();
+
3081 WriteLineIndent("# Set flags");
+
3082 WriteLineIndent("def set_flags(self, flags):");
+
3083 Indent(1);
+
3084 WriteLineIndent("self.value |= flags.value");
+
3085 WriteLineIndent("return self");
+
3086 Indent(-1);
+
3087
+
3088 // Generate flags remove_flags() method
+
3089 WriteLine();
+
3090 WriteLineIndent("# Remove flags");
+
3091 WriteLineIndent("def remove_flags(self, flags):");
+
3092 Indent(1);
+
3093 WriteLineIndent("self.value &= ~flags.value");
+
3094 WriteLineIndent("return self");
+
3095 Indent(-1);
+
3096
+
3097 // Generate flags __format__ method
+
3098 WriteLine();
+
3099 WriteLineIndent("def __format__(self, format_spec):");
+
3100 Indent(1);
+
3101 WriteLineIndent("return self.__str__()");
+
3102 Indent(-1);
+
3103
+
3104 // Generate flags __str__ method
+
3105 WriteLine();
+
3106 WriteLineIndent("def __str__(self):");
+
3107 Indent(1);
+
3108 WriteLineIndent("sb = list()");
+
3109 if (f->body && !f->body->values.empty())
+
3110 {
+
3111 WriteLineIndent("first = True");
+
3112 for (auto it = f->body->values.begin(); it != f->body->values.end(); ++it)
+
3113 {
+
3114 WriteLineIndent("if (self.value & " + *f->name + "." + *(*it)->name + ".value) and ((self.value & " + *f->name + "." + *(*it)->name + ".value) == " + *f->name + "." + *(*it)->name + ".value):");
+
3115 Indent(1);
+
3116 WriteLineIndent("if first:");
+
3117 Indent(1);
+
3118 WriteLineIndent("# noinspection PyUnusedLocal");
+
3119 WriteLineIndent("first = False");
+
3120 Indent(-1);
+
3121 WriteLineIndent("else:");
+
3122 Indent(1);
+
3123 WriteLineIndent("sb.append(\"|\")");
+
3124 Indent(-1);
+
3125 WriteLineIndent("sb.append(\"" + *(*it)->name + "\")");
+
3126 Indent(-1);
+
3127 }
+
3128 }
+
3129 WriteLineIndent("return \"\".join(sb)");
+
3130 Indent(-1);
+
3131
+
3132 if (JSON())
+
3133 {
+
3134 // Generate flags __from_json__ method
+
3135 WriteLine();
+
3136 WriteLineIndent("@staticmethod");
+
3137 WriteLineIndent("def __from_json__(value):");
+
3138 Indent(1);
+
3139 WriteLineIndent("if value is None:");
+
3140 Indent(1);
+
3141 WriteLineIndent("return None");
+
3142 Indent(-1);
+
3143 WriteLineIndent("return " + *f->name + "(value)");
+
3144 Indent(-1);
+
3145 }
+
3146
+
3147 // Generate flags end
+
3148 Indent(-1);
+
3149
+
3150 // Generate flags field model
+
3151 GenerateFlagsFieldModel(f);
+
3152
+
3153 // Generate flags final model
+
3154 if (Final())
+
3155 GenerateFlagsFinalModel(f);
+
3156}
+
3157
+
3158void GeneratorPython::GenerateFlagsFieldModel(const std::shared_ptr<FlagsType>& f)
+
3159{
+
3160 std::string code = R"CODE(
+
3161
+
3162# Fast Binary Encoding _FLAGS_NAME_ field model
+
3163class FieldModel_FLAGS_NAME_(fbe.FieldModel):
+
3164 def __init__(self, buffer, offset):
+
3165 super().__init__(buffer, offset)
+
3166
+
3167 # Get the field size
+
3168 @property
+
3169 def fbe_size(self):
+
3170 return _FLAGS_SIZE_
+
3171
+
3172 # Get the value
+
3173 def get(self, defaults=None):
+
3174 if defaults is None:
+
3175 defaults = _FLAGS_NAME_()
+
3176
+
3177 if (self._buffer.offset + self.fbe_offset + self.fbe_size) > self._buffer.size:
+
3178 return defaults
+
3179
+
3180 return _FLAGS_NAME_(self.read__FLAGS_TYPE_(self.fbe_offset))
+
3181
+
3182 # Set the value
+
3183 def set(self, value):
+
3184 assert ((self._buffer.offset + self.fbe_offset + self.fbe_size) <= self._buffer.size), "Model is broken!"
+
3185 if (self._buffer.offset + self.fbe_offset + self.fbe_size) > self._buffer.size:
+
3186 return
+
3187
+
3188 self.write__FLAGS_TYPE_(self.fbe_offset, value)
+
3189)CODE";
+
3190
+
3191 std::string flags_type = (f->base && !f->base->empty()) ? *f->base : "int32";
+
3192
+
3193 // Prepare code template
+
3194 code = std::regex_replace(code, std::regex("_FLAGS_NAME_"), *f->name);
+
3195 code = std::regex_replace(code, std::regex("_FLAGS_TYPE_"), ConvertEnumType(flags_type));
+
3196 code = std::regex_replace(code, std::regex("_FLAGS_SIZE_"), ConvertEnumSize(flags_type));
+
3197 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
3198
+
3199 Write(code);
+
3200}
+
3201
+
3202void GeneratorPython::GenerateFlagsFinalModel(const std::shared_ptr<FlagsType>& f)
+
3203{
+
3204 std::string code = R"CODE(
+
3205
+
3206# Fast Binary Encoding _FLAGS_NAME_ final model
+
3207class FinalModel_FLAGS_NAME_(fbe.FinalModel):
+
3208 def __init__(self, buffer, offset):
+
3209 super().__init__(buffer, offset)
+
3210
+
3211 # Get the allocation size
+
3212 # noinspection PyUnusedLocal
+
3213 def fbe_allocation_size(self, value):
+
3214 return self.fbe_size
+
3215
+
3216 # Get the final size
+
3217 @property
+
3218 def fbe_size(self):
+
3219 return _FLAGS_SIZE_
+
3220
+
3221 # Check if the value is valid
+
3222 def verify(self):
+
3223 if (self._buffer.offset + self.fbe_offset + self.fbe_size) > self._buffer.size:
+
3224 return sys.maxsize
+
3225
+
3226 return self.fbe_size
+
3227
+
3228 # Get the value
+
3229 def get(self):
+
3230 if (self._buffer.offset + self.fbe_offset + self.fbe_size) > self._buffer.size:
+
3231 return _FLAGS_NAME_(), 0
+
3232
+
3233 return _FLAGS_NAME_(self.read__FLAGS_TYPE_(self.fbe_offset)), self.fbe_size
+
3234
+
3235 # Set the value
+
3236 def set(self, value):
+
3237 assert ((self._buffer.offset + self.fbe_offset + self.fbe_size) <= self._buffer.size), "Model is broken!"
+
3238 if (self._buffer.offset + self.fbe_offset + self.fbe_size) > self._buffer.size:
+
3239 return 0
+
3240
+
3241 self.write__FLAGS_TYPE_(self.fbe_offset, value)
+
3242 return self.fbe_size
+
3243)CODE";
+
3244
+
3245 std::string flags_type = (f->base && !f->base->empty()) ? *f->base : "int32";
+
3246
+
3247 // Prepare code template
+
3248 code = std::regex_replace(code, std::regex("_FLAGS_NAME_"), *f->name);
+
3249 code = std::regex_replace(code, std::regex("_FLAGS_TYPE_"), ConvertEnumType(flags_type));
+
3250 code = std::regex_replace(code, std::regex("_FLAGS_SIZE_"), ConvertEnumSize(flags_type));
+
3251 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
3252
+
3253 Write(code);
+
3254}
+
3255
+
3256void GeneratorPython::GenerateStruct(const std::shared_ptr<StructType>& s)
+
3257{
+
3258 std::string base_type = (s->base && !s->base->empty()) ? ConvertTypeName(*s->base, false) : "object";
+
3259
+
3260 // Generate struct begin
+
3261 WriteLine();
+
3262 WriteLine();
+
3263 WriteLineIndent("@functools.total_ordering");
+
3264 WriteLineIndent("class " + *s->name + "(" + base_type + "):");
+
3265 Indent(1);
+
3266
+
3267 // Generate struct __slots__
+
3268 if (s->body && !s->body->fields.empty())
+
3269 {
+
3270 WriteIndent("__slots__ = ");
+
3271 for (const auto& field : s->body->fields)
+
3272 Write("\"" + *field->name + "\", ");
+
3273 WriteLine();
+
3274 WriteLine();
+
3275 }
+
3276
+
3277 // Generate struct constructor
+
3278 WriteIndent("def __init__(self");
+
3279 if (s->base && !s->base->empty())
+
3280 Write(", parent=None");
+
3281 if (s->body)
+
3282 {
+
3283 for (const auto& field : s->body->fields)
+
3284 {
+
3285 Write(", " + *field->name + "=");
+
3286 if (field->value && ((*field->value == "utc") || (*field->value == "uuid1") || (*field->value == "uuid2")))
+
3287 Write("None");
+
3288 else if (field->value)
+
3289 Write(ConvertConstant(*field->type, *field->value, field->optional));
+
3290 else if (field->array || field->vector || field->list || field->set || field->map || field->hash)
+
3291 Write("None");
+
3292 else
+
3293 Write(ConvertDefaultOrNone(*field->type, field->optional));
+
3294 }
+
3295 }
+
3296 WriteLine("):");
+
3297 Indent(1);
+
3298 if (s->base && !s->base->empty())
+
3299 {
+
3300 WriteLineIndent("super().__init__()");
+
3301 WriteLineIndent("if parent is None:");
+
3302 Indent(1);
+
3303 WriteLineIndent("parent = " + base_type + "()");
+
3304 Indent(-1);
+
3305 WriteLineIndent("super().copy(parent)");
+
3306 }
+
3307 if (s->body)
+
3308 {
+
3309 for (const auto& field : s->body->fields)
+
3310 {
+
3311 if (field->array || field->vector || field->list || field->set || field->map || field->hash || (field->value && ((*field->value == "utc") || (*field->value == "uuid1") || (*field->value == "uuid2"))) || (!field->value && !field->optional && !IsPrimitiveType(*field->type) && (*field->type != "string") && (*field->type != "timestamp")))
+
3312 {
+
3313 WriteLineIndent("if " + *field->name + " is None:");
+
3314 Indent(1);
+
3315 if (field->value)
+
3316 WriteLineIndent(*field->name + " = " + ConvertConstant(*field->type, *field->value, field->optional));
+
3317 else
+
3318 WriteLineIndent(*field->name + " = " + ConvertDefault(*field));
+
3319 Indent(-1);
+
3320 }
+
3321 }
+
3322 for (const auto& field : s->body->fields)
+
3323 WriteLineIndent("self." + *field->name + " = " + *field->name);
+
3324 }
+
3325 Indent(-1);
+
3326 if ((!s->base || s->base->empty()) && (!s->body || s->body->fields.empty()))
+
3327 {
+
3328 Indent(1);
+
3329 WriteLineIndent("pass");
+
3330 Indent(-1);
+
3331 }
+
3332
+
3333 // Generate struct copy() method
+
3334 WriteLine();
+
3335 WriteLineIndent("# Struct shallow copy");
+
3336 WriteLineIndent("def copy(self, other):");
+
3337 Indent(1);
+
3338 if (s->base && !s->base->empty())
+
3339 WriteLineIndent("super().copy(other)");
+
3340 if (s->body)
+
3341 for (const auto& field : s->body->fields)
+
3342 WriteLineIndent("self." + *field->name + " = other." + *field->name);
+
3343 WriteLineIndent("return self");
+
3344 Indent(-1);
+
3345
+
3346 // Generate struct clone() method
+
3347 WriteLine();
+
3348 WriteLineIndent("# Struct deep clone");
+
3349 WriteLineIndent("def clone(self):");
+
3350 Indent(1);
+
3351 WriteLineIndent("# Serialize the struct to the FBE stream");
+
3352 WriteLineIndent("writer = " + *s->name + "Model(fbe.WriteBuffer())");
+
3353 WriteLineIndent("writer.serialize(self)");
+
3354 WriteLine();
+
3355 WriteLineIndent("# Deserialize the struct from the FBE stream");
+
3356 WriteLineIndent("reader = " + *s->name + "Model(fbe.ReadBuffer())");
+
3357 WriteLineIndent("reader.attach_buffer(writer.buffer)");
+
3358 WriteLineIndent("return reader.deserialize()[0]");
+
3359 Indent(-1);
+
3360
+
3361 // Generate struct __eq__ method
+
3362 WriteLine();
+
3363 WriteLineIndent("def __eq__(self, other):");
+
3364 Indent(1);
+
3365 WriteLineIndent("if not isinstance(self, other.__class__):");
+
3366 Indent(1);
+
3367 WriteLineIndent("return NotImplemented");
+
3368 Indent(-1);
+
3369 if (s->base && !s->base->empty())
+
3370 {
+
3371 WriteLineIndent("if not super().__eq__(other):");
+
3372 Indent(1);
+
3373 WriteLineIndent("return False");
+
3374 Indent(-1);
+
3375 }
+
3376 if (s->body)
+
3377 {
+
3378 for (const auto& field : s->body->fields)
+
3379 {
+
3380 if (field->keys)
+
3381 {
+
3382 WriteLineIndent("if not self." + *field->name + " == other." + *field->name + ":");
+
3383 Indent(1);
+
3384 WriteLineIndent("return False");
+
3385 Indent(-1);
+
3386 }
+
3387 }
+
3388 }
+
3389 WriteLineIndent("return True");
+
3390 Indent(-1);
+
3391
+
3392 // Generate struct __lt__ method
+
3393 WriteLine();
+
3394 WriteLineIndent("def __lt__(self, other):");
+
3395 Indent(1);
+
3396 WriteLineIndent("if not isinstance(self, other.__class__):");
+
3397 Indent(1);
+
3398 WriteLineIndent("return NotImplemented");
+
3399 Indent(-1);
+
3400 if (s->base && !s->base->empty())
+
3401 {
+
3402 WriteLineIndent("if super().__lt__(other):");
+
3403 Indent(1);
+
3404 WriteLineIndent("return True");
+
3405 Indent(-1);
+
3406 WriteLineIndent("if super().__eq__(other):");
+
3407 Indent(1);
+
3408 WriteLineIndent("return False");
+
3409 Indent(-1);
+
3410 }
+
3411 if (s->body)
+
3412 {
+
3413 for (const auto& field : s->body->fields)
+
3414 {
+
3415 if (field->keys)
+
3416 {
+
3417 WriteLineIndent("if self." + *field->name + " < other." + *field->name + ":");
+
3418 Indent(1);
+
3419 WriteLineIndent("return True");
+
3420 Indent(-1);
+
3421 WriteLineIndent("if self." + *field->name + " == other." + *field->name + ":");
+
3422 Indent(1);
+
3423 WriteLineIndent("return False");
+
3424 Indent(-1);
+
3425 }
+
3426 }
+
3427 }
+
3428 WriteLineIndent("return False");
+
3429 Indent(-1);
+
3430
+
3431 // Generate struct __key__ property
+
3432 WriteLine();
+
3433 WriteLineIndent("@property");
+
3434 WriteLineIndent("def __key__(self):");
+
3435 Indent(1);
+
3436 WriteIndent("return ");
+
3437 if (s->base && !s->base->empty())
+
3438 Write("super().__key__ + (");
+
3439 bool empty = true;
+
3440 if (s->body)
+
3441 {
+
3442 for (const auto& field : s->body->fields)
+
3443 {
+
3444 if (field->keys)
+
3445 {
+
3446 Write("self." + *field->name + ", ");
+
3447 empty = false;
+
3448 }
+
3449 }
+
3450 }
+
3451 if (s->base && !s->base->empty())
+
3452 Write(")");
+
3453 else if (empty)
+
3454 Write("()");
+
3455 WriteLine();
+
3456 Indent(-1);
+
3457
+
3458 // Generate struct __hash__ method
+
3459 WriteLine();
+
3460 WriteLineIndent("def __hash__(self):");
+
3461 Indent(1);
+
3462 WriteLineIndent("return hash(self.__key__)");
+
3463 Indent(-1);
+
3464
+
3465 // Generate flags __format__ method
+
3466 WriteLine();
+
3467 WriteLineIndent("def __format__(self, format_spec):");
+
3468 Indent(1);
+
3469 WriteLineIndent("return self.__str__()");
+
3470 Indent(-1);
+
3471
+
3472 // Generate struct __str__ method
+
3473 WriteLine();
+
3474 WriteLineIndent("def __str__(self):");
+
3475 Indent(1);
+
3476 WriteLineIndent("sb = list()");
+
3477 WriteLineIndent("sb.append(\"" + *s->name + "(\")");
+
3478 bool first = true;
+
3479 if (s->base && !s->base->empty())
+
3480 {
+
3481 WriteLineIndent("sb.append(" + base_type + ".__str__(self))");
+
3482 first = false;
+
3483 }
+
3484 if (s->body)
+
3485 {
+
3486 for (const auto& field : s->body->fields)
+
3487 {
+
3488 WriteLineIndent("sb.append(\"" + std::string(first ? "" : ",") + *field->name + "=\")");
+
3489 if (field->attributes && field->attributes->hidden)
+
3490 WriteLineIndent("sb.append(\"***\")");
+
3491 else if (field->array || field->vector)
+
3492 {
+
3493 WriteLineIndent("if self." + *field->name + " is not None:");
+
3494 Indent(1);
+
3495 WriteLineIndent("first = True");
+
3496 WriteLineIndent("sb.append(\"[\" + str(len(self." + *field->name + "))" + " + \"][\")");
+
3497 WriteLineIndent("for item in self." + *field->name + ":");
+
3498 Indent(1);
+
3499 WriteOutputStreamValue(*field->type, "item", field->optional, true);
+
3500 WriteLineIndent("first = False");
+
3501 Indent(-1);
+
3502 WriteLineIndent("sb.append(\"]\")");
+
3503 Indent(-1);
+
3504 WriteLineIndent("else:");
+
3505 Indent(1);
+
3506 WriteLineIndent("sb.append(\"[0][]\")");
+
3507 Indent(-1);
+
3508 }
+
3509 else if (field->list)
+
3510 {
+
3511 WriteLineIndent("if self." + *field->name + " is not None:");
+
3512 Indent(1);
+
3513 WriteLineIndent("first = True");
+
3514 WriteLineIndent("sb.append(\"[\" + str(len(self." + *field->name + "))" + " + \"]<\")");
+
3515 WriteLineIndent("for item in self." + *field->name + ":");
+
3516 Indent(1);
+
3517 WriteOutputStreamValue(*field->type, "item", field->optional, true);
+
3518 WriteLineIndent("first = False");
+
3519 Indent(-1);
+
3520 WriteLineIndent("sb.append(\">\")");
+
3521 Indent(-1);
+
3522 WriteLineIndent("else:");
+
3523 Indent(1);
+
3524 WriteLineIndent("sb.append(\"[0]<>\")");
+
3525 Indent(-1);
+
3526 }
+
3527 else if (field->set)
+
3528 {
+
3529 WriteLineIndent("if self." + *field->name + " is not None:");
+
3530 Indent(1);
+
3531 WriteLineIndent("first = True");
+
3532 WriteLineIndent("sb.append(\"[\" + str(len(self." + *field->name + "))" + " + \"]{\")");
+
3533 WriteLineIndent("for item in self." + *field->name + ":");
+
3534 Indent(1);
+
3535 WriteOutputStreamValue(*field->type, "item", field->optional, true);
+
3536 WriteLineIndent("first = False");
+
3537 Indent(-1);
+
3538 WriteLineIndent("sb.append(\"}\")");
+
3539 Indent(-1);
+
3540 WriteLineIndent("else:");
+
3541 Indent(1);
+
3542 WriteLineIndent("sb.append(\"[0]{}\")");
+
3543 Indent(-1);
+
3544 }
+
3545 else if (field->map)
+
3546 {
+
3547 WriteLineIndent("if self." + *field->name + " is not None:");
+
3548 Indent(1);
+
3549 WriteLineIndent("first = True");
+
3550 WriteLineIndent("sb.append(\"[\" + str(len(self." + *field->name + "))" + " + \"]<{\")");
+
3551 WriteLineIndent("for key, value in self." + *field->name + ".items():");
+
3552 Indent(1);
+
3553 WriteOutputStreamValue(*field->key, "key", false, true);
+
3554 WriteLineIndent("sb.append(\"->\")");
+
3555 WriteOutputStreamValue(*field->type, "value", field->optional, false);
+
3556 WriteLineIndent("first = False");
+
3557 Indent(-1);
+
3558 WriteLineIndent("sb.append(\"}>\")");
+
3559 Indent(-1);
+
3560 WriteLineIndent("else:");
+
3561 Indent(1);
+
3562 WriteLineIndent("sb.append(\"[0]<{}>\")");
+
3563 Indent(-1);
+
3564 }
+
3565 else if (field->hash)
+
3566 {
+
3567 WriteLineIndent("if self." + *field->name + " is not None:");
+
3568 Indent(1);
+
3569 WriteLineIndent("first = True");
+
3570 WriteLineIndent("sb.append(\"[\" + str(len(self." + *field->name + "))" + " + \"][{\")");
+
3571 WriteLineIndent("for key, value in self." + *field->name + ".items():");
+
3572 Indent(1);
+
3573 WriteOutputStreamValue(*field->key, "key", false, true);
+
3574 WriteLineIndent("sb.append(\"->\")");
+
3575 WriteOutputStreamValue(*field->type, "value", field->optional, false);
+
3576 WriteLineIndent("first = False");
+
3577 Indent(-1);
+
3578 WriteLineIndent("sb.append(\"}]\")");
+
3579 Indent(-1);
+
3580 WriteLineIndent("else:");
+
3581 Indent(1);
+
3582 WriteLineIndent("sb.append(\"[0][{}]\")");
+
3583 Indent(-1);
+
3584 }
+
3585 else
+
3586 WriteOutputStreamValue(*field->type, "self." + *field->name, field->optional, false);
+
3587 first = false;
+
3588 }
+
3589 }
+
3590 WriteLineIndent("sb.append(\")\")");
+
3591 WriteLineIndent("return \"\".join(sb)");
+
3592 Indent(-1);
+
3593
+
3594 if (JSON())
+
3595 {
+
3596 // Generate struct to_json method
+
3597 WriteLine();
+
3598 WriteLineIndent("# Get struct JSON value");
+
3599 WriteLineIndent("def to_json(self):");
+
3600 Indent(1);
+
3601 WriteLineIndent("return json.dumps(self.__to_json__(), cls=fbe.JSONEncoder, separators=(',', ':'))");
+
3602 Indent(-1);
+
3603
+
3604 // Generate struct __to_json__ method
+
3605 WriteLine();
+
3606 WriteLineIndent("def __to_json__(self):");
+
3607 Indent(1);
+
3608 WriteLineIndent("result = dict()");
+
3609 if (s->base && !s->base->empty())
+
3610 WriteLineIndent("result.update(super().__to_json__())");
+
3611 if (s->body)
+
3612 {
+
3613 WriteLineIndent("result.update(dict(");
+
3614 Indent(1);
+
3615 for (const auto& field : s->body->fields)
+
3616 {
+
3617 if ((*field->type == "char") || (*field->type == "wchar"))
+
3618 WriteLineIndent(*field->name + "=None if self." + *field->name + " is None else ord(self." + *field->name + "), ");
+
3619 else
+
3620 WriteLineIndent(*field->name + "=self." + *field->name + ", ");
+
3621 }
+
3622 Indent(-1);
+
3623 WriteLineIndent("))");
+
3624 }
+
3625 WriteLineIndent("return result");
+
3626 Indent(-1);
+
3627
+
3628 // Generate struct from_json method
+
3629 WriteLine();
+
3630 WriteLineIndent("# Create struct from JSON value");
+
3631 WriteLineIndent("@staticmethod");
+
3632 WriteLineIndent("def from_json(document):");
+
3633 Indent(1);
+
3634 WriteLineIndent("return " + *s->name + ".__from_json__(json.loads(document))");
+
3635 Indent(-1);
+
3636
+
3637 // Generate struct __from_json__ method
+
3638 WriteLine();
+
3639 WriteLineIndent("@staticmethod");
+
3640 WriteLineIndent("def __from_json__(fields):");
+
3641 Indent(1);
+
3642 WriteLineIndent("if fields is None:");
+
3643 Indent(1);
+
3644 WriteLineIndent("return None");
+
3645 Indent(-1);
+
3646 WriteLineIndent("return " + *s->name + "(");
+
3647 Indent(1);
+
3648 if (s->base && !s->base->empty())
+
3649 WriteLineIndent(base_type + ".__from_json__(fields),");
+
3650 if (s->body)
+
3651 {
+
3652 for (const auto& field : s->body->fields)
+
3653 {
+
3654 std::string key;
+
3655 if (field->key)
+
3656 {
+
3657 if ((*field->key == "char") || (*field->key == "wchar"))
+
3658 key = "None if key is None else chr(key)";
+
3659 else if (*field->key == "bytes")
+
3660 key = "None if key is None else base64.b64decode(key.encode('ascii'))";
+
3661 else if (*field->key == "decimal")
+
3662 key = "None if key is None else decimal.Decimal(key)";
+
3663 else if (*field->key == "uuid")
+
3664 key = "None if key is None else uuid.UUID(key)";
+
3665 else if (IsPythonType(*field->key))
+
3666 key = "key";
+
3667 else
+
3668 key = *field->key + ".__from_json__(key)";
+
3669 }
+
3670
+
3671 std::string value;
+
3672 if (field->type)
+
3673 {
+
3674 if ((*field->type == "char") || (*field->type == "wchar"))
+
3675 value = "None if value is None else chr(value)";
+
3676 else if (*field->type == "bytes")
+
3677 value = "None if value is None else base64.b64decode(value.encode('ascii'))";
+
3678 else if (*field->type == "decimal")
+
3679 value = "None if value is None else decimal.Decimal(value)";
+
3680 else if (*field->type == "uuid")
+
3681 value = "None if value is None else uuid.UUID(value)";
+
3682 else if (IsPythonType(*field->type))
+
3683 value = "value";
+
3684 else
+
3685 value = *field->type + ".__from_json__(value)";
+
3686 }
+
3687
+
3688 if (field->array || field->vector || field->list)
+
3689 WriteLineIndent("None if \"" + *field->name + "\" not in fields else [" + value + " for value in fields[\"" + *field->name + "\"]],");
+
3690 else if (field->set)
+
3691 WriteLineIndent("None if \"" + *field->name + "\" not in fields else {" + value + " for value in fields[\"" + *field->name + "\"]},");
+
3692 else if (field->map || field->hash)
+
3693 WriteLineIndent("None if \"" + *field->name + "\" not in fields else {" + key + ": " + value + " for key, value in fields[\"" + *field->name + "\"].items()},");
+
3694 else if ((*field->type == "char") || (*field->type == "wchar"))
+
3695 WriteLineIndent("None if \"" + *field->name + "\" not in fields else None if fields[\"" + *field->name + "\"] is None else chr(fields[\"" + *field->name + "\"]),");
+
3696 else if (*field->type == "bytes")
+
3697 WriteLineIndent("None if \"" + *field->name + "\" not in fields else None if fields[\"" + *field->name + "\"] is None else base64.b64decode(fields[\"" + *field->name + "\"].encode('ascii')),");
+
3698 else if (*field->type == "decimal")
+
3699 WriteLineIndent("None if \"" + *field->name + "\" not in fields else None if fields[\"" + *field->name + "\"] is None else decimal.Decimal(fields[\"" + *field->name + "\"]),");
+
3700 else if (*field->type == "uuid")
+
3701 WriteLineIndent("None if \"" + *field->name + "\" not in fields else None if fields[\"" + *field->name + "\"] is None else uuid.UUID(fields[\"" + *field->name + "\"]),");
+
3702 else if (IsPythonType(*field->type))
+
3703 WriteLineIndent("None if \"" + *field->name + "\" not in fields else fields[\"" + *field->name + "\"],");
+
3704 else
+
3705 WriteLineIndent("None if \"" + *field->name + "\" not in fields else " + *field->type + ".__from_json__(fields[\"" + *field->name + "\"]),");
+
3706 }
+
3707 }
+
3708 Indent(-1);
+
3709 WriteLineIndent(")");
+
3710 Indent(-1);
+
3711 }
+
3712
+
3713 // Generate struct FBE type property
+
3714 WriteLine();
+
3715 WriteLineIndent("# Get the FBE type");
+
3716 WriteLineIndent("@property");
+
3717 WriteLineIndent("def fbe_type(self):");
+
3718 Indent(1);
+
3719 WriteLineIndent("return self.TYPE");
+
3720 Indent(-1);
+
3721
+
3722 // Generate struct FBE type
+
3723 WriteLine();
+
3724 if (s->base && !s->base->empty() && (s->type == 0))
+
3725 WriteLineIndent("TYPE = " + base_type + ".TYPE");
+
3726 else
+
3727 WriteLineIndent("TYPE = " + std::to_string(s->type));
+
3728
+
3729 // Generate struct end
+
3730 Indent(-1);
+
3731
+
3732 // Generate struct field model
+
3733 GenerateStructFieldModel(s);
+
3734
+
3735 // Generate struct model
+
3736 GenerateStructModel(s);
+
3737
+
3738 // Generate struct final models
+
3739 if (Final())
+
3740 {
+
3741 GenerateStructFinalModel(s);
+
3742 GenerateStructModelFinal(s);
+
3743 }
+
3744}
+
3745
+
3746void GeneratorPython::GenerateStructFieldModel(const std::shared_ptr<StructType>& s)
+
3747{
+
3748 // Generate struct field model begin
+
3749 WriteLine();
+
3750 WriteLine();
+
3751 WriteLineIndent("class FieldModel" + *s->name + "(fbe.FieldModel):");
+
3752 Indent(1);
+
3753
+
3754 // Generate struct field model __slots__
+
3755 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
3756 {
+
3757 WriteIndent("__slots__ = ");
+
3758 if (s->base && !s->base->empty())
+
3759 Write("\"_parent\", ");
+
3760 if (s->body)
+
3761 for (const auto& field : s->body->fields)
+
3762 Write("\"_" + *field->name + "\", ");
+
3763 WriteLine();
+
3764 WriteLine();
+
3765 }
+
3766
+
3767 // Generate struct field model constructor
+
3768 WriteLineIndent("def __init__(self, buffer, offset):");
+
3769 Indent(1);
+
3770 WriteLineIndent("super().__init__(buffer, offset)");
+
3771 std::string prev_offset("4");
+
3772 std::string prev_size("4");
+
3773 if (s->base && !s->base->empty())
+
3774 {
+
3775 WriteLineIndent("self._parent = " + ConvertTypeFieldName(*s->base, false) + "(buffer, " + prev_offset + " + " + prev_size + ")");
+
3776 prev_offset = "self._parent.fbe_offset";
+
3777 prev_size = "self._parent.fbe_body - 4 - 4";
+
3778 }
+
3779 if (s->body)
+
3780 {
+
3781 for (const auto& field : s->body->fields)
+
3782 {
+
3783 WriteLineIndent("self._" + *field->name + " = " + ConvertTypeFieldInitialization(*field, prev_offset + " + " + prev_size, false));
+
3784 prev_offset = "self._" + *field->name + ".fbe_offset";
+
3785 prev_size = "self._" + *field->name + ".fbe_size";
+
3786 }
+
3787 }
+
3788 Indent(-1);
+
3789
+
3790 // Generate struct field model accessors
+
3791 if (s->base && !s->base->empty())
+
3792 {
+
3793 WriteLine();
+
3794 WriteLineIndent("@property");
+
3795 WriteLineIndent("def parent(self):");
+
3796 Indent(1);
+
3797 WriteLineIndent("return self._parent");
+
3798 Indent(-1);
+
3799 }
+
3800 if (s->body)
+
3801 {
+
3802 for (const auto& field : s->body->fields)
+
3803 {
+
3804 WriteLine();
+
3805 WriteLineIndent("@property");
+
3806 WriteLineIndent("def " + *field->name + "(self):");
+
3807 Indent(1);
+
3808 WriteLineIndent("return self._" + *field->name);
+
3809 Indent(-1);
+
3810 }
+
3811 }
+
3812
+
3813 // Generate struct field model FBE properties
+
3814 WriteLine();
+
3815 WriteLineIndent("# Get the field size");
+
3816 WriteLineIndent("@property");
+
3817 WriteLineIndent("def fbe_size(self):");
+
3818 Indent(1);
+
3819 WriteLineIndent("return 4");
+
3820 Indent(-1);
+
3821 WriteLine();
+
3822 WriteLineIndent("# Get the field body size");
+
3823 WriteLineIndent("@property");
+
3824 WriteLineIndent("def fbe_body(self):");
+
3825 Indent(1);
+
3826 WriteLineIndent("fbe_result = 4 + 4 \\");
+
3827 Indent(1);
+
3828 if (s->base && !s->base->empty())
+
3829 WriteLineIndent("+ self.parent.fbe_body - 4 - 4 \\");
+
3830 if (s->body)
+
3831 for (const auto& field : s->body->fields)
+
3832 WriteLineIndent("+ self." + *field->name + ".fbe_size \\");
+
3833 Indent(-1);
+
3834 WriteLine();
+
3835 WriteLineIndent("return fbe_result");
+
3836 Indent(-1);
+
3837 WriteLine();
+
3838 WriteLineIndent("# Get the field extra size");
+
3839 WriteLineIndent("@property");
+
3840 WriteLineIndent("def fbe_extra(self):");
+
3841 Indent(1);
+
3842 WriteLineIndent("if (self._buffer.offset + self.fbe_offset + self.fbe_size) > self._buffer.size:");
+
3843 Indent(1);
+
3844 WriteLineIndent("return 0");
+
3845 Indent(-1);
+
3846 WriteLine();
+
3847 WriteLineIndent("fbe_struct_offset = self.read_uint32(self.fbe_offset)");
+
3848 WriteLineIndent("if (fbe_struct_offset == 0) or ((self._buffer.offset + fbe_struct_offset + 4) > self._buffer.size):");
+
3849 Indent(1);
+
3850 WriteLineIndent("return 0");
+
3851 Indent(-1);
+
3852 WriteLine();
+
3853 WriteLineIndent("self._buffer.shift(fbe_struct_offset)");
+
3854 WriteLine();
+
3855 WriteLineIndent("fbe_result = self.fbe_body \\");
+
3856 Indent(1);
+
3857 if (s->base && !s->base->empty())
+
3858 WriteLineIndent("+ self.parent.fbe_extra \\");
+
3859 if (s->body)
+
3860 for (const auto& field : s->body->fields)
+
3861 WriteLineIndent("+ self." + *field->name + ".fbe_extra \\");
+
3862 Indent(-1);
+
3863 WriteLine();
+
3864 WriteLineIndent("self._buffer.unshift(fbe_struct_offset)");
+
3865 WriteLine();
+
3866 WriteLineIndent("return fbe_result");
+
3867 Indent(-1);
+
3868 WriteLine();
+
3869 WriteLineIndent("# Get the field type");
+
3870 WriteLineIndent("@property");
+
3871 WriteLineIndent("def fbe_type(self):");
+
3872 Indent(1);
+
3873 WriteLineIndent("return self.TYPE");
+
3874 Indent(-1);
+
3875
+
3876 // Generate struct field model type
+
3877 WriteLine();
+
3878 if (s->base && !s->base->empty() && (s->type == 0))
+
3879 WriteLineIndent("TYPE = " + ConvertTypeFieldName(*s->base, false) + ".TYPE");
+
3880 else
+
3881 WriteLineIndent("TYPE = " + std::to_string(s->type));
+
3882
+
3883 // Generate struct field model verify() method
+
3884 WriteLine();
+
3885 WriteLineIndent("# Check if the struct value is valid");
+
3886 WriteLineIndent("def verify(self, fbe_verify_type=True):");
+
3887 Indent(1);
+
3888 WriteLineIndent("if (self._buffer.offset + self.fbe_offset + self.fbe_size) > self._buffer.size:");
+
3889 Indent(1);
+
3890 WriteLineIndent("return True");
+
3891 Indent(-1);
+
3892 WriteLine();
+
3893 WriteLineIndent("fbe_struct_offset = self.read_uint32(self.fbe_offset)");
+
3894 WriteLineIndent("if (fbe_struct_offset == 0) or ((self._buffer.offset + fbe_struct_offset + 4 + 4) > self._buffer.size):");
+
3895 Indent(1);
+
3896 WriteLineIndent("return False");
+
3897 Indent(-1);
+
3898 WriteLine();
+
3899 WriteLineIndent("fbe_struct_size = self.read_uint32(fbe_struct_offset)");
+
3900 WriteLineIndent("if fbe_struct_size < (4 + 4):");
+
3901 Indent(1);
+
3902 WriteLineIndent("return False");
+
3903 Indent(-1);
+
3904 WriteLine();
+
3905 WriteLineIndent("fbe_struct_type = self.read_uint32(fbe_struct_offset + 4)");
+
3906 WriteLineIndent("if fbe_verify_type and (fbe_struct_type != self.fbe_type):");
+
3907 Indent(1);
+
3908 WriteLineIndent("return False");
+
3909 Indent(-1);
+
3910 WriteLine();
+
3911 WriteLineIndent("self._buffer.shift(fbe_struct_offset)");
+
3912 WriteLineIndent("fbe_result = self.verify_fields(fbe_struct_size)");
+
3913 WriteLineIndent("self._buffer.unshift(fbe_struct_offset)");
+
3914 WriteLineIndent("return fbe_result");
+
3915 Indent(-1);
+
3916
+
3917 // Generate struct field model verify_fields() method
+
3918 WriteLine();
+
3919 WriteLineIndent("# Check if the struct fields are valid");
+
3920 WriteLineIndent("def verify_fields(self, fbe_struct_size):");
+
3921 Indent(1);
+
3922 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
3923 {
+
3924 WriteLineIndent("fbe_current_size = 4 + 4");
+
3925 if (s->base && !s->base->empty())
+
3926 {
+
3927 WriteLine();
+
3928 WriteLineIndent("if (fbe_current_size + self.parent.fbe_body - 4 - 4) > fbe_struct_size:");
+
3929 Indent(1);
+
3930 WriteLineIndent("return True");
+
3931 Indent(-1);
+
3932 WriteLineIndent("if not self.parent.verify_fields(fbe_struct_size):");
+
3933 Indent(1);
+
3934 WriteLineIndent("return False");
+
3935 Indent(-1);
+
3936 WriteLineIndent("fbe_current_size += self.parent.fbe_body - 4 - 4");
+
3937 }
+
3938 if (s->body)
+
3939 {
+
3940 for (const auto& field : s->body->fields)
+
3941 {
+
3942 WriteLine();
+
3943 WriteLineIndent("if (fbe_current_size + self." + *field->name + ".fbe_size) > fbe_struct_size:");
+
3944 Indent(1);
+
3945 WriteLineIndent("return True");
+
3946 Indent(-1);
+
3947 WriteLineIndent("if not self." + *field->name + ".verify():");
+
3948 Indent(1);
+
3949 WriteLineIndent("return False");
+
3950 Indent(-1);
+
3951 WriteLineIndent("fbe_current_size += self." + *field->name + ".fbe_size");
+
3952 }
+
3953 }
+
3954 WriteLine();
+
3955 }
+
3956 WriteLineIndent("return True");
+
3957 Indent(-1);
+
3958
+
3959 // Generate struct field model get_begin() method
+
3960 WriteLine();
+
3961 WriteLineIndent("# Get the struct value (begin phase)");
+
3962 WriteLineIndent("def get_begin(self):");
+
3963 Indent(1);
+
3964 WriteLineIndent("if (self._buffer.offset + self.fbe_offset + self.fbe_size) > self._buffer.size:");
+
3965 Indent(1);
+
3966 WriteLineIndent("return 0");
+
3967 Indent(-1);
+
3968 WriteLine();
+
3969 WriteLineIndent("fbe_struct_offset = self.read_uint32(self.fbe_offset)");
+
3970 WriteLineIndent("assert (fbe_struct_offset > 0) and ((self._buffer.offset + fbe_struct_offset + 4 + 4) <= self._buffer.size), \"Model is broken!\"");
+
3971 WriteLineIndent("if (fbe_struct_offset == 0) or ((self._buffer.offset + fbe_struct_offset + 4 + 4) > self._buffer.size):");
+
3972 Indent(1);
+
3973 WriteLineIndent("return 0");
+
3974 Indent(-1);
+
3975 WriteLine();
+
3976 WriteLineIndent("fbe_struct_size = self.read_uint32(fbe_struct_offset)");
+
3977 WriteLineIndent("assert (fbe_struct_size >= (4 + 4)), \"Model is broken!\"");
+
3978 WriteLineIndent("if fbe_struct_size < (4 + 4):");
+
3979 Indent(1);
+
3980 WriteLineIndent("return 0");
+
3981 Indent(-1);
+
3982 WriteLine();
+
3983 WriteLineIndent("self._buffer.shift(fbe_struct_offset)");
+
3984 WriteLineIndent("return fbe_struct_offset");
+
3985 Indent(-1);
+
3986
+
3987 // Generate struct field model get_end() method
+
3988 WriteLine();
+
3989 WriteLineIndent("# Get the struct value (end phase)");
+
3990 WriteLineIndent("def get_end(self, fbe_begin):");
+
3991 Indent(1);
+
3992 WriteLineIndent("self._buffer.unshift(fbe_begin)");
+
3993 Indent(-1);
+
3994
+
3995 // Generate struct field model get() method
+
3996 WriteLine();
+
3997 WriteLineIndent("# Get the struct value");
+
3998 WriteLineIndent("def get(self, fbe_value=None):");
+
3999 Indent(1);
+
4000 WriteLineIndent("if fbe_value is None:");
+
4001 Indent(1);
+
4002 WriteLineIndent("fbe_value = " + *s->name + "()");
+
4003 Indent(-1);
+
4004 WriteLine();
+
4005 WriteLineIndent("fbe_begin = self.get_begin()");
+
4006 WriteLineIndent("if fbe_begin == 0:");
+
4007 Indent(1);
+
4008 WriteLineIndent("return fbe_value");
+
4009 Indent(-1);
+
4010 WriteLine();
+
4011 WriteLineIndent("fbe_struct_size = self.read_uint32(0)");
+
4012 WriteLineIndent("self.get_fields(fbe_value, fbe_struct_size)");
+
4013 WriteLineIndent("self.get_end(fbe_begin)");
+
4014 WriteLineIndent("return fbe_value");
+
4015 Indent(-1);
+
4016
+
4017 // Generate struct field model get_fields() method
+
4018 WriteLine();
+
4019 WriteLineIndent("# Get the struct fields values");
+
4020 WriteLineIndent("def get_fields(self, fbe_value, fbe_struct_size):");
+
4021 Indent(1);
+
4022 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
4023 {
+
4024 WriteLineIndent("fbe_current_size = 4 + 4");
+
4025 if (s->base && !s->base->empty())
+
4026 {
+
4027 WriteLine();
+
4028 WriteLineIndent("if (fbe_current_size + self.parent.fbe_body - 4 - 4) <= fbe_struct_size:");
+
4029 Indent(1);
+
4030 WriteLineIndent("self.parent.get_fields(fbe_value, fbe_struct_size)");
+
4031 Indent(-1);
+
4032 WriteLineIndent("fbe_current_size += self.parent.fbe_body - 4 - 4");
+
4033 }
+
4034 if (s->body)
+
4035 {
+
4036 for (const auto& field : s->body->fields)
+
4037 {
+
4038 WriteLine();
+
4039 WriteLineIndent("if (fbe_current_size + self." + *field->name + ".fbe_size) <= fbe_struct_size:");
+
4040 Indent(1);
+
4041 if (field->array || field->vector || field->list || field->set || field->map || field->hash)
+
4042 WriteLineIndent("self." + *field->name + ".get(fbe_value." + *field->name + ")");
+
4043 else
+
4044 WriteLineIndent("fbe_value." + *field->name + " = self." + *field->name + ".get(" + (field->value ? ConvertConstant(*field->type, *field->value, field->optional) : "") + ")");
+
4045 Indent(-1);
+
4046 WriteLineIndent("else:");
+
4047 Indent(1);
+
4048 if (field->array || field->vector || field->list || field->set || field->map || field->hash)
+
4049 WriteLineIndent("fbe_value." + *field->name + ".clear()");
+
4050 else
+
4051 WriteLineIndent("fbe_value." + *field->name + " = " + ConvertDefault(*field));
+
4052 Indent(-1);
+
4053 WriteLineIndent("fbe_current_size += self." + *field->name + ".fbe_size");
+
4054 }
+
4055 }
+
4056 }
+
4057 else
+
4058 WriteLineIndent("pass");
+
4059 Indent(-1);
+
4060
+
4061 // Generate struct field model set_begin() method
+
4062 WriteLine();
+
4063 WriteLineIndent("# Set the struct value (begin phase)");
+
4064 WriteLineIndent("def set_begin(self):");
+
4065 Indent(1);
+
4066 WriteLineIndent("assert (self._buffer.offset + self.fbe_offset + self.fbe_size) <= self._buffer.size, \"Model is broken!\"");
+
4067 WriteLineIndent("if (self._buffer.offset + self.fbe_offset + self.fbe_size) > self._buffer.size:");
+
4068 Indent(1);
+
4069 WriteLineIndent("return 0");
+
4070 Indent(-1);
+
4071 WriteLine();
+
4072 WriteLineIndent("fbe_struct_size = self.fbe_body");
+
4073 WriteLineIndent("fbe_struct_offset = self._buffer.allocate(fbe_struct_size) - self._buffer.offset");
+
4074 WriteLineIndent("assert (fbe_struct_offset > 0) and ((self._buffer.offset + fbe_struct_offset + fbe_struct_size) <= self._buffer.size), \"Model is broken!\"");
+
4075 WriteLineIndent("if (fbe_struct_offset <= 0) or ((self._buffer.offset + fbe_struct_offset + fbe_struct_size) > self._buffer.size):");
+
4076 Indent(1);
+
4077 WriteLineIndent("return 0");
+
4078 Indent(-1);
+
4079 WriteLine();
+
4080 WriteLineIndent("self.write_uint32(self.fbe_offset, fbe_struct_offset)");
+
4081 WriteLineIndent("self.write_uint32(fbe_struct_offset, fbe_struct_size)");
+
4082 WriteLineIndent("self.write_uint32(fbe_struct_offset + 4, self.fbe_type)");
+
4083 WriteLine();
+
4084 WriteLineIndent("self._buffer.shift(fbe_struct_offset)");
+
4085 WriteLineIndent("return fbe_struct_offset");
+
4086 Indent(-1);
+
4087
+
4088 // Generate struct field model set_end() method
+
4089 WriteLine();
+
4090 WriteLineIndent("# Set the struct value (end phase)");
+
4091 WriteLineIndent("def set_end(self, fbe_begin):");
+
4092 Indent(1);
+
4093 WriteLineIndent("self._buffer.unshift(fbe_begin)");
+
4094 Indent(-1);
+
4095
+
4096 // Generate struct field model set() method
+
4097 WriteLine();
+
4098 WriteLineIndent("# Set the struct value");
+
4099 WriteLineIndent("def set(self, fbe_value):");
+
4100 Indent(1);
+
4101 WriteLineIndent("fbe_begin = self.set_begin()");
+
4102 WriteLineIndent("if fbe_begin == 0:");
+
4103 Indent(1);
+
4104 WriteLineIndent("return");
+
4105 Indent(-1);
+
4106 WriteLine();
+
4107 WriteLineIndent("self.set_fields(fbe_value)");
+
4108 WriteLineIndent("self.set_end(fbe_begin)");
+
4109 Indent(-1);
+
4110
+
4111 // Generate struct field model set_fields() method
+
4112 WriteLine();
+
4113 WriteLineIndent("# Set the struct fields values");
+
4114 WriteLineIndent("def set_fields(self, fbe_value):");
+
4115 Indent(1);
+
4116 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
4117 {
+
4118 if (s->base && !s->base->empty())
+
4119 WriteLineIndent("self.parent.set_fields(fbe_value)");
+
4120 if (s->body)
+
4121 for (const auto& field : s->body->fields)
+
4122 WriteLineIndent("self." + *field->name + ".set(fbe_value." + *field->name + ")");
+
4123 }
+
4124 else
+
4125 WriteLineIndent("pass");
+
4126 Indent(-1);
+
4127
+
4128 // Generate struct field model end
+
4129 Indent(-1);
+
4130}
+
4131
+
4132void GeneratorPython::GenerateStructModel(const std::shared_ptr<StructType>& s)
+
4133{
+
4134 // Generate struct model begin
+
4135 WriteLine();
+
4136 WriteLine();
+
4137 WriteLineIndent("# Fast Binary Encoding " + *s->name + " model");
+
4138 WriteLineIndent("class " + *s->name + "Model(fbe.Model):");
+
4139 Indent(1);
+
4140
+
4141 // Generate struct model __slots__
+
4142 WriteLineIndent("__slots__ = \"_model\",");
+
4143
+
4144 // Generate struct model constructor
+
4145 WriteLine();
+
4146 WriteLineIndent("def __init__(self, buffer=None):");
+
4147 Indent(1);
+
4148 WriteLineIndent("super().__init__(buffer)");
+
4149 WriteLineIndent("self._model = FieldModel" + *s->name + "(self.buffer, 4)");
+
4150 Indent(-1);
+
4151
+
4152 // Generate struct model accessor
+
4153 WriteLine();
+
4154 WriteLineIndent("@property");
+
4155 WriteLineIndent("def model(self):");
+
4156 Indent(1);
+
4157 WriteLineIndent("return self._model");
+
4158 Indent(-1);
+
4159
+
4160 // Generate struct model FBE properties
+
4161 WriteLine();
+
4162 WriteLineIndent("# Get the model size");
+
4163 WriteLineIndent("@property");
+
4164 WriteLineIndent("def fbe_size(self):");
+
4165 Indent(1);
+
4166 WriteLineIndent("return self._model.fbe_size + self._model.fbe_extra");
+
4167 Indent(-1);
+
4168 WriteLine();
+
4169 WriteLineIndent("# Get the model type");
+
4170 WriteLineIndent("@property");
+
4171 WriteLineIndent("def fbe_type(self):");
+
4172 Indent(1);
+
4173 WriteLineIndent("return self.TYPE");
+
4174 Indent(-1);
+
4175
+
4176 // Generate struct model type
+
4177 WriteLine();
+
4178 WriteLineIndent("TYPE = FieldModel" + *s->name + ".TYPE");
+
4179
+
4180 // Generate struct model verify() method
+
4181 WriteLine();
+
4182 WriteLineIndent("# Check if the struct value is valid");
+
4183 WriteLineIndent("def verify(self):");
+
4184 Indent(1);
+
4185 WriteLineIndent("if (self.buffer.offset + self._model.fbe_offset - 4) > self.buffer.size:");
+
4186 Indent(1);
+
4187 WriteLineIndent("return False");
+
4188 Indent(-1);
+
4189 WriteLine();
+
4190 WriteLineIndent("fbe_full_size = self.read_uint32(self._model.fbe_offset - 4)");
+
4191 WriteLineIndent("if fbe_full_size < self._model.fbe_size:");
+
4192 Indent(1);
+
4193 WriteLineIndent("return False");
+
4194 Indent(-1);
+
4195 WriteLine();
+
4196 WriteLineIndent("return self._model.verify()");
+
4197 Indent(-1);
+
4198
+
4199 // Generate struct model create_begin() method
+
4200 WriteLine();
+
4201 WriteLineIndent("# Create a new model (begin phase)");
+
4202 WriteLineIndent("def create_begin(self):");
+
4203 Indent(1);
+
4204 WriteLineIndent("fbe_begin = self.buffer.allocate(4 + self._model.fbe_size)");
+
4205 WriteLineIndent("return fbe_begin");
+
4206 Indent(-1);
+
4207
+
4208 // Generate struct model create_end() method
+
4209 WriteLine();
+
4210 WriteLineIndent("# Create a new model (end phase)");
+
4211 WriteLineIndent("def create_end(self, fbe_begin):");
+
4212 Indent(1);
+
4213 WriteLineIndent("fbe_end = self.buffer.size");
+
4214 WriteLineIndent("fbe_full_size = fbe_end - fbe_begin");
+
4215 WriteLineIndent("self.write_uint32(self._model.fbe_offset - 4, fbe_full_size)");
+
4216 WriteLineIndent("return fbe_full_size");
+
4217 Indent(-1);
+
4218
+
4219 // Generate struct model serialize() method
+
4220 WriteLine();
+
4221 WriteLineIndent("# Serialize the struct value");
+
4222 WriteLineIndent("def serialize(self, value):");
+
4223 Indent(1);
+
4224 WriteLineIndent("fbe_begin = self.create_begin()");
+
4225 WriteLineIndent("self._model.set(value)");
+
4226 WriteLineIndent("fbe_full_size = self.create_end(fbe_begin)");
+
4227 WriteLineIndent("return fbe_full_size");
+
4228 Indent(-1);
+
4229
+
4230 // Generate struct model deserialize() methods
+
4231 WriteLine();
+
4232 WriteLineIndent("# Deserialize the struct value");
+
4233 WriteLineIndent("def deserialize(self, value=None):");
+
4234 Indent(1);
+
4235 WriteLineIndent("if value is None:");
+
4236 Indent(1);
+
4237 WriteLineIndent("value = " + *s->name + "()");
+
4238 Indent(-1);
+
4239 WriteLine();
+
4240 WriteLineIndent("if (self.buffer.offset + self._model.fbe_offset - 4) > self.buffer.size:");
+
4241 Indent(1);
+
4242 WriteLineIndent("value = " + *s->name + "()");
+
4243 WriteLineIndent("return value, 0");
+
4244 Indent(-1);
+
4245 WriteLine();
+
4246 WriteLineIndent("fbe_full_size = self.read_uint32(self._model.fbe_offset - 4)");
+
4247 WriteLineIndent("assert (fbe_full_size >= self._model.fbe_size), \"Model is broken!\"");
+
4248 WriteLineIndent("if fbe_full_size < self._model.fbe_size:");
+
4249 Indent(1);
+
4250 WriteLineIndent("value = " + *s->name + "()");
+
4251 WriteLineIndent("return value, 0");
+
4252 Indent(-1);
+
4253 WriteLine();
+
4254 WriteLineIndent("self._model.get(value)");
+
4255 WriteLineIndent("return value, fbe_full_size");
+
4256 Indent(-1);
+
4257
+
4258 // Generate struct model next() method
+
4259 WriteLine();
+
4260 WriteLineIndent("# Move to the next struct value");
+
4261 WriteLineIndent("def next(self, prev):");
+
4262 Indent(1);
+
4263 WriteLineIndent("self._model.fbe_shift(prev)");
+
4264 Indent(-1);
+
4265
+
4266 // Generate struct model end
+
4267 Indent(-1);
+
4268}
+
4269
+
4270void GeneratorPython::GenerateStructFinalModel(const std::shared_ptr<StructType>& s)
+
4271{
+
4272 // Generate struct final model begin
+
4273 WriteLine();
+
4274 WriteLine();
+
4275 WriteLineIndent("class FinalModel" + *s->name + "(fbe.FinalModel):");
+
4276 Indent(1);
+
4277
+
4278 // Generate struct final model __slots__
+
4279 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
4280 {
+
4281 WriteIndent("__slots__ = ");
+
4282 if (s->base && !s->base->empty())
+
4283 Write("\"_parent\", ");
+
4284 if (s->body)
+
4285 for (const auto& field : s->body->fields)
+
4286 Write("\"_" + *field->name + "\", ");
+
4287 WriteLine();
+
4288 WriteLine();
+
4289 }
+
4290
+
4291 // Generate struct final model constructor
+
4292 WriteLineIndent("def __init__(self, buffer, offset):");
+
4293 Indent(1);
+
4294 WriteLineIndent("super().__init__(buffer, offset)");
+
4295 if (s->base && !s->base->empty())
+
4296 WriteLineIndent("self._parent = " + ConvertTypeFieldName(*s->base, true) + "(buffer, 0)");
+
4297 if (s->body)
+
4298 for (const auto& field : s->body->fields)
+
4299 WriteLineIndent("self._" + *field->name + " = " + ConvertTypeFieldInitialization(*field, "0", true));
+
4300 Indent(-1);
+
4301
+
4302 // Generate struct final model accessors
+
4303 if (s->base && !s->base->empty())
+
4304 {
+
4305 WriteLine();
+
4306 WriteLineIndent("@property");
+
4307 WriteLineIndent("def parent(self):");
+
4308 Indent(1);
+
4309 WriteLineIndent("return self._parent");
+
4310 Indent(-1);
+
4311 }
+
4312 if (s->body)
+
4313 {
+
4314 for (const auto& field : s->body->fields)
+
4315 {
+
4316 WriteLine();
+
4317 WriteLineIndent("@property");
+
4318 WriteLineIndent("def " + *field->name + "(self):");
+
4319 Indent(1);
+
4320 WriteLineIndent("return self._" + *field->name);
+
4321 Indent(-1);
+
4322 }
+
4323 }
+
4324
+
4325 // Generate struct final model FBE properties
+
4326 WriteLine();
+
4327 WriteLineIndent("# Get the allocation size");
+
4328 WriteLineIndent("def fbe_allocation_size(self, fbe_value):");
+
4329 Indent(1);
+
4330 WriteLineIndent("fbe_result = 0 \\");
+
4331 Indent(1);
+
4332 if (s->base && !s->base->empty())
+
4333 WriteLineIndent("+ self.parent.fbe_allocation_size(fbe_value) \\");
+
4334 if (s->body)
+
4335 for (const auto& field : s->body->fields)
+
4336 WriteLineIndent("+ self." + *field->name + ".fbe_allocation_size(fbe_value." + *field->name + ") \\");
+
4337 Indent(-1);
+
4338 WriteLine();
+
4339 WriteLineIndent("return fbe_result");
+
4340 Indent(-1);
+
4341 WriteLine();
+
4342 WriteLineIndent("# Get the final type");
+
4343 WriteLineIndent("@property");
+
4344 WriteLineIndent("def fbe_type(self):");
+
4345 Indent(1);
+
4346 WriteLineIndent("return self.TYPE");
+
4347 Indent(-1);
+
4348
+
4349 // Generate struct final model type
+
4350 WriteLine();
+
4351 if (s->base && !s->base->empty() && (s->type == 0))
+
4352 WriteLineIndent("TYPE = " + ConvertTypeFieldName(*s->base, true) + ".TYPE");
+
4353 else
+
4354 WriteLineIndent("TYPE = " + std::to_string(s->type));
+
4355
+
4356 // Generate struct final model verify() method
+
4357 WriteLine();
+
4358 WriteLineIndent("# Check if the struct value is valid");
+
4359 WriteLineIndent("def verify(self):");
+
4360 Indent(1);
+
4361 WriteLineIndent("self._buffer.shift(self.fbe_offset)");
+
4362 WriteLineIndent("fbe_result = self.verify_fields()");
+
4363 WriteLineIndent("self._buffer.unshift(self.fbe_offset)");
+
4364 WriteLineIndent("return fbe_result");
+
4365 Indent(-1);
+
4366
+
4367 // Generate struct final model verify_fields() method
+
4368 WriteLine();
+
4369 WriteLineIndent("# Check if the struct fields are valid");
+
4370 WriteLineIndent("def verify_fields(self):");
+
4371 Indent(1);
+
4372 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
4373 {
+
4374 WriteLineIndent("fbe_current_offset = 0");
+
4375 if (s->base && !s->base->empty())
+
4376 {
+
4377 WriteLine();
+
4378 WriteLineIndent("self.parent.fbe_offset = fbe_current_offset");
+
4379 WriteLineIndent("fbe_field_size = self.parent.verify_fields()");
+
4380 WriteLineIndent("if fbe_field_size == sys.maxsize:");
+
4381 Indent(1);
+
4382 WriteLineIndent("return sys.maxsize");
+
4383 Indent(-1);
+
4384 WriteLineIndent("fbe_current_offset += fbe_field_size");
+
4385 }
+
4386 if (s->body)
+
4387 {
+
4388 for (const auto& field : s->body->fields)
+
4389 {
+
4390 WriteLine();
+
4391 WriteLineIndent("self." + *field->name + ".fbe_offset = fbe_current_offset");
+
4392 WriteLineIndent("fbe_field_size = self." + *field->name + ".verify()");
+
4393 WriteLineIndent("if fbe_field_size == sys.maxsize:");
+
4394 Indent(1);
+
4395 WriteLineIndent("return sys.maxsize");
+
4396 Indent(-1);
+
4397 WriteLineIndent("fbe_current_offset += fbe_field_size");
+
4398 }
+
4399 }
+
4400 WriteLine();
+
4401 WriteLineIndent("return fbe_current_offset");
+
4402 }
+
4403 else
+
4404 WriteLineIndent("return 0");
+
4405 Indent(-1);
+
4406
+
4407 // Generate struct final model get() method
+
4408 WriteLine();
+
4409 WriteLineIndent("# Get the struct value");
+
4410 WriteLineIndent("def get(self, fbe_value=None):");
+
4411 Indent(1);
+
4412 WriteLineIndent("if fbe_value is None:");
+
4413 Indent(1);
+
4414 WriteLineIndent("fbe_value = " + *s->name + "()");
+
4415 Indent(-1);
+
4416 WriteLine();
+
4417 WriteLineIndent("self._buffer.shift(self.fbe_offset)");
+
4418 WriteLineIndent("fbe_size = self.get_fields(fbe_value)");
+
4419 WriteLineIndent("self._buffer.unshift(self.fbe_offset)");
+
4420 WriteLineIndent("return fbe_value, fbe_size");
+
4421 Indent(-1);
+
4422
+
4423 // Generate struct final model get_fields() method
+
4424 WriteLine();
+
4425 WriteLineIndent("# Get the struct fields values");
+
4426 WriteLineIndent("def get_fields(self, fbe_value):");
+
4427 Indent(1);
+
4428 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
4429 {
+
4430 WriteLineIndent("fbe_current_offset = 0");
+
4431 WriteLineIndent("fbe_current_size = 0");
+
4432 if (s->base && !s->base->empty())
+
4433 {
+
4434 WriteLine();
+
4435 WriteLineIndent("self.parent.fbe_offset = fbe_current_offset");
+
4436 WriteLineIndent("fbe_result = self.parent.get_fields(fbe_value)");
+
4437 WriteLineIndent("fbe_current_offset += fbe_result");
+
4438 WriteLineIndent("fbe_current_size += fbe_result");
+
4439 }
+
4440 if (s->body)
+
4441 {
+
4442 for (const auto& field : s->body->fields)
+
4443 {
+
4444 WriteLine();
+
4445 WriteLineIndent("self." + *field->name + ".fbe_offset = fbe_current_offset");
+
4446 if (field->array || field->vector || field->list || field->set || field->map || field->hash)
+
4447 WriteLineIndent("fbe_result = self." + *field->name + ".get(fbe_value." + *field->name + ")");
+
4448 else
+
4449 {
+
4450 WriteLineIndent("fbe_result = self." + *field->name + ".get()");
+
4451 WriteLineIndent("fbe_value." + *field->name + " = fbe_result[0]");
+
4452 }
+
4453 WriteLineIndent("fbe_current_offset += fbe_result[1]");
+
4454 WriteLineIndent("fbe_current_size += fbe_result[1]");
+
4455 }
+
4456 }
+
4457 WriteLine();
+
4458 WriteLineIndent("return fbe_current_size");
+
4459 }
+
4460 else
+
4461 WriteLineIndent("return 0");
+
4462 Indent(-1);
+
4463
+
4464 // Generate struct final model set() method
+
4465 WriteLine();
+
4466 WriteLineIndent("# Set the struct value");
+
4467 WriteLineIndent("def set(self, fbe_value):");
+
4468 Indent(1);
+
4469 WriteLineIndent("self._buffer.shift(self.fbe_offset)");
+
4470 WriteLineIndent("fbe_size = self.set_fields(fbe_value)");
+
4471 WriteLineIndent("self._buffer.unshift(self.fbe_offset)");
+
4472 WriteLineIndent("return fbe_size");
+
4473 Indent(-1);
+
4474
+
4475 // Generate struct final model set_fields() method
+
4476 WriteLine();
+
4477 WriteLineIndent("# Set the struct fields values");
+
4478 WriteLineIndent("def set_fields(self, fbe_value):");
+
4479 Indent(1);
+
4480 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
4481 {
+
4482 WriteLineIndent("fbe_current_offset = 0");
+
4483 WriteLineIndent("fbe_current_size = 0");
+
4484 if (s->base && !s->base->empty())
+
4485 {
+
4486 WriteLine();
+
4487 WriteLineIndent("self.parent.fbe_offset = fbe_current_offset");
+
4488 WriteLineIndent("fbe_field_size = self.parent.set_fields(fbe_value)");
+
4489 WriteLineIndent("fbe_current_offset += fbe_field_size");
+
4490 WriteLineIndent("fbe_current_size += fbe_field_size");
+
4491 }
+
4492 if (s->body)
+
4493 {
+
4494 for (const auto& field : s->body->fields)
+
4495 {
+
4496 WriteLine();
+
4497 WriteLineIndent("self." + *field->name + ".fbe_offset = fbe_current_offset");
+
4498 WriteLineIndent("fbe_field_size = self." + *field->name + ".set(fbe_value." + *field->name + ")");
+
4499 WriteLineIndent("fbe_current_offset += fbe_field_size");
+
4500 WriteLineIndent("fbe_current_size += fbe_field_size");
+
4501 }
+
4502 }
+
4503 WriteLine();
+
4504 WriteLineIndent("return fbe_current_size");
+
4505 }
+
4506 else
+
4507 WriteLineIndent("return 0");
+
4508 Indent(-1);
+
4509
+
4510 // Generate struct final model end
+
4511 Indent(-1);
+
4512}
+
4513
+
4514void GeneratorPython::GenerateStructModelFinal(const std::shared_ptr<StructType>& s)
+
4515{
+
4516 // Generate struct model final begin
+
4517 WriteLine();
+
4518 WriteLine();
+
4519 WriteLineIndent("# Fast Binary Encoding " + *s->name + " final model");
+
4520 WriteLineIndent("class " + *s->name + "FinalModel(fbe.Model):");
+
4521 Indent(1);
+
4522
+
4523 // Generate struct model final __slots__
+
4524 WriteLineIndent("__slots__ = \"_model\",");
+
4525
+
4526 // Generate struct model final constructor
+
4527 WriteLine();
+
4528 WriteLineIndent("def __init__(self, buffer=None):");
+
4529 Indent(1);
+
4530 WriteLineIndent("super().__init__(buffer)");
+
4531 WriteLineIndent("self._model = FinalModel" + *s->name + "(self.buffer, 8)");
+
4532 Indent(-1);
+
4533
+
4534 // Generate struct model final FBE properties
+
4535 WriteLine();
+
4536 WriteLineIndent("# Get the model type");
+
4537 WriteLineIndent("@property");
+
4538 WriteLineIndent("def fbe_type(self):");
+
4539 Indent(1);
+
4540 WriteLineIndent("return self.TYPE");
+
4541 Indent(-1);
+
4542
+
4543 // Generate struct model type
+
4544 WriteLine();
+
4545 WriteLineIndent("TYPE = FinalModel" + *s->name + ".TYPE");
+
4546
+
4547 // Generate struct model final verify() method
+
4548 WriteLine();
+
4549 WriteLineIndent("# Check if the struct value is valid");
+
4550 WriteLineIndent("def verify(self):");
+
4551 Indent(1);
+
4552 WriteLineIndent("if (self.buffer.offset + self._model.fbe_offset) > self.buffer.size:");
+
4553 Indent(1);
+
4554 WriteLineIndent("return False");
+
4555 Indent(-1);
+
4556 WriteLine();
+
4557 WriteLineIndent("fbe_struct_size = self.read_uint32(self._model.fbe_offset - 8)");
+
4558 WriteLineIndent("fbe_struct_type = self.read_uint32(self._model.fbe_offset - 4)");
+
4559 WriteLineIndent("if (fbe_struct_size <= 0) or (fbe_struct_type != self.fbe_type):");
+
4560 Indent(1);
+
4561 WriteLineIndent("return False");
+
4562 Indent(-1);
+
4563 WriteLine();
+
4564 WriteLineIndent("return (8 + self._model.verify()) == fbe_struct_size");
+
4565 Indent(-1);
+
4566
+
4567 // Generate struct model final serialize() method
+
4568 WriteLine();
+
4569 WriteLineIndent("# Serialize the struct value");
+
4570 WriteLineIndent("def serialize(self, value):");
+
4571 Indent(1);
+
4572 WriteLineIndent("fbe_initial_size = self.buffer.size");
+
4573 WriteLine();
+
4574 WriteLineIndent("fbe_struct_type = self.fbe_type");
+
4575 WriteLineIndent("fbe_struct_size = 8 + self._model.fbe_allocation_size(value)");
+
4576 WriteLineIndent("fbe_struct_offset = self.buffer.allocate(fbe_struct_size) - self.buffer.offset");
+
4577 WriteLineIndent("assert ((self.buffer.offset + fbe_struct_offset + fbe_struct_size) <= self.buffer.size), \"Model is broken!\"");
+
4578 WriteLineIndent("if (self.buffer.offset + fbe_struct_offset + fbe_struct_size) > self.buffer.size:");
+
4579 Indent(1);
+
4580 WriteLineIndent("return 0");
+
4581 Indent(-1);
+
4582 WriteLine();
+
4583 WriteLineIndent("fbe_struct_size = 8 + self._model.set(value)");
+
4584 WriteLineIndent("self.buffer.resize(fbe_initial_size + fbe_struct_size)");
+
4585 WriteLine();
+
4586 WriteLineIndent("self.write_uint32(self._model.fbe_offset - 8, fbe_struct_size)");
+
4587 WriteLineIndent("self.write_uint32(self._model.fbe_offset - 4, fbe_struct_type)");
+
4588 WriteLine();
+
4589 WriteLineIndent("return fbe_struct_size");
+
4590 Indent(-1);
+
4591
+
4592 // Generate struct model final deserialize() methods
+
4593 WriteLine();
+
4594 WriteLineIndent("# Deserialize the struct value");
+
4595 WriteLineIndent("def deserialize(self, value=None):");
+
4596 Indent(1);
+
4597 WriteLineIndent("if value is None:");
+
4598 Indent(1);
+
4599 WriteLineIndent("value = " + *s->name + "()");
+
4600 Indent(-1);
+
4601 WriteLine();
+
4602 WriteLineIndent("assert ((self.buffer.offset + self._model.fbe_offset) <= self.buffer.size), \"Model is broken!\"");
+
4603 WriteLineIndent("if (self.buffer.offset + self._model.fbe_offset) > self.buffer.size:");
+
4604 Indent(1);
+
4605 WriteLineIndent("return " + *s->name + "(), 0");
+
4606 Indent(-1);
+
4607 WriteLine();
+
4608 WriteLineIndent("fbe_struct_size = self.read_uint32(self._model.fbe_offset - 8)");
+
4609 WriteLineIndent("fbe_struct_type = self.read_uint32(self._model.fbe_offset - 4)");
+
4610 WriteLineIndent("assert ((fbe_struct_size > 0) and (fbe_struct_type == self.fbe_type)), \"Model is broken!\"");
+
4611 WriteLineIndent("if (fbe_struct_size <= 0) or (fbe_struct_type != self.fbe_type):");
+
4612 Indent(1);
+
4613 WriteLineIndent("return " + *s->name + "(), 8");
+
4614 Indent(-1);
+
4615 WriteLine();
+
4616 WriteLineIndent("fbe_result = self._model.get(value)");
+
4617 WriteLineIndent("return fbe_result[0], (8 + fbe_result[1])");
+
4618 Indent(-1);
+
4619
+
4620 // Generate struct model final next() method
+
4621 WriteLine();
+
4622 WriteLineIndent("# Move to the next struct value");
+
4623 WriteLineIndent("def next(self, prev):");
+
4624 Indent(1);
+
4625 WriteLineIndent("self._model.fbe_shift(prev)");
+
4626 Indent(-1);
+
4627
+
4628 // Generate struct model final end
+
4629 Indent(-1);
+
4630}
+
4631
+
4632void GeneratorPython::GenerateProtocolVersion(const std::shared_ptr<Package>& p)
+
4633{
+
4634 // Generate protocol version class
+
4635 WriteLine();
+
4636 WriteLine();
+
4637 WriteLineIndent("# Fast Binary Encoding " + *p->name + " protocol version");
+
4638 WriteLineIndent("class ProtocolVersion(object):");
+
4639 Indent(1);
+
4640 WriteLineIndent("# Protocol major version");
+
4641 WriteLineIndent("Major = " + std::to_string(p->version->major));
+
4642 WriteLineIndent("# Protocol minor version");
+
4643 WriteLineIndent("Minor = " + std::to_string(p->version->minor));
+
4644 Indent(-1);
+
4645}
+
4646
+
4647void GeneratorPython::GenerateSender(const std::shared_ptr<Package>& p, bool final)
+
4648{
+
4649 std::string sender = (final ? "FinalSender" : "Sender");
+
4650 std::string model = (final ? "FinalModel" : "Model");
+
4651
+
4652 // Generate sender begin
+
4653 WriteLine();
+
4654 WriteLine();
+
4655 if (final)
+
4656 WriteLineIndent("# Fast Binary Encoding " + *p->name + " final sender");
+
4657 else
+
4658 WriteLineIndent("# Fast Binary Encoding " + *p->name + " sender");
+
4659 WriteLineIndent("class " + sender + "(fbe.Sender):");
+
4660 Indent(1);
+
4661
+
4662 bool messages = false;
+
4663 for (const auto& s : p->body->structs)
+
4664 if (s->message)
+
4665 messages = true;
+
4666
+
4667 // Generate sender __slots__
+
4668 if (p->import || messages)
+
4669 {
+
4670 WriteIndent("__slots__ = ");
+
4671 if (p->import)
+
4672 {
+
4673 for (const auto& import : p->import->imports)
+
4674 Write("\"_" + CppCommon::StringUtils::ToLower(*import) + "_sender\", ");
+
4675 }
+
4676 if (p->body)
+
4677 {
+
4678 for (const auto& s : p->body->structs)
+
4679 if (s->message)
+
4680 Write("\"_" + CppCommon::StringUtils::ToLower(*s->name) + "_model\", ");
+
4681 }
+
4682 WriteLine();
+
4683 WriteLine();
+
4684 }
+
4685
+
4686 // Generate sender constructor
+
4687 WriteLineIndent("def __init__(self, buffer=None):");
+
4688 Indent(1);
+
4689 WriteLineIndent("super().__init__(buffer, " + std::string(final ? "True" : "False") + ")");
+
4690 if (p->import)
+
4691 {
+
4692 for (const auto& import : p->import->imports)
+
4693 WriteLineIndent("self._" + CppCommon::StringUtils::ToLower(*import) + "_sender = " + *import + "." + sender + "(self.buffer)");
+
4694 }
+
4695 if (p->body)
+
4696 {
+
4697 for (const auto& s : p->body->structs)
+
4698 if (s->message)
+
4699 WriteLineIndent("self._" + CppCommon::StringUtils::ToLower(*s->name) + "_model = " + *s->name + model + "(self.buffer)");
+
4700 }
+
4701 Indent(-1);
+
4702
+
4703 // Generate imported senders accessors
+
4704 if (p->import)
+
4705 {
+
4706 WriteLine();
+
4707 WriteLineIndent("# Imported senders");
+
4708 for (const auto& import : p->import->imports)
+
4709 {
+
4710 WriteLine();
+
4711 WriteLineIndent("@property");
+
4712 WriteLineIndent("def " + CppCommon::StringUtils::ToLower(*import) + "_sender(self):");
+
4713 Indent(1);
+
4714 WriteLineIndent("return self._" + CppCommon::StringUtils::ToLower(*import) + "_sender");
+
4715 Indent(-1);
+
4716 }
+
4717 }
+
4718
+
4719 // Generate sender models accessors
+
4720 if (p->body)
+
4721 {
+
4722 WriteLine();
+
4723 WriteLineIndent("# Sender models accessors");
+
4724 for (const auto& s : p->body->structs)
+
4725 {
+
4726 if (s->message)
+
4727 {
+
4728 WriteLine();
+
4729 WriteLineIndent("@property");
+
4730 WriteLineIndent("def " + CppCommon::StringUtils::ToLower(*s->name) + "_model(self):");
+
4731 Indent(1);
+
4732 WriteLineIndent("return self._" + CppCommon::StringUtils::ToLower(*s->name) + "_model");
+
4733 Indent(-1);
+
4734 }
+
4735 }
+
4736 }
+
4737
+
4738 // Generate sender methods
+
4739 WriteLine();
+
4740 WriteLineIndent("# Send methods");
+
4741 WriteLine();
+
4742 WriteLineIndent("def send(self, value):");
+
4743 Indent(1);
+
4744 if (p->body)
+
4745 {
+
4746 for (const auto& s : p->body->structs)
+
4747 {
+
4748 if (s->message)
+
4749 {
+
4750 WriteLineIndent("if isinstance(value, " + *s->name + ") and (value.fbe_type == self." + CppCommon::StringUtils::ToLower(*s->name) + "_model.fbe_type):");
+
4751 Indent(1);
+
4752 WriteLineIndent("return self.send_" + CppCommon::StringUtils::ToLower(*s->name) + "(value)");
+
4753 Indent(-1);
+
4754 }
+
4755 }
+
4756 }
+
4757 if (p->import)
+
4758 {
+
4759 for (const auto& import : p->import->imports)
+
4760 {
+
4761 WriteLineIndent("result = self._" + CppCommon::StringUtils::ToLower(*import) + "_sender.send(value)");
+
4762 WriteLineIndent("if result > 0:");
+
4763 Indent(1);
+
4764 WriteLineIndent("return result");
+
4765 Indent(-1);
+
4766 }
+
4767 }
+
4768 WriteLineIndent("return 0");
+
4769 Indent(-1);
+
4770 if (p->body)
+
4771 {
+
4772 for (const auto& s : p->body->structs)
+
4773 {
+
4774 if (s->message)
+
4775 {
+
4776 WriteLine();
+
4777 WriteLineIndent("def send_" + CppCommon::StringUtils::ToLower(*s->name) + "(self, value):");
+
4778 Indent(1);
+
4779 WriteLineIndent("# Serialize the value into the FBE stream");
+
4780 WriteLineIndent("serialized = self." + CppCommon::StringUtils::ToLower(*s->name) + "_model.serialize(value)");
+
4781 WriteLineIndent("assert (serialized > 0), \"" + *p->name + "." + *s->name + " serialization failed!\"");
+
4782 WriteLineIndent("assert self." + CppCommon::StringUtils::ToLower(*s->name) + "_model.verify(), \"" + *p->name + "." + *s->name + " validation failed!\"");
+
4783 WriteLine();
+
4784 WriteLineIndent("# Log the value");
+
4785 WriteLineIndent("if self.logging:");
+
4786 Indent(1);
+
4787 WriteLineIndent("message = str(value)");
+
4788 WriteLineIndent("self.on_send_log(message)");
+
4789 Indent(-1);
+
4790 WriteLine();
+
4791 WriteLineIndent("# Send the serialized value");
+
4792 WriteLineIndent("return self.send_serialized(serialized)");
+
4793 Indent(-1);
+
4794 }
+
4795 }
+
4796 }
+
4797
+
4798 // Generate sender message handler
+
4799 WriteLine();
+
4800 WriteLineIndent("# Send message handler");
+
4801 WriteLineIndent("def on_send(self, buffer, offset, size):");
+
4802 Indent(1);
+
4803 WriteLineIndent("raise NotImplementedError(\"" + *p->name + ".Sender.on_send() not implemented!\")");
+
4804 Indent(-1);
+
4805
+
4806 // Generate sender end
+
4807 Indent(-1);
+
4808}
+
4809
+
4810void GeneratorPython::GenerateReceiver(const std::shared_ptr<Package>& p, bool final)
+
4811{
+
4812 std::string receiver = (final ? "FinalReceiver" : "Receiver");
+
4813 std::string model = (final ? "FinalModel" : "Model");
+
4814
+
4815 // Generate receiver begin
+
4816 WriteLine();
+
4817 WriteLine();
+
4818 if (final)
+
4819 WriteLineIndent("# Fast Binary Encoding " + *p->name + " final receiver");
+
4820 else
+
4821 WriteLineIndent("# Fast Binary Encoding " + *p->name + " receiver");
+
4822 WriteLineIndent("class " + receiver + "(fbe.Receiver):");
+
4823 Indent(1);
+
4824
+
4825 bool messages = false;
+
4826 for (const auto& s : p->body->structs)
+
4827 if (s->message)
+
4828 messages = true;
+
4829
+
4830 // Generate receiver __slots__
+
4831 if (p->import || messages)
+
4832 {
+
4833 WriteIndent("__slots__ = ");
+
4834 if (p->import)
+
4835 {
+
4836 for (const auto& import : p->import->imports)
+
4837 Write("\"_" + CppCommon::StringUtils::ToLower(*import) + "_receiver\", ");
+
4838 }
+
4839 if (p->body)
+
4840 {
+
4841 for (const auto& s : p->body->structs)
+
4842 {
+
4843 if (s->message)
+
4844 {
+
4845 Write("\"_" + CppCommon::StringUtils::ToLower(*s->name) + "_value\", ");
+
4846 Write("\"_" + CppCommon::StringUtils::ToLower(*s->name) + "_model\", ");
+
4847 }
+
4848 }
+
4849 }
+
4850 WriteLine();
+
4851 WriteLine();
+
4852 }
+
4853
+
4854 // Generate receiver constructor
+
4855 WriteLineIndent("def __init__(self, buffer=None):");
+
4856 Indent(1);
+
4857 WriteLineIndent("super().__init__(buffer, " + std::string(final ? "True" : "False") + ")");
+
4858 if (p->import)
+
4859 {
+
4860 for (const auto& import : p->import->imports)
+
4861 WriteLineIndent("self._" + CppCommon::StringUtils::ToLower(*import) + "_receiver = " + *import + "." + receiver + "(self.buffer)");
+
4862 }
+
4863 if (p->body)
+
4864 {
+
4865 for (const auto& s : p->body->structs)
+
4866 {
+
4867 if (s->message)
+
4868 {
+
4869 WriteLineIndent("self._" + CppCommon::StringUtils::ToLower(*s->name) + "_value = " + *s->name + "()");
+
4870 WriteLineIndent("self._" + CppCommon::StringUtils::ToLower(*s->name) + "_model = " + *s->name + model + "()");
+
4871 }
+
4872 }
+
4873 }
+
4874 Indent(-1);
+
4875
+
4876 // Generate imported receiver accessors
+
4877 if (p->import)
+
4878 {
+
4879 WriteLine();
+
4880 WriteLineIndent("# Imported receivers");
+
4881 for (const auto& import : p->import->imports)
+
4882 {
+
4883 WriteLine();
+
4884 WriteLineIndent("@property");
+
4885 WriteLineIndent("def " + CppCommon::StringUtils::ToLower(*import) + "_receiver(self):");
+
4886 Indent(1);
+
4887 WriteLineIndent("return self._" + CppCommon::StringUtils::ToLower(*import) + "_receiver");
+
4888 Indent(-1);
+
4889 WriteLine();
+
4890 WriteLineIndent("@" + CppCommon::StringUtils::ToLower(*import) + "_receiver.setter");
+
4891 WriteLineIndent("def " + CppCommon::StringUtils::ToLower(*import) + "_receiver(self, receiver):");
+
4892 Indent(1);
+
4893 WriteLineIndent("self._" + CppCommon::StringUtils::ToLower(*import) + "_receiver = receiver");
+
4894 Indent(-1);
+
4895 }
+
4896 }
+
4897
+
4898 // Generate receiver handlers
+
4899 if (p->body)
+
4900 {
+
4901 WriteLine();
+
4902 WriteLineIndent("# Receive handlers");
+
4903 for (const auto& s : p->body->structs)
+
4904 {
+
4905 if (s->message)
+
4906 {
+
4907 WriteLine();
+
4908 WriteLineIndent("def on_receive_" + CppCommon::StringUtils::ToLower(*s->name) + "(self, value):");
+
4909 Indent(1);
+
4910 WriteLineIndent("pass");
+
4911 Indent(-1);
+
4912 }
+
4913 }
+
4914 WriteLine();
+
4915 }
+
4916
+
4917 // Generate receiver message handler
+
4918 WriteLineIndent("def on_receive(self, type, buffer, offset, size):");
+
4919 Indent(1);
+
4920 if (p->body)
+
4921 {
+
4922 for (const auto& s : p->body->structs)
+
4923 {
+
4924 if (s->message)
+
4925 {
+
4926 WriteLine();
+
4927 WriteLineIndent("if type == " + *s->name + model + ".TYPE:");
+
4928 Indent(1);
+
4929 WriteLineIndent("# Deserialize the value from the FBE stream");
+
4930 WriteLineIndent("self._" + CppCommon::StringUtils::ToLower(*s->name) + "_model.attach_buffer(buffer, offset)");
+
4931 WriteLineIndent("assert self._" + CppCommon::StringUtils::ToLower(*s->name) + "_model.verify(), \"" + *p->name + "." + *s->name + " validation failed!\"");
+
4932 WriteLineIndent("(_, deserialized) = self._" + CppCommon::StringUtils::ToLower(*s->name) + "_model.deserialize(self._" + CppCommon::StringUtils::ToLower(*s->name) + "_value)");
+
4933 WriteLineIndent("assert (deserialized > 0), \"" + *p->name + "." + *s->name + " deserialization failed!\"");
+
4934 WriteLine();
+
4935 WriteLineIndent("# Log the value");
+
4936 WriteLineIndent("if self.logging:");
+
4937 Indent(1);
+
4938 WriteLineIndent("message = str(self._" + CppCommon::StringUtils::ToLower(*s->name) + "_value)");
+
4939 WriteLineIndent("self.on_receive_log(message)");
+
4940 Indent(-1);
+
4941 WriteLine();
+
4942 WriteLineIndent("# Call receive handler with deserialized value");
+
4943 WriteLineIndent("self.on_receive_" + CppCommon::StringUtils::ToLower(*s->name) + "(self._" + CppCommon::StringUtils::ToLower(*s->name) + "_value)");
+
4944 WriteLineIndent("return True");
+
4945 Indent(-1);
+
4946 }
+
4947 }
+
4948 }
+
4949 if (p->import)
+
4950 {
+
4951 WriteLine();
+
4952 for (const auto& import : p->import->imports)
+
4953 {
+
4954 WriteLineIndent("if (self." + CppCommon::StringUtils::ToLower(*import) + "_receiver is not None) and self." + CppCommon::StringUtils::ToLower(*import) + "_receiver.on_receive(type, buffer, offset, size):");
+
4955 Indent(1);
+
4956 WriteLineIndent("return True");
+
4957 Indent(-1);
+
4958 }
+
4959 }
+
4960 WriteLine();
+
4961 WriteLineIndent("return False");
+
4962 Indent(-1);
+
4963
+
4964 // Generate receiver end
+
4965 Indent(-1);
+
4966}
+
4967
+
4968void GeneratorPython::GenerateProxy(const std::shared_ptr<Package>& p, bool final)
+
4969{
+
4970 std::string proxy = (final ? "FinalProxy" : "Proxy");
+
4971 std::string model = (final ? "FinalModel" : "Model");
+
4972
+
4973 // Generate proxy begin
+
4974 WriteLine();
+
4975 WriteLine();
+
4976 if (final)
+
4977 WriteLineIndent("# Fast Binary Encoding " + *p->name + " final proxy");
+
4978 else
+
4979 WriteLineIndent("# Fast Binary Encoding " + *p->name + " proxy");
+
4980 WriteLineIndent("class " + proxy + "(fbe.Receiver):");
+
4981 Indent(1);
+
4982
+
4983 bool messages = false;
+
4984 for (const auto& s : p->body->structs)
+
4985 if (s->message)
+
4986 messages = true;
+
4987
+
4988 // Generate proxy __slots__
+
4989 if (p->import || messages)
+
4990 {
+
4991 WriteIndent("__slots__ = ");
+
4992 if (p->import)
+
4993 {
+
4994 for (const auto& import : p->import->imports)
+
4995 Write("\"_" + CppCommon::StringUtils::ToLower(*import) + "_proxy\", ");
+
4996 }
+
4997 if (p->body)
+
4998 {
+
4999 for (const auto& s : p->body->structs)
+
5000 if (s->message)
+
5001 Write("\"_" + CppCommon::StringUtils::ToLower(*s->name) + "_model\", ");
+
5002 }
+
5003 WriteLine();
+
5004 WriteLine();
+
5005 }
+
5006
+
5007 // Generate proxy constructor
+
5008 WriteLineIndent("def __init__(self, buffer=None):");
+
5009 Indent(1);
+
5010 WriteLineIndent("super().__init__(buffer, " + std::string(final ? "True" : "False") + ")");
+
5011 if (p->import)
+
5012 {
+
5013 for (const auto& import : p->import->imports)
+
5014 WriteLineIndent("self._" + CppCommon::StringUtils::ToLower(*import) + "_proxy = " + *import + "." + proxy + "(self.buffer)");
+
5015 }
+
5016 if (p->body)
+
5017 {
+
5018 for (const auto& s : p->body->structs)
+
5019 if (s->message)
+
5020 WriteLineIndent("self._" + CppCommon::StringUtils::ToLower(*s->name) + "_model = " + *s->name + model + "()");
+
5021 }
+
5022 Indent(-1);
+
5023
+
5024 // Generate imported proxy accessors
+
5025 if (p->import)
+
5026 {
+
5027 WriteLine();
+
5028 WriteLineIndent("# Imported proxy");
+
5029 for (const auto& import : p->import->imports)
+
5030 {
+
5031 WriteLine();
+
5032 WriteLineIndent("@property");
+
5033 WriteLineIndent("def " + CppCommon::StringUtils::ToLower(*import) + "_proxy(self):");
+
5034 Indent(1);
+
5035 WriteLineIndent("return self._" + CppCommon::StringUtils::ToLower(*import) + "_proxy");
+
5036 Indent(-1);
+
5037 WriteLine();
+
5038 WriteLineIndent("@" + CppCommon::StringUtils::ToLower(*import) + "_proxy.setter");
+
5039 WriteLineIndent("def " + CppCommon::StringUtils::ToLower(*import) + "_proxy(self, proxy):");
+
5040 Indent(1);
+
5041 WriteLineIndent("self._" + CppCommon::StringUtils::ToLower(*import) + "_proxy = proxy");
+
5042 Indent(-1);
+
5043 }
+
5044 }
+
5045
+
5046 // Generate proxy handlers
+
5047 if (p->body)
+
5048 {
+
5049 WriteLine();
+
5050 WriteLineIndent("# Receive handlers");
+
5051 for (const auto& s : p->body->structs)
+
5052 {
+
5053 if (s->message)
+
5054 {
+
5055 WriteLine();
+
5056 WriteLineIndent("def on_proxy_" + CppCommon::StringUtils::ToLower(*s->name) + "(self, model, type, buffer, offset, size):");
+
5057 Indent(1);
+
5058 WriteLineIndent("pass");
+
5059 Indent(-1);
+
5060 }
+
5061 }
+
5062 WriteLine();
+
5063 }
+
5064
+
5065 // Generate proxy message handler
+
5066 WriteLineIndent("def on_receive(self, type, buffer, offset, size):");
+
5067 Indent(1);
+
5068 if (p->body)
+
5069 {
+
5070 for (const auto& s : p->body->structs)
+
5071 {
+
5072 if (s->message)
+
5073 {
+
5074 WriteLine();
+
5075 WriteLineIndent("if type == " + *s->name + model + ".TYPE:");
+
5076 Indent(1);
+
5077 WriteLineIndent("# Attach the FBE stream to the proxy model");
+
5078 WriteLineIndent("self._" + CppCommon::StringUtils::ToLower(*s->name) + "_model.attach_buffer(buffer, offset)");
+
5079 WriteLineIndent("assert self._" + CppCommon::StringUtils::ToLower(*s->name) + "_model.verify(), \"" + *p->name + "." + *s->name + " validation failed!\"");
+
5080 WriteLine();
+
5081 WriteLineIndent("fbe_begin = self._" + CppCommon::StringUtils::ToLower(*s->name) + "_model.model.get_begin()");
+
5082 WriteLineIndent("if fbe_begin == 0:");
+
5083 Indent(1);
+
5084 WriteLineIndent("return False");
+
5085 Indent(-1);
+
5086 WriteLineIndent("# Call proxy handler");
+
5087 WriteLineIndent("self.on_proxy_" + CppCommon::StringUtils::ToLower(*s->name) + "(self._" + CppCommon::StringUtils::ToLower(*s->name) + "_model, type, buffer, offset, size)");
+
5088 WriteLineIndent("self._" + CppCommon::StringUtils::ToLower(*s->name) + "_model.model.get_end(fbe_begin)");
+
5089 WriteLineIndent("return True");
+
5090 Indent(-1);
+
5091 }
+
5092 }
+
5093 }
+
5094 if (p->import)
+
5095 {
+
5096 WriteLine();
+
5097 for (const auto& import : p->import->imports)
+
5098 {
+
5099 WriteLineIndent("if (self." + CppCommon::StringUtils::ToLower(*import) + "_proxy is not None) and self." + CppCommon::StringUtils::ToLower(*import) + "_proxy.on_receive(type, buffer, offset, size):");
+
5100 Indent(1);
+
5101 WriteLineIndent("return True");
+
5102 Indent(-1);
+
5103 }
+
5104 }
+
5105 WriteLine();
+
5106 WriteLineIndent("return False");
+
5107 Indent(-1);
+
5108
+
5109 // Generate proxy end
+
5110 Indent(-1);
+
5111}
+
5112
+
5113bool GeneratorPython::IsPrimitiveType(const std::string& type)
+
5114{
+
5115 return ((type == "bool") || (type == "byte") ||
+
5116 (type == "char") || (type == "wchar") ||
+
5117 (type == "int8") || (type == "uint8") ||
+
5118 (type == "int16") || (type == "uint16") ||
+
5119 (type == "int32") || (type == "uint32") ||
+
5120 (type == "int64") || (type == "uint64") ||
+
5121 (type == "float") || (type == "double"));
+
5122}
+
5123
+
5124bool GeneratorPython::IsPythonType(const std::string& type)
+
5125{
+
5126 return IsPrimitiveType(type) || (type == "bytes") || (type == "decimal") || (type == "string") || (type == "timestamp") || (type == "uuid");
+
5127}
+
5128
+
5129std::string GeneratorPython::ConvertEnumSize(const std::string& type)
+
5130{
+
5131 if (type == "byte")
+
5132 return "1";
+
5133 else if (type == "char")
+
5134 return "1";
+
5135 else if (type == "wchar")
+
5136 return "4";
+
5137 else if (type == "int8")
+
5138 return "1";
+
5139 else if (type == "uint8")
+
5140 return "1";
+
5141 else if (type == "int16")
+
5142 return "2";
+
5143 else if (type == "uint16")
+
5144 return "2";
+
5145 else if (type == "int32")
+
5146 return "4";
+
5147 else if (type == "uint32")
+
5148 return "4";
+
5149 else if (type == "int64")
+
5150 return "8";
+
5151 else if (type == "uint64")
+
5152 return "8";
+
5153
+
5154 yyerror("Unsupported enum base type - " + type);
+
5155 return "";
+
5156}
+
5157
+
5158std::string GeneratorPython::ConvertEnumType(const std::string& type)
+
5159{
+
5160 if (type == "byte")
+
5161 return "byte";
+
5162 else if (type == "char")
+
5163 return "uint8";
+
5164 else if (type == "wchar")
+
5165 return "uint32";
+
5166 else if (type == "int8")
+
5167 return "int8";
+
5168 else if (type == "uint8")
+
5169 return "uint8";
+
5170 else if (type == "int16")
+
5171 return "int16";
+
5172 else if (type == "uint16")
+
5173 return "uint16";
+
5174 else if (type == "int32")
+
5175 return "int32";
+
5176 else if (type == "uint32")
+
5177 return "uint32";
+
5178 else if (type == "int64")
+
5179 return "int64";
+
5180 else if (type == "uint64")
+
5181 return "uint64";
+
5182
+
5183 yyerror("Unsupported enum base type - " + type);
+
5184 return "";
+
5185}
+
5186
+
5187std::string GeneratorPython::ConvertEnumConstant(const std::string& type, const std::string& value)
+
5188{
+
5189 if (((type == "char") || (type == "wchar")) && CppCommon::StringUtils::StartsWith(value, "'"))
+
5190 return "ord(" + value + ")";
+
5191 else if (type.empty())
+
5192 return value;
+
5193
+
5194 return "int(" + value + ")";
+
5195}
+
5196
+
5197std::string GeneratorPython::ConvertTypeName(const std::string& type, bool optional)
+
5198{
+
5199 if (type == "bool")
+
5200 return "bool";
+
5201 else if ((type == "byte") || (type == "int8") || (type == "uint8") || (type == "int16") || (type == "uint16") || (type == "int32") || (type == "uint32") || (type == "int64") || (type == "uint64") || (type == "timestamp"))
+
5202 return "int";
+
5203 else if (type == "bytes")
+
5204 return "bytearray";
+
5205 else if ((type == "float") || (type == "double"))
+
5206 return "float";
+
5207 else if (type == "decimal")
+
5208 return "decimal.Decimal";
+
5209 else if (type == "string")
+
5210 return "str";
+
5211 else if (type == "uuid")
+
5212 return "uuid.UUID";
+
5213
+
5214 return type;
+
5215}
+
5216
+
5217std::string GeneratorPython::ConvertTypeName(const StructField& field)
+
5218{
+
5219 if (field.array)
+
5220 return "list";
+
5221 else if (field.vector)
+
5222 return "list";
+
5223 else if (field.list)
+
5224 return "list";
+
5225 else if (field.set)
+
5226 return "set";
+
5227 else if (field.map)
+
5228 return "dict";
+
5229 else if (field.hash)
+
5230 return "dict";
+
5231
+
5232 return ConvertTypeName(*field.type, field.optional);
+
5233}
+
5234
+
5235std::string GeneratorPython::ConvertTypeFieldName(const std::string& type, bool final)
+
5236{
+
5237 std::string modelType = final ? "Final" : "Field";
+
5238
+
5239 if (type == "bool")
+
5240 return "fbe." + modelType + "ModelBool";
+
5241 else if (type == "byte")
+
5242 return "fbe." + modelType + "ModelByte";
+
5243 else if (type == "bytes")
+
5244 return "fbe." + modelType + "ModelBytes";
+
5245 else if (type == "char")
+
5246 return "fbe." + modelType + "ModelChar";
+
5247 else if (type == "wchar")
+
5248 return "fbe." + modelType + "ModelWChar";
+
5249 else if (type == "int8")
+
5250 return "fbe." + modelType + "ModelInt8";
+
5251 else if (type == "uint8")
+
5252 return "fbe." + modelType + "ModelUInt8";
+
5253 else if (type == "int16")
+
5254 return "fbe." + modelType + "ModelInt16";
+
5255 else if (type == "uint16")
+
5256 return "fbe." + modelType + "ModelUInt16";
+
5257 else if (type == "int32")
+
5258 return "fbe." + modelType + "ModelInt32";
+
5259 else if (type == "uint32")
+
5260 return "fbe." + modelType + "ModelUInt32";
+
5261 else if (type == "int64")
+
5262 return "fbe." + modelType + "ModelInt64";
+
5263 else if (type == "uint64")
+
5264 return "fbe." + modelType + "ModelUInt64";
+
5265 else if (type == "float")
+
5266 return "fbe." + modelType + "ModelFloat";
+
5267 else if (type == "double")
+
5268 return "fbe." + modelType + "ModelDouble";
+
5269 else if (type == "decimal")
+
5270 return "fbe." + modelType + "ModelDecimal";
+
5271 else if (type == "timestamp")
+
5272 return "fbe." + modelType + "ModelTimestamp";
+
5273 else if (type == "string")
+
5274 return "fbe." + modelType + "ModelString";
+
5275 else if (type == "uuid")
+
5276 return "fbe." + modelType + "ModelUUID";
+
5277
+
5278 std::string ns = "";
+
5279 std::string t = type;
+
5280
+
5281 size_t pos = type.find_last_of('.');
+
5282 if (pos != std::string::npos)
+
5283 {
+
5284 ns.assign(type, 0, pos + 1);
+
5285 t.assign(type, pos + 1, type.size() - pos);
+
5286 }
+
5287
+
5288 return ns + modelType + "Model" + ConvertTypeName(t, false);
+
5289}
+
5290
+
5291std::string GeneratorPython::ConvertTypeFieldInitialization(const std::string& type, bool optional, const std::string& offset, bool final)
+
5292{
+
5293 std::string modelType = final ? "Final" : "Field";
+
5294
+
5295 if (optional)
+
5296 return "fbe." + modelType + "ModelOptional(" + ConvertTypeFieldInitialization(type, false, offset, final)+ ", buffer, " + offset + ")";
+
5297 else
+
5298 return ConvertTypeFieldName(type, final) + "(buffer, " + offset + ")";
+
5299}
+
5300
+
5301std::string GeneratorPython::ConvertTypeFieldInitialization(const StructField& field, const std::string& offset, bool final)
+
5302{
+
5303 std::string modelType = final ? "Final" : "Field";
+
5304
+
5305 if (field.array)
+
5306 return "fbe." + modelType + "ModelArray(" + ConvertTypeFieldInitialization(*field.type, field.optional, offset, final) + ", buffer, " + offset + ", " + std::to_string(field.N) + ")";
+
5307 else if (field.vector || field.list)
+
5308 return "fbe." + modelType + "ModelVector(" + ConvertTypeFieldInitialization(*field.type, field.optional, offset, final) + ", buffer, " + offset + ")";
+
5309 else if (field.set)
+
5310 return "fbe." + modelType + "ModelSet(" + ConvertTypeFieldInitialization(*field.type, field.optional, offset, final) + ", buffer, " + offset + ")";
+
5311 else if (field.map || field.hash)
+
5312 return "fbe." + modelType + "ModelMap(" + ConvertTypeFieldInitialization(*field.key, false, offset, final) + ", " + ConvertTypeFieldInitialization(*field.type, field.optional, offset, final) + ", buffer, " + offset + ")";
+
5313 else
+
5314 return ConvertTypeFieldInitialization(*field.type, field.optional, offset, final);
+
5315}
+
5316
+
5317std::string GeneratorPython::ConvertConstant(const std::string& type, const std::string& value, bool optional)
+
5318{
+
5319 if (value == "true")
+
5320 return "True";
+
5321 else if (value == "false")
+
5322 return "False";
+
5323 else if (value == "null")
+
5324 return "None";
+
5325 else if (value == "min")
+
5326 {
+
5327 if ((type == "byte") || (type == "uint8") || (type == "uint16") || (type == "uint32") || (type == "uint64"))
+
5328 return "0";
+
5329 else if (type == "int8")
+
5330 return "-128";
+
5331 else if (type == "int16")
+
5332 return "-32768";
+
5333 else if (type == "int32")
+
5334 return "-2147483648";
+
5335 else if (type == "int64")
+
5336 return "-9223372036854775808";
+
5337
+
5338 yyerror("Unsupported type " + type + " for 'min' constant");
+
5339 return "";
+
5340 }
+
5341 else if (value == "max")
+
5342 {
+
5343 if (type == "byte")
+
5344 return "255";
+
5345 else if (type == "int8")
+
5346 return "127";
+
5347 else if (type == "uint8")
+
5348 return "255";
+
5349 else if (type == "int16")
+
5350 return "32767";
+
5351 else if (type == "uint16")
+
5352 return "65535";
+
5353 else if (type == "int32")
+
5354 return "2147483647";
+
5355 else if (type == "uint32")
+
5356 return "4294967295";
+
5357 else if (type == "int64")
+
5358 return "9223372036854775807";
+
5359 else if (type == "uint64")
+
5360 return "18446744073709551615";
+
5361
+
5362 yyerror("Unsupported type " + type + " for 'max' constant");
+
5363 return "";
+
5364 }
+
5365 else if (value == "epoch")
+
5366 return "fbe.epoch()";
+
5367 else if (value == "utc")
+
5368 return "fbe.utc()";
+
5369 else if (value == "uuid0")
+
5370 return "uuid.UUID(int=0)";
+
5371 else if (value == "uuid1")
+
5372 return "uuid.uuid1()";
+
5373 else if (value == "uuid4")
+
5374 return "uuid.uuid4()";
+
5375
+
5376 if (type == "bool")
+
5377 return "bool(" + value + ")";
+
5378 else if (((type == "char") || (type == "wchar")) && !CppCommon::StringUtils::StartsWith(value, "'"))
+
5379 return "chr(" + value + ")";
+
5380 else if ((type == "byte") || (type == "int8") || (type == "uint8") || (type == "int16") || (type == "uint16") || (type == "int32") || (type == "uint32") || (type == "int64") || (type == "uint64") || (type == "timestamp"))
+
5381 return "int(" + value + ")";
+
5382 else if ((type == "float") || (type == "double"))
+
5383 return "float(" + value + ")";
+
5384 else if (type == "decimal")
+
5385 return "decimal.Decimal(\"" + value + "\")";
+
5386 else if (type == "uuid")
+
5387 return "uuid.UUID(" + value + ")";
+
5388
+
5389 return value;
+
5390}
+
5391
+
5392std::string GeneratorPython::ConvertDefaultOrNone(const std::string& type, bool optional)
+
5393{
+
5394 if (optional)
+
5395 return "None";
+
5396
+
5397 if (type == "bool")
+
5398 return "False";
+
5399 else if (type == "byte")
+
5400 return "0";
+
5401 else if (type == "bytes")
+
5402 return "None";
+
5403 else if ((type == "char") || (type == "wchar"))
+
5404 return "'\\0'";
+
5405 else if ((type == "int8") || (type == "uint8") || (type == "int16") || (type == "uint16") || (type == "int32") || (type == "uint32") || (type == "int64") || (type == "uint64"))
+
5406 return "0";
+
5407 else if ((type == "float") || (type == "double"))
+
5408 return "0.0";
+
5409 else if (type == "decimal")
+
5410 return "decimal.Decimal(0)";
+
5411 else if (type == "timestamp")
+
5412 return "fbe.epoch()";
+
5413 else if (type == "string")
+
5414 return "\"\"";
+
5415 else if (type == "uuid")
+
5416 return "uuid.UUID(int=0)";
+
5417
+
5418 return "None";
+
5419}
+
5420
+
5421std::string GeneratorPython::ConvertDefault(const std::string& type, bool optional)
+
5422{
+
5423 if (optional)
+
5424 return "None";
+
5425
+
5426 if (type == "bool")
+
5427 return "False";
+
5428 else if (type == "byte")
+
5429 return "0";
+
5430 else if (type == "bytes")
+
5431 return "bytearray()";
+
5432 else if ((type == "char") || (type == "wchar"))
+
5433 return "'\\0'";
+
5434 else if ((type == "int8") || (type == "uint8") || (type == "int16") || (type == "uint16") || (type == "int32") || (type == "uint32") || (type == "int64") || (type == "uint64"))
+
5435 return "0";
+
5436 else if ((type == "float") || (type == "double"))
+
5437 return "0.0";
+
5438 else if (type == "decimal")
+
5439 return "decimal.Decimal(0)";
+
5440 else if (type == "timestamp")
+
5441 return "fbe.epoch()";
+
5442 else if (type == "string")
+
5443 return "\"\"";
+
5444 else if (type == "uuid")
+
5445 return "uuid.UUID(int=0)";
+
5446
+
5447 return type + "()";
+
5448}
+
5449
+
5450std::string GeneratorPython::ConvertDefault(const StructField& field)
+
5451{
+
5452 if (field.value)
+
5453 return ConvertConstant(*field.type, *field.value, field.optional);
+
5454
+
5455 if (field.array)
+
5456 return "[" + ConvertDefault(*field.type, field.optional) + "]*" + std::to_string(field.N);
+
5457 else if (field.vector || field.list || field.set || field.map || field.hash)
+
5458 return ConvertTypeName(field) + "()";
+
5459
+
5460 return ConvertDefault(*field.type, field.optional);
+
5461}
+
5462
+
5463void GeneratorPython::WriteOutputStreamType(const std::string& type, const std::string& name, bool optional)
+
5464{
+
5465 if (type == "bool")
+
5466 WriteLineIndent("sb.append(\"true\" if " + name + " else \"false\")");
+
5467 else if (type == "bytes")
+
5468 WriteLineIndent("sb.append(\"bytes[\" + str(len(" + name + ")) + \"]\")");
+
5469 else if ((type == "char") || (type == "wchar"))
+
5470 WriteLineIndent("sb.append(\"'\" + str(" + name + ") + \"'\")");
+
5471 else if ((type == "string") || (type == "uuid"))
+
5472 WriteLineIndent("sb.append(\"\\\"\" + str(" + name + ") + \"\\\"\")");
+
5473 else
+
5474 WriteLineIndent("sb.append(str(" + name + "))");
+
5475}
+
5476
+
5477void GeneratorPython::WriteOutputStreamValue(const std::string& type, const std::string& name, bool optional, bool separate)
+
5478{
+
5479 if (optional || (type == "bytes") || (type == "decimal") || (type == "string") || (type == "timestamp") || (type == "uuid"))
+
5480 {
+
5481 WriteLineIndent("if " + name + " is not None:");
+
5482 Indent(1);
+
5483 if (separate)
+
5484 WriteLineIndent("sb.append(\"\" if first else \",\")");
+
5485 WriteOutputStreamType(type, name, true);
+
5486 Indent(-1);
+
5487 WriteLineIndent("else:");
+
5488 Indent(1);
+
5489 if (separate)
+
5490 WriteLineIndent("sb.append(\"\" if first else \",\")");
+
5491 WriteLineIndent("sb.append(\"null\")");
+
5492 Indent(-1);
+
5493 }
+
5494 else
+
5495 {
+
5496 if (separate)
+
5497 WriteLineIndent("sb.append(\"\" if first else \",\")");
+
5498 WriteOutputStreamType(type, name, false);
+
5499 }
+
5500}
+
5501
+
5502} // namespace FBE
+
void WriteBegin()
Definition generator.inl:24
+
void Store(const CppCommon::Path &filename)
Definition generator.cpp:17
+
static std::string EndLine()
Definition generator.inl:68
+
std::string _input
Definition generator.h:25
+ +
std::string _output
Definition generator.h:26
+
void WriteLineIndent(const std::string &str)
Definition generator.inl:58
+
void Write(const std::string &str)
Definition generator.inl:29
+ +
void Indent(int count)
Definition generator.inl:19
+
void WriteIndent()
Definition generator.inl:34
+
bool Proto() const noexcept
+
bool JSON() const noexcept
+
bool Final() const noexcept
+
void Generate(const std::shared_ptr< Package > &package) override
+
int yyerror(const char *msg)
Definition fbe.l:163
+
Fast binary encoding Python generator definition.
+
Definition fbe.h:33
+
const char version[]
Definition version.h:15
+ +
+ + +
+ + diff --git a/documents/html/generator__python_8h.html b/documents/html/generator__python_8h.html new file mode 100644 index 000000000..7b51d7ad9 --- /dev/null +++ b/documents/html/generator__python_8h.html @@ -0,0 +1,114 @@ + + + + + + + +FastBinaryEncoding: include/generator_python.h File Reference + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+ +
generator_python.h File Reference
+
+
+ +

Fast binary encoding Python generator definition. +More...

+
#include "generator.h"
+
+

Go to the source code of this file.

+ + + +

+Classes

class  FBE::GeneratorPython
+ + +

+Namespaces

namespace  FBE
+

Detailed Description

+

Fast binary encoding Python generator definition.

+
Author
Ivan Shynkarenka
+
Date
24.04.2018
+ + +

Definition in file generator_python.h.

+
+ + +
+ + diff --git a/documents/html/generator__python_8h_source.html b/documents/html/generator__python_8h_source.html new file mode 100644 index 000000000..6ca77787b --- /dev/null +++ b/documents/html/generator__python_8h_source.html @@ -0,0 +1,208 @@ + + + + + + + +FastBinaryEncoding: include/generator_python.h Source File + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+
generator_python.h
+
+
+Go to the documentation of this file.
1
+
8
+
9#ifndef GENERATOR_PYTHON_H
+
10#define GENERATOR_PYTHON_H
+
11
+
12#include "generator.h"
+
13
+
14namespace FBE {
+
15
+
+ +
17{
+
18public:
+ +
20
+
21 // Final protocol code generation
+
22 bool Final() const noexcept { return _final; }
+
23 GeneratorPython& Final(bool final) noexcept { _final = final; return *this; }
+
24
+
25 // JSON protocol code generation
+
26 bool JSON() const noexcept { return _json; }
+
27 GeneratorPython& JSON(bool json) noexcept { _json = json; return *this; }
+
28
+
29 // Sender/Receiver protocol code generation
+
30 bool Proto() const noexcept { return _proto; }
+
31 GeneratorPython& Proto(bool proto) noexcept { _proto = proto; return *this; }
+
32
+
33 void Generate(const std::shared_ptr<Package>& package) override;
+
34
+
35private:
+
36 bool _final{false};
+
37 bool _json{false};
+
38 bool _proto{false};
+
39
+
40 void GenerateHeader(const std::string& source);
+
41 void GenerateFooter();
+
42 void GenerateInit(const CppCommon::Path& path);
+
43 void GenerateFBE(const CppCommon::Path& path);
+
44 void GenerateFBEWriteBuffer();
+
45 void GenerateFBEReadBuffer();
+
46 void GenerateFBEModel();
+
47 void GenerateFBEFieldModelBase();
+
48 void GenerateFBEFieldModel();
+
49 void GenerateFBEFieldModel(const std::string& name, const std::string& type, const std::string& size, const std::string& defaults);
+
50 void GenerateFBEFieldModelDecimal();
+
51 void GenerateFBEFieldModelBytes();
+
52 void GenerateFBEFieldModelString();
+
53 void GenerateFBEFieldModelOptional();
+
54 void GenerateFBEFieldModelArray();
+
55 void GenerateFBEFieldModelVector();
+
56 void GenerateFBEFieldModelSet();
+
57 void GenerateFBEFieldModelMap();
+
58 void GenerateFBEFinalModel();
+
59 void GenerateFBEFinalModel(const std::string& name, const std::string& type, const std::string& size, const std::string& defaults);
+
60 void GenerateFBEFinalModelDecimal();
+
61 void GenerateFBEFinalModelBytes();
+
62 void GenerateFBEFinalModelString();
+
63 void GenerateFBEFinalModelOptional();
+
64 void GenerateFBEFinalModelArray();
+
65 void GenerateFBEFinalModelVector();
+
66 void GenerateFBEFinalModelSet();
+
67 void GenerateFBEFinalModelMap();
+
68 void GenerateFBESender();
+
69 void GenerateFBEReceiver();
+
70 void GenerateImports(const std::shared_ptr<Package>& p);
+
71
+
72 void GeneratePackage(const std::shared_ptr<Package>& p);
+
73 void GenerateEnum(const std::shared_ptr<EnumType>& e);
+
74 void GenerateEnumFieldModel(const std::shared_ptr<EnumType>& e);
+
75 void GenerateEnumFinalModel(const std::shared_ptr<EnumType>& e);
+
76 void GenerateFlags(const std::shared_ptr<FlagsType>& f);
+
77 void GenerateFlagsFieldModel(const std::shared_ptr<FlagsType>& f);
+
78 void GenerateFlagsFinalModel(const std::shared_ptr<FlagsType>& f);
+
79 void GenerateStruct(const std::shared_ptr<StructType>& s);
+
80 void GenerateStructFieldModel(const std::shared_ptr<StructType>& s);
+
81 void GenerateStructModel(const std::shared_ptr<StructType>& s);
+
82 void GenerateStructFinalModel(const std::shared_ptr<StructType>& s);
+
83 void GenerateStructModelFinal(const std::shared_ptr<StructType>& s);
+
84 void GenerateProtocolVersion(const std::shared_ptr<Package>& p);
+
85 void GenerateSender(const std::shared_ptr<Package>& p, bool final);
+
86 void GenerateReceiver(const std::shared_ptr<Package>& p, bool final);
+
87 void GenerateProxy(const std::shared_ptr<Package>& p, bool final);
+
88
+
89 bool IsPrimitiveType(const std::string& type);
+
90 bool IsPythonType(const std::string& type);
+
91
+
92 std::string ConvertEnumSize(const std::string& type);
+
93 std::string ConvertEnumType(const std::string& type);
+
94 std::string ConvertEnumConstant(const std::string& type, const std::string& value);
+
95 std::string ConvertTypeName(const std::string& type, bool optional);
+
96 std::string ConvertTypeName(const StructField& field);
+
97 std::string ConvertTypeFieldName(const std::string& type, bool final);
+
98 std::string ConvertTypeFieldInitialization(const std::string& type, bool optional, const std::string& offset, bool final);
+
99 std::string ConvertTypeFieldInitialization(const StructField& field, const std::string& offset, bool final);
+
100 std::string ConvertConstant(const std::string& type, const std::string& value, bool optional);
+
101 std::string ConvertDefaultOrNone(const std::string& type, bool optional);
+
102 std::string ConvertDefault(const std::string& type, bool optional);
+
103 std::string ConvertDefault(const StructField& field);
+
104
+
105 void WriteOutputStreamType(const std::string& type, const std::string& name, bool optional);
+
106 void WriteOutputStreamValue(const std::string& type, const std::string& name, bool optional, bool separate);
+
107};
+
+
108
+
109} // namespace FBE
+
110
+
111#endif // GENERATOR_PYTHON_H
+
Generator(const std::string &input, const std::string &output, int indent, char space)
Definition generator.inl:11
+ +
GeneratorPython & Proto(bool proto) noexcept
+
bool Proto() const noexcept
+
bool JSON() const noexcept
+
GeneratorPython & JSON(bool json) noexcept
+
GeneratorPython & Final(bool final) noexcept
+
bool Final() const noexcept
+
void Generate(const std::shared_ptr< Package > &package) override
+
Generator(const std::string &input, const std::string &output, int indent, char space)
Definition generator.inl:11
+
Fast binary encoding generator definition.
+
Definition fbe.h:33
+
+ + +
+ + diff --git a/documents/html/generator__ruby_8cpp.html b/documents/html/generator__ruby_8cpp.html new file mode 100644 index 000000000..552f93284 --- /dev/null +++ b/documents/html/generator__ruby_8cpp.html @@ -0,0 +1,109 @@ + + + + + + + +FastBinaryEncoding: source/generator_ruby.cpp File Reference + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+ +
generator_ruby.cpp File Reference
+
+
+ +

Fast binary encoding Ruby generator implementation. +More...

+
#include "generator_ruby.h"
+
+

Go to the source code of this file.

+ + + +

+Namespaces

namespace  FBE
+

Detailed Description

+

Fast binary encoding Ruby generator implementation.

+
Author
Ivan Shynkarenka
+
Date
15.10.2018
+ + +

Definition in file generator_ruby.cpp.

+
+ + +
+ + diff --git a/documents/html/generator__ruby_8cpp_source.html b/documents/html/generator__ruby_8cpp_source.html new file mode 100644 index 000000000..e3bc170c5 --- /dev/null +++ b/documents/html/generator__ruby_8cpp_source.html @@ -0,0 +1,6435 @@ + + + + + + + +FastBinaryEncoding: source/generator_ruby.cpp Source File + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+
generator_ruby.cpp
+
+
+Go to the documentation of this file.
1
+
8
+
9#include "generator_ruby.h"
+
10
+
11namespace FBE {
+
12
+
+
13void GeneratorRuby::Generate(const std::shared_ptr<Package>& package)
+
14{
+
15 GeneratePackage(package);
+
16}
+
+
17
+
18void GeneratorRuby::GenerateHeader(const std::string& source)
+
19{
+
20 std::string code = R"CODE(#------------------------------------------------------------------------------
+
21# Automatically generated by the Fast Binary Encoding compiler, do not modify!
+
22# https://github.com/chronoxor/FastBinaryEncoding
+
23# Source: _INPUT_
+
24# FBE version: _VERSION_
+
25#------------------------------------------------------------------------------
+
26
+
27# rubocop:disable Lint/MissingCopEnableDirective
+
28# rubocop:disable Lint/UnneededCopDisableDirective
+
29# rubocop:disable Metrics/AbcSize
+
30# rubocop:disable Metrics/ClassLength
+
31# rubocop:disable Metrics/CyclomaticComplexity
+
32# rubocop:disable Metrics/LineLength
+
33# rubocop:disable Metrics/MethodLength
+
34# rubocop:disable Metrics/PerceivedComplexity
+
35)CODE";
+
36
+
37 // Prepare code template
+
38 code = std::regex_replace(code, std::regex("_INPUT_"), source);
+
39 code = std::regex_replace(code, std::regex("_VERSION_"), version);
+
40 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
41
+
42 Write(code);
+
43}
+
44
+
45void GeneratorRuby::GenerateFooter()
+
46{
+
47 std::string code = R"CODE(
+
48# rubocop:enable all
+
49)CODE";
+
50
+
51 // Prepare code template
+
52 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
53
+
54 Write(code);
+
55}
+
56
+
57void GeneratorRuby::GenerateImports()
+
58{
+
59 std::string code = R"CODE(
+
60require 'base64'
+
61require 'bigdecimal'
+
62require 'json'
+
63require 'set'
+
64require 'uuidtools'
+
65)CODE";
+
66
+
67 // Prepare code template
+
68 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
69
+
70 Write(code);
+
71}
+
72
+
73void GeneratorRuby::GenerateFBE(const CppCommon::Path& path)
+
74{
+
75 // Generate the common file
+
76 CppCommon::Path common = path / "fbe.rb";
+
77 WriteBegin();
+
78
+
79 // Generate common header
+
80 GenerateHeader("FBE");
+
81 GenerateImports();
+
82
+
83 // Generate module begin
+
84 WriteLine();
+
85 WriteLineIndent("module FBE");
+
86 Indent(1);
+
87
+
88 // Generate common models
+
89 GenerateFBEEnum();
+
90 GenerateFBEFlags();
+
91 GenerateFBEInteger();
+
92 GenerateFBEWriteBuffer();
+
93 GenerateFBEReadBuffer();
+
94 GenerateFBEModel();
+
95 GenerateFBEFieldModelBase();
+
96 GenerateFBEFieldModel();
+
97 GenerateFBEFieldModel("Bool", "bool", "1", "false");
+
98 GenerateFBEFieldModel("Byte", "byte", "1", "0");
+
99 GenerateFBEFieldModel("Char", "char", "1", "\"\\0\"");
+
100 GenerateFBEFieldModel("WChar", "wchar", "4", "\"\\0\"");
+
101 GenerateFBEFieldModel("Int8", "int8", "1", "0");
+
102 GenerateFBEFieldModel("UInt8", "uint8", "1", "0");
+
103 GenerateFBEFieldModel("Int16", "int16", "2", "0");
+
104 GenerateFBEFieldModel("UInt16", "uint16", "2", "0");
+
105 GenerateFBEFieldModel("Int32", "int32", "4", "0");
+
106 GenerateFBEFieldModel("UInt32", "uint32", "4", "0");
+
107 GenerateFBEFieldModel("Int64", "int64", "8", "0");
+
108 GenerateFBEFieldModel("UInt64", "uint64", "8", "0");
+
109 GenerateFBEFieldModel("Float", "float", "4", "0.0");
+
110 GenerateFBEFieldModel("Double", "double", "8", "0.0");
+
111 GenerateFBEFieldModel("Timestamp", "timestamp", "8", "0");
+
112 GenerateFBEFieldModel("UUID", "uuid", "16", "UUIDTools::UUID.parse_int(0)");
+
113 GenerateFBEFieldModelDecimal();
+
114 GenerateFBEFieldModelBytes();
+
115 GenerateFBEFieldModelString();
+
116 GenerateFBEFieldModelOptional();
+
117 GenerateFBEFieldModelArray();
+
118 GenerateFBEFieldModelVector();
+
119 GenerateFBEFieldModelSet();
+
120 GenerateFBEFieldModelMap();
+
121 if (Final())
+
122 {
+
123 GenerateFBEFinalModel();
+
124 GenerateFBEFinalModel("Bool", "bool", "1", "false");
+
125 GenerateFBEFinalModel("Byte", "byte", "1", "0");
+
126 GenerateFBEFinalModel("Char", "char", "1", "\"\\0\"");
+
127 GenerateFBEFinalModel("WChar", "wchar", "4", "\"\\0\"");
+
128 GenerateFBEFinalModel("Int8", "int8", "1", "0");
+
129 GenerateFBEFinalModel("UInt8", "uint8", "1", "0");
+
130 GenerateFBEFinalModel("Int16", "int16", "2", "0");
+
131 GenerateFBEFinalModel("UInt16", "uint16", "2", "0");
+
132 GenerateFBEFinalModel("Int32", "int32", "4", "0");
+
133 GenerateFBEFinalModel("UInt32", "uint32", "4", "0");
+
134 GenerateFBEFinalModel("Int64", "int64", "8", "0");
+
135 GenerateFBEFinalModel("UInt64", "uint64", "8", "0");
+
136 GenerateFBEFinalModel("Float", "float", "4", "0.0");
+
137 GenerateFBEFinalModel("Double", "double", "8", "0.0");
+
138 GenerateFBEFinalModel("Timestamp", "timestamp", "8", "0");
+
139 GenerateFBEFinalModel("UUID", "uuid", "16", "UUIDTools::UUID.parse_int(0)");
+
140 GenerateFBEFinalModelDecimal();
+
141 GenerateFBEFinalModelBytes();
+
142 GenerateFBEFinalModelString();
+
143 GenerateFBEFinalModelOptional();
+
144 GenerateFBEFinalModelArray();
+
145 GenerateFBEFinalModelVector();
+
146 GenerateFBEFinalModelSet();
+
147 GenerateFBEFinalModelMap();
+
148 }
+
149 if (Proto())
+
150 {
+
151 GenerateFBESender();
+
152 GenerateFBEReceiver();
+
153 }
+
154
+
155 // Generate module end
+
156 Indent(-1);
+
157 WriteLine();
+
158 WriteLineIndent("end");
+
159
+
160 // Generate common footer
+
161 GenerateFooter();
+
162
+
163 // Close the common file
+
164 WriteEnd();
+
165 Store(common);
+
166}
+
167
+
168void GeneratorRuby::GenerateFBEEnum()
+
169{
+
170 std::string code = R"CODE(
+
171 # Fast Binary Encoding enum utility module
+
172 module Enum
+
173
+
174 attr_reader :key, :value
+
175
+
176 def initialize(key, value)
+
177 @key = key
+
178 @value = value
+
179 end
+
180
+
181 def self.included(base)
+
182 base.extend Enumerable
+
183 base.extend ClassMethods
+
184 end
+
185
+
186 module ClassMethods
+
187 # Define an enumerated value.
+
188 #
+
189 # === Parameters
+
190 # [key] Enumerator key.
+
191 # [value] Enumerator value.
+
192 def define(key, value)
+
193 @_enum_hash ||= {}
+
194 @_enums_by_value ||= {}
+
195
+
196 validate_key!(key)
+
197 store_new_instance(key, value)
+
198 define_singleton_method(key) { value }
+
199 end
+
200
+
201 def store_new_instance(key, value)
+
202 new_instance = new(key, value)
+
203 @_enum_hash[key] = new_instance
+
204 @_enums_by_value[value] = new_instance
+
205 end
+
206
+
207 def const_missing(key)
+
208 raise "Constant is missing for key '#{key}' in enum '#{name}'"
+
209 end
+
210
+
211 # Iterate over all enumerated values.
+
212 # Required for Enumerable mixin
+
213 def each(&block)
+
214 @_enum_hash.each(&block)
+
215 end
+
216
+
217 # Attempt to parse an enum key and return the
+
218 # corresponding value.
+
219 #
+
220 # === Parameters
+
221 # [k] The key string to parse.
+
222 #
+
223 # Returns the corresponding value or nil.
+
224 def parse(k)
+
225 k = k.to_s.upcase
+
226 each do |key, enum|
+
227 return enum.value if key.to_s.upcase == k
+
228 end
+
229 nil
+
230 end
+
231
+
232 # Whether the specified key exists in this enum.
+
233 #
+
234 # === Parameters
+
235 # [k] The string key to check.
+
236 #
+
237 # Returns true if the key exists, false otherwise.
+
238 def key?(k)
+
239 @_enum_hash.key?(k)
+
240 end
+
241
+
242 # Gets the string value for the specified key.
+
243 #
+
244 # === Parameters
+
245 # [k] The key symbol to get the value for.
+
246 #
+
247 # Returns the corresponding enum instance or nil.
+
248 def value(k)
+
249 enum = @_enum_hash[k]
+
250 enum.value if enum
+
251 end
+
252
+
253 # Whether the specified value exists in this enum.
+
254 #
+
255 # === Parameters
+
256 # [k] The string value to check.
+
257 #
+
258 # Returns true if the value exists, false otherwise.
+
259 def value?(v)
+
260 @_enums_by_value.key?(v)
+
261 end
+
262
+
263 # Gets the key symbol for the specified value.
+
264 #
+
265 # === Parameters
+
266 # [v] The string value to parse.
+
267 #
+
268 # Returns the corresponding key symbol or nil.
+
269 def key(v)
+
270 enum = @_enums_by_value[v]
+
271 enum.key if enum
+
272 end
+
273
+
274 # Returns all enum keys.
+
275 def keys
+
276 @_enum_hash.values.map(&:key)
+
277 end
+
278
+
279 # Returns all enum values.
+
280 def values
+
281 @_enum_hash.values.map(&:value)
+
282 end
+
283
+
284 def to_h
+
285 Hash[@_enum_hash.map do |key, enum|
+
286 [key, enum.value]
+
287 end]
+
288 end
+
289
+
290 private
+
291
+
292 def upper?(s)
+
293 !/[[:upper:]]/.match(s).nil?
+
294 end
+
295
+
296 def validate_key!(key)
+
297 return unless @_enum_hash.key?(key)
+
298 raise "Duplicate key '#{key}' in enum '#{name}'"
+
299 end
+
300
+
301 def validate_value!(value)
+
302 return unless @_enums_by_value.key?(value)
+
303 raise "Duplicate value '#{value}' in enum '#{name}'"
+
304 end
+
305 end
+
306
+
307 end
+
308)CODE";
+
309
+
310 // Prepare code template
+
311 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
312
+
313 Write(code);
+
314}
+
315
+
316void GeneratorRuby::GenerateFBEFlags()
+
317{
+
318 std::string code = R"CODE(
+
319 # Fast Binary Encoding flags utility module
+
320 module Flags
+
321
+
322 attr_reader :key, :value
+
323
+
324 def initialize(key, value)
+
325 @key = key
+
326 @value = value
+
327 end
+
328
+
329 def self.included(base)
+
330 base.extend Enumerable
+
331 base.extend ClassMethods
+
332 end
+
333
+
334 module ClassMethods
+
335 # Define an enumerated value.
+
336 #
+
337 # === Parameters
+
338 # [key] Enumerator key.
+
339 # [value] Enumerator value.
+
340 def define(key, value)
+
341 @_enum_hash ||= {}
+
342 @_enums_by_value ||= {}
+
343
+
344 validate_key!(key)
+
345 store_new_instance(key, value)
+
346 define_singleton_method(key) { value }
+
347
+
348 name = key.to_s
+
349
+
350 # Flags check method
+
351 define_method(name + '?') do
+
352 @value & value != 0
+
353 end
+
354
+
355 # Flags set/reset method
+
356 define_method(name + '=') do |set|
+
357 if set
+
358 @value |= value
+
359 else
+
360 @value &= ~value
+
361 end
+
362 end
+
363 end
+
364
+
365 def store_new_instance(key, value)
+
366 new_instance = new(key, value)
+
367 @_enum_hash[key] = new_instance
+
368 @_enums_by_value[value] = new_instance
+
369 end
+
370
+
371 def const_missing(key)
+
372 raise "Constant is missing for key '#{key}' in flags '#{name}'"
+
373 end
+
374
+
375 # Iterate over all enumerated values.
+
376 # Required for Enumerable mixin
+
377 def each(&block)
+
378 @_enum_hash.each(&block)
+
379 end
+
380
+
381 # Attempt to parse an enum key and return the
+
382 # corresponding value.
+
383 #
+
384 # === Parameters
+
385 # [k] The key string to parse.
+
386 #
+
387 # Returns the corresponding value or nil.
+
388 def parse(k)
+
389 k = k.to_s.upcase
+
390 each do |key, enum|
+
391 return enum.value if key.to_s.upcase == k
+
392 end
+
393 nil
+
394 end
+
395
+
396 # Whether the specified key exists in this enum.
+
397 #
+
398 # === Parameters
+
399 # [k] The string key to check.
+
400 #
+
401 # Returns true if the key exists, false otherwise.
+
402 def key?(k)
+
403 @_enum_hash.key?(k)
+
404 end
+
405
+
406 # Gets the string value for the specified key.
+
407 #
+
408 # === Parameters
+
409 # [k] The key symbol to get the value for.
+
410 #
+
411 # Returns the corresponding enum instance or nil.
+
412 def value(k)
+
413 enum = @_enum_hash[k]
+
414 enum.value if enum
+
415 end
+
416
+
417 # Whether the specified value exists in this enum.
+
418 #
+
419 # === Parameters
+
420 # [k] The string value to check.
+
421 #
+
422 # Returns true if the value exists, false otherwise.
+
423 def value?(v)
+
424 @_enums_by_value.key?(v)
+
425 end
+
426
+
427 # Gets the key symbol for the specified value.
+
428 #
+
429 # === Parameters
+
430 # [v] The string value to parse.
+
431 #
+
432 # Returns the corresponding key symbol or nil.
+
433 def key(v)
+
434 enum = @_enums_by_value[v]
+
435 enum.key if enum
+
436 end
+
437
+
438 # Returns all enum keys.
+
439 def keys
+
440 @_enum_hash.values.map(&:key)
+
441 end
+
442
+
443 # Returns all enum values.
+
444 def values
+
445 @_enum_hash.values.map(&:value)
+
446 end
+
447
+
448 def to_h
+
449 Hash[@_enum_hash.map do |key, enum|
+
450 [key, enum.value]
+
451 end]
+
452 end
+
453
+
454 private
+
455
+
456 def upper?(s)
+
457 !/[[:upper:]]/.match(s).nil?
+
458 end
+
459
+
460 def validate_key!(key)
+
461 return unless @_enum_hash.key?(key)
+
462 raise "Duplicate key '#{key}' in flags '#{name}'"
+
463 end
+
464
+
465 def validate_value!(value)
+
466 return unless @_enums_by_value.key?(value)
+
467 raise "Duplicate value '#{value}' in flags '#{name}'"
+
468 end
+
469 end
+
470
+
471 end
+
472)CODE";
+
473
+
474 // Prepare code template
+
475 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
476
+
477 Write(code);
+
478}
+
479
+
480void GeneratorRuby::GenerateFBEInteger()
+
481{
+
482 std::string code = R"CODE(
+
483 # Fast Binary Encoding integer number constants
+
484 class Integer
+
485 N_BYTES = [42].pack('i').size
+
486 N_BITS = N_BYTES * 16
+
487 MAX = 2 ** (N_BITS - 2) - 1
+
488 MIN = -MAX - 1
+
489 end
+
490)CODE";
+
491
+
492 // Prepare code template
+
493 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
494
+
495 Write(code);
+
496}
+
497
+
498void GeneratorRuby::GenerateFBEWriteBuffer()
+
499{
+
500 std::string code = R"CODE(
+
501 # Fast Binary Encoding write buffer based on the dynamic byte array
+
502 class WriteBuffer
+
503 def initialize(capacity = 0)
+
504 @_buffer = capacity > 0 ? [0].pack('C') * capacity : ''
+
505 @_size = 0
+
506 @_offset = 0
+
507 end
+
508
+
509 def empty?
+
510 @_buffer.nil? || @_size <= 0
+
511 end
+
512
+
513 def buffer
+
514 @_buffer
+
515 end
+
516
+
517 def capacity
+
518 @_buffer.length
+
519 end
+
520
+
521 def size
+
522 @_size
+
523 end
+
524
+
525 def offset
+
526 @_offset
+
527 end
+
528
+
529 # Attach an empty memory buffer
+
530 def attach_new
+
531 @_buffer = ''
+
532 @_size = 0
+
533 @_offset = 0
+
534 end
+
535
+
536 # Attach an empty memory buffer with a given capacity
+
537 def attach_capacity(capacity)
+
538 @_buffer = [0].pack('C') * capacity
+
539 @_size = 0
+
540 @_offset = 0
+
541 end
+
542
+
543 # Attach a given memory buffer
+
544 def attach_buffer(buffer, offset = 0, size = nil)
+
545 raise ArgumentError, "Invalid buffer!" if buffer.nil?
+
546
+
547 if buffer.is_a?(String)
+
548 @_buffer = buffer
+
549 size = @_buffer.length if size.nil?
+
550 elsif buffer.is_a?(Array)
+
551 @_buffer = buffer.join
+
552 size = @_buffer.length if size.nil?
+
553 elsif buffer.is_a?(WriteBuffer)
+
554 @_buffer = buffer.buffer
+
555 size = buffer.size if size.nil?
+
556 elsif buffer.is_a?(ReadBuffer)
+
557 @_buffer = buffer.buffer
+
558 size = buffer.size if size.nil?
+
559 else
+
560 raise ArgumentError, "Unknown buffer type!"
+
561 end
+
562
+
563 raise ArgumentError, "Invalid size!" if size <= 0
+
564 raise ArgumentError, "Invalid offset!" if offset > size
+
565
+
566 @_size = size
+
567 @_offset = offset
+
568 end
+
569
+
570 # Allocate memory in the current write buffer and return offset to the allocated memory block
+
571 def allocate(size)
+
572 raise ArgumentError, "Invalid allocation size!" if size < 0
+
573
+
574 offset = @_size
+
575
+
576 # Calculate a new buffer size
+
577 total = @_size + size
+
578
+
579 if total <= @_buffer.length
+
580 @_size = total
+
581 return offset
+
582 end
+
583
+
584 @_buffer += [0].pack('C') * [total, 2 * @_buffer.length].max
+
585 @_size = total
+
586 offset
+
587 end
+
588
+
589 # Remove some memory of the given size from the current write buffer
+
590 def remove(offset, size)
+
591 raise ArgumentError, "Invalid offset & size!" if (offset + size) > @_buffer.length
+
592
+
593 @_buffer.slice!(offset, size)
+
594 @_size -= size
+
595 if @_offset >= (offset + size)
+
596 @_offset -= size
+
597 elsif @_offset >= offset
+
598 @_offset -= @_offset - offset
+
599 @_offset = @_size if @_offset > @_size
+
600 end
+
601 end
+
602
+
603 # Reserve memory of the given capacity in the current write buffer
+
604 def reserve(capacity)
+
605 raise ArgumentError, "Invalid reserve capacity!" if capacity < 0
+
606
+
607 @_buffer += [0].pack('C') * [capacity, 2 * @_buffer.length].max if capacity > @_buffer.length
+
608 end
+
609
+
610 # Resize the current write buffer
+
611 def resize(size)
+
612 reserve(size)
+
613 @_size = size
+
614 @_offset = @_size if @_offset > @_size
+
615 end
+
616
+
617 # Reset the current write buffer and its offset
+
618 def reset
+
619 @_size = 0
+
620 @_offset = 0
+
621 end
+
622
+
623 # Shift the current write buffer offset
+
624 def shift(offset)
+
625 @_offset += offset
+
626 end
+
627
+
628 # Unshift the current write buffer offset
+
629 def unshift(offset)
+
630 @_offset -= offset
+
631 end
+
632 end
+
633)CODE";
+
634
+
635 // Prepare code template
+
636 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
637
+
638 Write(code);
+
639}
+
640
+
641void GeneratorRuby::GenerateFBEReadBuffer()
+
642{
+
643 std::string code = R"CODE(
+
644 # Fast Binary Encoding read buffer based on the constant byte buffer
+
645 class ReadBuffer
+
646 def initialize
+
647 @_buffer = nil
+
648 @_size = 0
+
649 @_offset = 0
+
650 end
+
651
+
652 def empty?
+
653 @_buffer.nil? || @_size <= 0
+
654 end
+
655
+
656 def buffer
+
657 @_buffer
+
658 end
+
659
+
660 def capacity
+
661 @_buffer.length
+
662 end
+
663
+
664 def size
+
665 @_size
+
666 end
+
667
+
668 def offset
+
669 @_offset
+
670 end
+
671
+
672 # Attach a given memory buffer
+
673 def attach_buffer(buffer, offset = 0, size = nil)
+
674 raise ArgumentError, "Invalid buffer!" if buffer.nil?
+
675
+
676 if buffer.is_a?(String)
+
677 @_buffer = buffer
+
678 size = @_buffer.length if size.nil?
+
679 elsif buffer.is_a?(Array)
+
680 @_buffer = buffer.join
+
681 size = @_buffer.length if size.nil?
+
682 elsif buffer.is_a?(WriteBuffer)
+
683 @_buffer = buffer.buffer
+
684 size = buffer.size if size.nil?
+
685 elsif buffer.is_a?(ReadBuffer)
+
686 @_buffer = buffer.buffer
+
687 size = buffer.size if size.nil?
+
688 else
+
689 raise ArgumentError, "Unknown buffer type!"
+
690 end
+
691
+
692 raise ArgumentError, "Invalid size!" if size <= 0
+
693 raise ArgumentError, "Invalid offset!" if offset > size
+
694
+
695 @_size = size
+
696 @_offset = offset
+
697 end
+
698
+
699 # Reset the current read buffer and its offset
+
700 def reset
+
701 @_buffer = nil
+
702 @_size = 0
+
703 @_offset = 0
+
704 end
+
705
+
706 # Shift the current read buffer offset
+
707 def shift(offset)
+
708 @_offset += offset
+
709 end
+
710
+
711 # Unshift the current read buffer offset
+
712 def unshift(offset)
+
713 @_offset -= offset
+
714 end
+
715 end
+
716)CODE";
+
717
+
718 // Prepare code template
+
719 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
720
+
721 Write(code);
+
722}
+
723
+
724void GeneratorRuby::GenerateFBEModel()
+
725{
+
726 std::string code = R"CODE(
+
727 # Fast Binary Encoding base model
+
728 class Model
+
729 def initialize(buffer = WriteBuffer.new)
+
730 @_buffer = buffer
+
731 end
+
732
+
733 def buffer
+
734 @_buffer
+
735 end
+
736
+
737 # Attach an empty memory buffer
+
738 def attach_new
+
739 @_buffer.attach_new
+
740 end
+
741
+
742 # Attach an empty memory buffer with a given capacity
+
743 def attach_capacity(capacity)
+
744 @_buffer.attach_capacity(capacity)
+
745 end
+
746
+
747 # Attach a given memory buffer
+
748 def attach_buffer(buffer, offset = 0, size = nil)
+
749 @_buffer.attach_buffer(buffer, offset, size)
+
750 end
+
751
+
752 # Allocate memory in the current write buffer and return offset to the allocated memory block
+
753 def allocate(size)
+
754 @_buffer.allocate(size)
+
755 end
+
756
+
757 # Remove some memory of the given size from the current write buffer
+
758 def remove(offset, size)
+
759 @_buffer.remove(offset, size)
+
760 end
+
761
+
762 # Reserve memory of the given capacity in the current write buffer
+
763 def reserve(capacity)
+
764 @_buffer.reserve(capacity)
+
765 end
+
766
+
767 # Resize the current write buffer
+
768 def resize(size)
+
769 @_buffer.resize(size)
+
770 end
+
771
+
772 # Reset the current write buffer and its offset
+
773 def reset
+
774 @_buffer.reset
+
775 end
+
776
+
777 # Shift the current write buffer offset
+
778 def shift(offset)
+
779 @_buffer.shift(offset)
+
780 end
+
781
+
782 # Unshift the current write buffer offset
+
783 def unshift(offset)
+
784 @_buffer.unshift(offset)
+
785 end
+
786
+
787 protected
+
788
+
789 # Buffer I/O methods
+
790
+
791 def read_uint32(offset)
+
792 @_buffer.buffer.slice(@_buffer.offset + offset, 4).unpack('L<')[0]
+
793 end
+
794
+
795 def write_uint32(offset, value)
+
796 @_buffer.buffer[@_buffer.offset + offset, 4] = [value].pack('L<')
+
797 end
+
798 end
+
799)CODE";
+
800
+
801 // Prepare code template
+
802 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
803
+
804 Write(code);
+
805}
+
806
+
807void GeneratorRuby::GenerateFBEFieldModelBase()
+
808{
+
809 std::string code = R"CODE(
+
810 # Fast Binary Encoding base field model
+
811 # noinspection RubyTooManyMethodsInspection
+
812 class FieldModelBase
+
813 def initialize(buffer, offset)
+
814 @_buffer = buffer
+
815 @_offset = offset
+
816 end
+
817
+
818 def buffer
+
819 @_buffer
+
820 end
+
821
+
822 # Get the field offset
+
823 def fbe_offset
+
824 @_offset
+
825 end
+
826
+
827 # Set the field offset
+
828 def fbe_offset=(offset)
+
829 @_offset = offset
+
830 end
+
831
+
832 # Get the field size
+
833 def fbe_size
+
834 0
+
835 end
+
836
+
837 # Get the field extra size
+
838 def fbe_extra
+
839 0
+
840 end
+
841
+
842 # Shift the current field offset
+
843 def fbe_shift(offset)
+
844 @_offset += offset
+
845 end
+
846
+
847 # Unshift the current field offset
+
848 def fbe_unshift(offset)
+
849 @_offset -= offset
+
850 end
+
851
+
852 protected
+
853
+
854 # Buffer I/O methods
+
855
+
856 def read_bool(offset)
+
857 @_buffer.buffer.slice(@_buffer.offset + offset, 1).unpack('C')[0] != 0
+
858 end
+
859
+
860 def read_byte(offset)
+
861 @_buffer.buffer.slice(@_buffer.offset + offset, 1).unpack('C')[0]
+
862 end
+
863
+
864 def read_char(offset)
+
865 @_buffer.buffer.slice(@_buffer.offset + offset, 1).unpack('C')[0].chr
+
866 end
+
867
+
868 def read_wchar(offset)
+
869 # noinspection RubyResolve
+
870 @_buffer.buffer.slice(@_buffer.offset + offset, 4).unpack('L<')[0].chr(Encoding::UTF_8)
+
871 end
+
872
+
873 def read_int8(offset)
+
874 @_buffer.buffer.slice(@_buffer.offset + offset, 1).unpack('c')[0]
+
875 end
+
876
+
877 def read_uint8(offset)
+
878 @_buffer.buffer.slice(@_buffer.offset + offset, 1).unpack('C')[0]
+
879 end
+
880
+
881 def read_int16(offset)
+
882 @_buffer.buffer.slice(@_buffer.offset + offset, 2).unpack('s<')[0]
+
883 end
+
884
+
885 def read_uint16(offset)
+
886 @_buffer.buffer.slice(@_buffer.offset + offset, 2).unpack('S<')[0]
+
887 end
+
888
+
889 def read_uint16_be(offset)
+
890 @_buffer.buffer.slice(@_buffer.offset + offset, 2).unpack('S>')[0]
+
891 end
+
892
+
893 def read_int32(offset)
+
894 @_buffer.buffer.slice(@_buffer.offset + offset, 4).unpack('l<')[0]
+
895 end
+
896
+
897 def read_uint32(offset)
+
898 @_buffer.buffer.slice(@_buffer.offset + offset, 4).unpack('L<')[0]
+
899 end
+
900
+
901 def read_uint32_be(offset)
+
902 @_buffer.buffer.slice(@_buffer.offset + offset, 4).unpack('L>')[0]
+
903 end
+
904
+
905 def read_int64(offset)
+
906 @_buffer.buffer.slice(@_buffer.offset + offset, 8).unpack('q<')[0]
+
907 end
+
908
+
909 def read_uint64(offset)
+
910 @_buffer.buffer.slice(@_buffer.offset + offset, 8).unpack('Q<')[0]
+
911 end
+
912
+
913 def read_float(offset)
+
914 @_buffer.buffer.slice(@_buffer.offset + offset, 4).unpack('e')[0]
+
915 end
+
916
+
917 def read_double(offset)
+
918 @_buffer.buffer.slice(@_buffer.offset + offset, 8).unpack('E')[0]
+
919 end
+
920
+
921 def read_bytes(offset, size)
+
922 @_buffer.buffer.slice(@_buffer.offset + offset, size)
+
923 end
+
924
+
925 def read_timestamp(offset)
+
926 nanoseconds = read_uint64(offset)
+
927 Time.at(nanoseconds / 1000000000, nanoseconds % 1000000000, :nsec).utc
+
928 end
+
929
+
930 def read_uuid(offset)
+
931 UUIDTools::UUID.parse_raw(@_buffer.buffer.slice(@_buffer.offset + offset, 16))
+
932 end
+
933
+
934 def write_bool(offset, value)
+
935 @_buffer.buffer[@_buffer.offset + offset, 1] = [value ? 1 : 0].pack('C')
+
936 end
+
937
+
938 def write_byte(offset, value)
+
939 @_buffer.buffer[@_buffer.offset + offset, 1] = [value].pack('C')
+
940 end
+
941
+
942 def write_char(offset, value)
+
943 @_buffer.buffer[@_buffer.offset + offset, 1] = [value.ord].pack('C')
+
944 end
+
945
+
946 def write_wchar(offset, value)
+
947 @_buffer.buffer[@_buffer.offset + offset, 4] = [value.ord].pack('L<')
+
948 end
+
949
+
950 def write_int8(offset, value)
+
951 @_buffer.buffer[@_buffer.offset + offset, 1] = [value].pack('c')
+
952 end
+
953
+
954 def write_uint8(offset, value)
+
955 @_buffer.buffer[@_buffer.offset + offset, 1] = [value].pack('C')
+
956 end
+
957
+
958 def write_int16(offset, value)
+
959 @_buffer.buffer[@_buffer.offset + offset, 2] = [value].pack('s<')
+
960 end
+
961
+
962 def write_uint16(offset, value)
+
963 @_buffer.buffer[@_buffer.offset + offset, 2] = [value].pack('S<')
+
964 end
+
965
+
966 def write_int32(offset, value)
+
967 @_buffer.buffer[@_buffer.offset + offset, 4] = [value].pack('l<')
+
968 end
+
969
+
970 def write_uint32(offset, value)
+
971 @_buffer.buffer[@_buffer.offset + offset, 4] = [value].pack('L<')
+
972 end
+
973
+
974 def write_int64(offset, value)
+
975 @_buffer.buffer[@_buffer.offset + offset, 8] = [value].pack('q<')
+
976 end
+
977
+
978 def write_uint64(offset, value)
+
979 @_buffer.buffer[@_buffer.offset + offset, 8] = [value].pack('Q<')
+
980 end
+
981
+
982 def write_float(offset, value)
+
983 @_buffer.buffer[@_buffer.offset + offset, 4] = [value].pack('e')
+
984 end
+
985
+
986 def write_double(offset, value)
+
987 @_buffer.buffer[@_buffer.offset + offset, 8] = [value].pack('E')
+
988 end
+
989
+
990 def write_bytes(offset, buffer)
+
991 @_buffer.buffer[@_buffer.offset + offset, buffer.length] = buffer
+
992 end
+
993
+
994 def write_count(offset, value, value_count)
+
995 (0...value_count).each { |i| @_buffer.buffer[@_buffer.offset + offset + i] = value.chr }
+
996 end
+
997
+
998 def write_timestamp(offset, value)
+
999 nanoseconds = value.to_i * 1000000000 + value.nsec
+
1000 write_uint64(offset, nanoseconds)
+
1001 end
+
1002
+
1003 def write_uuid(offset, value)
+
1004 @_buffer.buffer[@_buffer.offset + offset, 16] = value.raw
+
1005 end
+
1006 end
+
1007)CODE";
+
1008
+
1009 // Prepare code template
+
1010 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
1011
+
1012 Write(code);
+
1013}
+
1014
+
1015void GeneratorRuby::GenerateFBEFieldModel()
+
1016{
+
1017 std::string code = R"CODE(
+
1018 # Fast Binary Encoding field model
+
1019 class FieldModel < FieldModelBase
+
1020 def initialize(buffer, offset)
+
1021 super(buffer, offset)
+
1022 end
+
1023
+
1024 # Is the value valid?
+
1025 def valid?
+
1026 verify
+
1027 end
+
1028
+
1029 # Check if the value is valid
+
1030 def verify
+
1031 true
+
1032 end
+
1033 end
+
1034)CODE";
+
1035
+
1036 // Prepare code template
+
1037 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
1038
+
1039 Write(code);
+
1040}
+
1041
+
1042void GeneratorRuby::GenerateFBEFieldModel(const std::string& name, const std::string& type, const std::string& size, const std::string& defaults)
+
1043{
+
1044 std::string code = R"CODE(
+
1045 # Fast Binary Encoding _TYPE_ field model
+
1046 class FieldModel_NAME_ < FieldModel
+
1047 def initialize(buffer, offset)
+
1048 super(buffer, offset)
+
1049 end
+
1050
+
1051 # Get the field size
+
1052 def fbe_size
+
1053 _SIZE_
+
1054 end
+
1055
+
1056 # Get the value
+
1057 def get(defaults = _DEFAULTS_)
+
1058 if (@_buffer.offset + fbe_offset + fbe_size) > @_buffer.size
+
1059 return defaults
+
1060 end
+
1061
+
1062 read__TYPE_(fbe_offset)
+
1063 end
+
1064
+
1065 # Set the value
+
1066 def set(value)
+
1067 if (@_buffer.offset + fbe_offset + fbe_size) > @_buffer.size
+
1068 return
+
1069 end
+
1070
+
1071 write__TYPE_(fbe_offset, value)
+
1072 end
+
1073 end
+
1074)CODE";
+
1075
+
1076 // Prepare code template
+
1077 code = std::regex_replace(code, std::regex("_NAME_"), name);
+
1078 code = std::regex_replace(code, std::regex("_TYPE_"), type);
+
1079 code = std::regex_replace(code, std::regex("_SIZE_"), size);
+
1080 code = std::regex_replace(code, std::regex("_DEFAULTS_"), defaults);
+
1081 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
1082
+
1083 Write(code);
+
1084}
+
1085
+
1086void GeneratorRuby::GenerateFBEFieldModelDecimal()
+
1087{
+
1088 std::string code = R"CODE(
+
1089 # Fast Binary Encoding decimal field model
+
1090 class FieldModelDecimal < FieldModel
+
1091 def initialize(buffer, offset)
+
1092 super(buffer, offset)
+
1093 end
+
1094
+
1095 # Get the field size
+
1096 def fbe_size
+
1097 16
+
1098 end
+
1099
+
1100 # Get the decimal value
+
1101 def get(defaults = BigDecimal(0))
+
1102 if (@_buffer.offset + fbe_offset + fbe_size) > @_buffer.size
+
1103 return defaults
+
1104 end
+
1105
+
1106 # Read decimal parts
+
1107 low = read_uint32(fbe_offset)
+
1108 mid = read_uint32(fbe_offset + 4)
+
1109 high = read_uint32(fbe_offset + 8)
+
1110 flags = read_uint32(fbe_offset + 12)
+
1111
+
1112 # Calculate decimal value
+
1113 negative = (flags & 0x80000000) != 0
+
1114 scale = (flags & 0x7FFFFFFF) >> 16
+
1115 result = BigDecimal(high) * 18446744073709551616
+
1116 result += BigDecimal(mid) * 4294967296
+
1117 result += BigDecimal(low)
+
1118 result /= 10 ** scale
+
1119 result = -result if negative
+
1120
+
1121 # Return decimal value
+
1122 result
+
1123 end
+
1124
+
1125 # Set the decimal value
+
1126 def set(value)
+
1127 if (@_buffer.offset + fbe_offset + fbe_size) > @_buffer.size
+
1128 return
+
1129 end
+
1130
+
1131 # Extract decimal parts
+
1132 sign, significant_digits, _, exponent = value.split
+
1133 number = significant_digits.to_i(10)
+
1134 if exponent > significant_digits.length
+
1135 number *= 10 ** (exponent - 1)
+
1136 scale = 0
+
1137 else
+
1138 scale = significant_digits.length - exponent
+
1139 end
+
1140
+
1141 # Check for decimal number overflow
+
1142 bits = number.bit_length
+
1143 if (bits < 0) || (bits > 96)
+
1144 # Value too big for .NET Decimal (bit length is limited to [0, 96])
+
1145 write_count(fbe_offset, 0, fbe_size)
+
1146 return
+
1147 end
+
1148
+
1149 # Check for decimal scale overflow
+
1150 if (scale < 0) || (scale > 28)
+
1151 # Value scale exceeds .NET Decimal limit of [0, 28]
+
1152 write_count(fbe_offset, 0, fbe_size)
+
1153 return
+
1154 end
+
1155
+
1156 # Write unscaled value to bytes 0-11
+
1157 bytes = []
+
1158 while number > 0
+
1159 bytes.insert(-1, number & 0xFF)
+
1160 number >>= 8
+
1161 end
+
1162 bytes = bytes.pack("C*")
+
1163 write_bytes(fbe_offset, bytes)
+
1164 write_count(fbe_offset + bytes.length, 0, 12 - bytes.length)
+
1165
+
1166 # Write scale at byte 14
+
1167 write_byte(fbe_offset + 14, scale)
+
1168
+
1169 # Write signum at byte 15
+
1170 write_byte(fbe_offset + 15, (sign == -1) ? 0x80 : 0)
+
1171 end
+
1172 end
+
1173)CODE";
+
1174
+
1175 // Prepare code template
+
1176 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
1177
+
1178 Write(code);
+
1179}
+
1180
+
1181void GeneratorRuby::GenerateFBEFieldModelBytes()
+
1182{
+
1183 std::string code = R"CODE(
+
1184 # Fast Binary Encoding bytes field model
+
1185 class FieldModelBytes < FieldModel
+
1186 def initialize(buffer, offset)
+
1187 super(buffer, offset)
+
1188 end
+
1189
+
1190 # Get the field size
+
1191 def fbe_size
+
1192 4
+
1193 end
+
1194
+
1195 # Get the field extra size
+
1196 def fbe_extra
+
1197 if (@_buffer.offset + fbe_offset + fbe_size) > @_buffer.size
+
1198 return 0
+
1199 end
+
1200
+
1201 fbe_bytes_offset = read_uint32(fbe_offset)
+
1202 if (fbe_bytes_offset == 0) || ((@_buffer.offset + fbe_bytes_offset + 4) > @_buffer.size)
+
1203 return 0
+
1204 end
+
1205
+
1206 fbe_bytes_size = read_uint32(fbe_bytes_offset)
+
1207 4 + fbe_bytes_size
+
1208 end
+
1209
+
1210 # Is the bytes value valid?
+
1211 def valid?
+
1212 verify
+
1213 end
+
1214
+
1215 # Check if the bytes value is valid
+
1216 def verify
+
1217 if (@_buffer.offset + fbe_offset + fbe_size) > @_buffer.size
+
1218 return true
+
1219 end
+
1220
+
1221 fbe_bytes_offset = read_uint32(fbe_offset)
+
1222 if fbe_bytes_offset == 0
+
1223 return true
+
1224 end
+
1225
+
1226 if (@_buffer.offset + fbe_bytes_offset + 4) > @_buffer.size
+
1227 return false
+
1228 end
+
1229
+
1230 fbe_bytes_size = read_uint32(fbe_bytes_offset)
+
1231 if (@_buffer.offset + fbe_bytes_offset + 4 + fbe_bytes_size) > @_buffer.size
+
1232 return false
+
1233 end
+
1234
+
1235 true
+
1236 end
+
1237
+
1238 # Get the bytes value
+
1239 def get(defaults = '')
+
1240 if (@_buffer.offset + fbe_offset + fbe_size) > @_buffer.size
+
1241 return defaults
+
1242 end
+
1243
+
1244 fbe_bytes_offset = read_uint32(fbe_offset)
+
1245 if fbe_bytes_offset == 0
+
1246 return defaults
+
1247 end
+
1248
+
1249 if (@_buffer.offset + fbe_bytes_offset + 4) > @_buffer.size
+
1250 return defaults
+
1251 end
+
1252
+
1253 fbe_bytes_size = read_uint32(fbe_bytes_offset)
+
1254 if (@_buffer.offset + fbe_bytes_offset + 4 + fbe_bytes_size) > @_buffer.size
+
1255 return defaults
+
1256 end
+
1257
+
1258 read_bytes(fbe_bytes_offset + 4, fbe_bytes_size)
+
1259 end
+
1260
+
1261 # Set the bytes value
+
1262 def set(value)
+
1263 raise ArgumentError, "Invalid bytes value!" if value.nil? || !value.is_a?(String)
+
1264
+
1265 if (@_buffer.offset + fbe_offset + fbe_size) > @_buffer.size
+
1266 return
+
1267 end
+
1268
+
1269 fbe_bytes_size = value.length
+
1270 fbe_bytes_offset = @_buffer.allocate(4 + fbe_bytes_size) - @_buffer.offset
+
1271 if (fbe_bytes_offset <= 0) or ((@_buffer.offset + fbe_bytes_offset + 4 + fbe_bytes_size) > @_buffer.size)
+
1272 return
+
1273 end
+
1274
+
1275 write_uint32(fbe_offset, fbe_bytes_offset)
+
1276 write_uint32(fbe_bytes_offset, fbe_bytes_size)
+
1277 write_bytes(fbe_bytes_offset + 4, value)
+
1278 end
+
1279 end
+
1280)CODE";
+
1281
+
1282 // Prepare code template
+
1283 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
1284
+
1285 Write(code);
+
1286}
+
1287
+
1288void GeneratorRuby::GenerateFBEFieldModelString()
+
1289{
+
1290 std::string code = R"CODE(
+
1291 # Fast Binary Encoding string field model
+
1292 class FieldModelString < FieldModel
+
1293 def initialize(buffer, offset)
+
1294 super(buffer, offset)
+
1295 end
+
1296
+
1297 # Get the field size
+
1298 def fbe_size
+
1299 4
+
1300 end
+
1301
+
1302 # Get the field extra size
+
1303 def fbe_extra
+
1304 if (@_buffer.offset + fbe_offset + fbe_size) > @_buffer.size
+
1305 return 0
+
1306 end
+
1307
+
1308 fbe_string_offset = read_uint32(fbe_offset)
+
1309 if (fbe_string_offset == 0) or ((@_buffer.offset + fbe_string_offset + 4) > @_buffer.size)
+
1310 return 0
+
1311 end
+
1312
+
1313 fbe_string_size = read_uint32(fbe_string_offset)
+
1314 4 + fbe_string_size
+
1315 end
+
1316
+
1317 # Is the string value valid?
+
1318 def valid?
+
1319 verify
+
1320 end
+
1321
+
1322 # Check if the string value is valid
+
1323 def verify
+
1324 if (@_buffer.offset + fbe_offset + fbe_size) > @_buffer.size
+
1325 return true
+
1326 end
+
1327
+
1328 fbe_string_offset = read_uint32(fbe_offset)
+
1329 if fbe_string_offset == 0
+
1330 return true
+
1331 end
+
1332
+
1333 if (@_buffer.offset + fbe_string_offset + 4) > @_buffer.size
+
1334 return false
+
1335 end
+
1336
+
1337 fbe_string_size = read_uint32(fbe_string_offset)
+
1338 if (@_buffer.offset + fbe_string_offset + 4 + fbe_string_size) > @_buffer.size
+
1339 return false
+
1340 end
+
1341
+
1342 true
+
1343 end
+
1344
+
1345 # Get the string value
+
1346 def get(defaults = '')
+
1347 if (@_buffer.offset + fbe_offset + fbe_size) > @_buffer.size
+
1348 return defaults
+
1349 end
+
1350
+
1351 fbe_string_offset = read_uint32(fbe_offset)
+
1352 if fbe_string_offset == 0
+
1353 return defaults
+
1354 end
+
1355
+
1356 if (@_buffer.offset + fbe_string_offset + 4) > @_buffer.size
+
1357 return defaults
+
1358 end
+
1359
+
1360 fbe_string_size = read_uint32(fbe_string_offset)
+
1361 if (@_buffer.offset + fbe_string_offset + 4 + fbe_string_size) > @_buffer.size
+
1362 return defaults
+
1363 end
+
1364
+
1365 data = read_bytes(fbe_string_offset + 4, fbe_string_size)
+
1366 data.encode!('utf-8')
+
1367 end
+
1368
+
1369 # Set the string value
+
1370 def set(value)
+
1371 raise ArgumentError, "Invalid string value!" if value.nil? || !value.is_a?(String)
+
1372
+
1373 if (@_buffer.offset + fbe_offset + fbe_size) > @_buffer.size
+
1374 return
+
1375 end
+
1376
+
1377 data = value.encode('utf-8')
+
1378
+
1379 fbe_string_size = data.length
+
1380 fbe_string_offset = @_buffer.allocate(4 + fbe_string_size) - @_buffer.offset
+
1381 if (fbe_string_offset <= 0) || ((@_buffer.offset + fbe_string_offset + 4 + fbe_string_size) > @_buffer.size)
+
1382 return
+
1383 end
+
1384
+
1385 write_uint32(fbe_offset, fbe_string_offset)
+
1386 write_uint32(fbe_string_offset, fbe_string_size)
+
1387 write_bytes(fbe_string_offset + 4, data)
+
1388 end
+
1389 end
+
1390)CODE";
+
1391
+
1392 // Prepare code template
+
1393 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
1394
+
1395 Write(code);
+
1396}
+
1397
+
1398void GeneratorRuby::GenerateFBEFieldModelOptional()
+
1399{
+
1400 std::string code = R"CODE(
+
1401 # Fast Binary Encoding optional field model
+
1402 class FieldModelOptional < FieldModel
+
1403 def initialize(model, buffer, offset)
+
1404 super(buffer, offset)
+
1405 @_model = model
+
1406 @_model.fbe_offset = 0
+
1407 end
+
1408
+
1409 # Get the field size
+
1410 def fbe_size
+
1411 1 + 4
+
1412 end
+
1413
+
1414 # Get the field extra size
+
1415 def fbe_extra
+
1416 unless has_value?
+
1417 return 0
+
1418 end
+
1419
+
1420 fbe_optional_offset = read_uint32(fbe_offset + 1)
+
1421 if (fbe_optional_offset == 0) || ((@_buffer.offset + fbe_optional_offset + 4) > @_buffer.size)
+
1422 return 0
+
1423 end
+
1424
+
1425 @_buffer.shift(fbe_optional_offset)
+
1426 fbe_result = value.fbe_size + value.fbe_extra
+
1427 @_buffer.unshift(fbe_optional_offset)
+
1428 fbe_result
+
1429 end
+
1430
+
1431 # Checks if the object contains a value
+
1432 def empty?
+
1433 has_value?
+
1434 end
+
1435
+
1436 # Checks if the object contains a value
+
1437 def has_value?
+
1438 if (@_buffer.offset + fbe_offset + fbe_size) > @_buffer.size
+
1439 return false
+
1440 end
+
1441
+
1442 fbe_has_value = read_uint8(fbe_offset)
+
1443 fbe_has_value != 0
+
1444 end
+
1445
+
1446 # Get the base field model value
+
1447 def value
+
1448 @_model
+
1449 end
+
1450
+
1451 # Is the optional value valid?
+
1452 def valid?
+
1453 verify
+
1454 end
+
1455
+
1456 # Check if the optional value is valid
+
1457 def verify
+
1458 if (@_buffer.offset + fbe_offset + fbe_size) > @_buffer.size
+
1459 return true
+
1460 end
+
1461
+
1462 fbe_has_value = read_uint8(fbe_offset)
+
1463 if fbe_has_value == 0
+
1464 return true
+
1465 end
+
1466
+
1467 fbe_optional_offset = read_uint32(fbe_offset + 1)
+
1468 if fbe_optional_offset == 0
+
1469 return false
+
1470 end
+
1471
+
1472 @_buffer.shift(fbe_optional_offset)
+
1473 fbe_result = value.verify
+
1474 @_buffer.unshift(fbe_optional_offset)
+
1475 fbe_result
+
1476 end
+
1477
+
1478 # Get the optional value (being phase)
+
1479 def get_begin
+
1480 unless has_value?
+
1481 return 0
+
1482 end
+
1483
+
1484 fbe_optional_offset = read_uint32(fbe_offset + 1)
+
1485 if fbe_optional_offset <= 0
+
1486 return 0
+
1487 end
+
1488
+
1489 @_buffer.shift(fbe_optional_offset)
+
1490 fbe_optional_offset
+
1491 end
+
1492
+
1493 # Get the optional value (end phase)
+
1494 def get_end(fbe_begin)
+
1495 @_buffer.unshift(fbe_begin)
+
1496 end
+
1497
+
1498 # Get the optional value
+
1499 def get(defaults = nil)
+
1500 fbe_begin = get_begin
+
1501 if fbe_begin == 0
+
1502 return defaults
+
1503 end
+
1504 optional = value.get
+
1505 get_end(fbe_begin)
+
1506 optional
+
1507 end
+
1508
+
1509 # Set the optional value (begin phase)
+
1510 def set_begin(has_value)
+
1511 if (@_buffer.offset + fbe_offset + fbe_size) > @_buffer.size
+
1512 return 0
+
1513 end
+
1514
+
1515 fbe_has_value = has_value ? 1 : 0
+
1516 write_uint8(fbe_offset, fbe_has_value)
+
1517 if fbe_has_value == 0
+
1518 return 0
+
1519 end
+
1520
+
1521 fbe_optional_size = value.fbe_size
+
1522 fbe_optional_offset = @_buffer.allocate(fbe_optional_size) - @_buffer.offset
+
1523 if (fbe_optional_offset <= 0) || ((@_buffer.offset + fbe_optional_offset + fbe_optional_size) > @_buffer.size)
+
1524 return 0
+
1525 end
+
1526
+
1527 write_uint32(fbe_offset + 1, fbe_optional_offset)
+
1528
+
1529 @_buffer.shift(fbe_optional_offset)
+
1530 fbe_optional_offset
+
1531 end
+
1532
+
1533 # Set the optional value (end phase)
+
1534 def set_end(fbe_begin)
+
1535 @_buffer.unshift(fbe_begin)
+
1536 end
+
1537
+
1538 # Set the optional value
+
1539 def set(optional)
+
1540 fbe_begin = set_begin(!optional.nil?)
+
1541 if fbe_begin == 0
+
1542 return
+
1543 end
+
1544 value.set(optional)
+
1545 set_end(fbe_begin)
+
1546 end
+
1547 end
+
1548)CODE";
+
1549
+
1550 // Prepare code template
+
1551 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
1552
+
1553 Write(code);
+
1554}
+
1555
+
1556void GeneratorRuby::GenerateFBEFieldModelArray()
+
1557{
+
1558 std::string code = R"CODE(
+
1559 # Fast Binary Encoding array field model
+
1560 class FieldModelArray < FieldModel
+
1561 def initialize(model, buffer, offset, size)
+
1562 super(buffer, offset)
+
1563 @_model = model
+
1564 @_size = size
+
1565 end
+
1566
+
1567 # Get the field size
+
1568 def fbe_size
+
1569 @_size * @_model.fbe_size
+
1570 end
+
1571
+
1572 # Get the field extra size
+
1573 def fbe_extra
+
1574 0
+
1575 end
+
1576
+
1577 # Get the array offset
+
1578 def offset
+
1579 0
+
1580 end
+
1581
+
1582 # Get the array size
+
1583 def size
+
1584 @_size
+
1585 end
+
1586
+
1587 # Array index operator
+
1588 def [](index)
+
1589 raise RuntimeError, "Model is broken!" if (@_buffer.offset + fbe_offset + fbe_size) > @_buffer.size
+
1590 raise IndexError, "Index is out of bounds!" if index >= @_size
+
1591
+
1592 @_model.fbe_offset = fbe_offset
+
1593 @_model.fbe_shift(index * @_model.fbe_size)
+
1594 @_model
+
1595 end
+
1596
+
1597 # Is the array valid?
+
1598 def valid?
+
1599 verify
+
1600 end
+
1601
+
1602 # Check if the array is valid
+
1603 def verify
+
1604 if (@_buffer.offset + fbe_offset + fbe_size) > @_buffer.size
+
1605 return false
+
1606 end
+
1607
+
1608 @_model.fbe_offset = fbe_offset
+
1609 @_size.times do
+
1610 unless @_model.verify
+
1611 return false
+
1612 end
+
1613 @_model.fbe_shift(@_model.fbe_size)
+
1614 end
+
1615
+
1616 true
+
1617 end
+
1618
+
1619 # Get the array
+
1620 def get(values = Array.new)
+
1621 values.clear
+
1622
+
1623 fbe_model = self[0]
+
1624 @_size.times do
+
1625 value = fbe_model.get
+
1626 values.append(value)
+
1627 fbe_model.fbe_shift(fbe_model.fbe_size)
+
1628 end
+
1629
+
1630 values
+
1631 end
+
1632
+
1633 # Set the array
+
1634 def set(values)
+
1635 raise ArgumentError, "Invalid values parameter!" if values.nil? || !values.is_a?(Array)
+
1636
+
1637 if (@_buffer.offset + fbe_offset + fbe_size) > @_buffer.size
+
1638 return
+
1639 end
+
1640
+
1641 fbe_model = self[0]
+
1642 (0...[values.length, @_size].min).each do |i|
+
1643 fbe_model.set(values[i])
+
1644 fbe_model.fbe_shift(fbe_model.fbe_size)
+
1645 end
+
1646 end
+
1647 end
+
1648)CODE";
+
1649
+
1650 // Prepare code template
+
1651 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
1652
+
1653 Write(code);
+
1654}
+
1655
+
1656void GeneratorRuby::GenerateFBEFieldModelVector()
+
1657{
+
1658 std::string code = R"CODE(
+
1659 # Fast Binary Encoding vector field model
+
1660 class FieldModelVector < FieldModel
+
1661 def initialize(model, buffer, offset)
+
1662 super(buffer, offset)
+
1663 @_model = model
+
1664 end
+
1665
+
1666 # Get the field size
+
1667 def fbe_size
+
1668 4
+
1669 end
+
1670
+
1671 # Get the field extra size
+
1672 def fbe_extra
+
1673 if (@_buffer.offset + fbe_offset + fbe_size) > @_buffer.size
+
1674 return 0
+
1675 end
+
1676
+
1677 fbe_vector_offset = read_uint32(fbe_offset)
+
1678 if (fbe_vector_offset == 0) || ((@_buffer.offset + fbe_vector_offset + 4) > @_buffer.size)
+
1679 return 0
+
1680 end
+
1681
+
1682 fbe_vector_size = read_uint32(fbe_vector_offset)
+
1683
+
1684 fbe_result = 4
+
1685 @_model.fbe_offset = fbe_vector_offset + 4
+
1686 fbe_vector_size.times do
+
1687 fbe_result += @_model.fbe_size + @_model.fbe_extra
+
1688 @_model.fbe_shift(@_model.fbe_size)
+
1689 end
+
1690 fbe_result
+
1691 end
+
1692
+
1693 # Get the vector offset
+
1694 def offset
+
1695 if (@_buffer.offset + fbe_offset + fbe_size) > @_buffer.size
+
1696 return 0
+
1697 end
+
1698
+
1699 read_uint32(fbe_offset)
+
1700 end
+
1701
+
1702 # Get the vector size
+
1703 def size
+
1704 if (@_buffer.offset + fbe_offset + fbe_size) > @_buffer.size
+
1705 return 0
+
1706 end
+
1707
+
1708 fbe_vector_offset = read_uint32(fbe_offset)
+
1709 if (fbe_vector_offset == 0) || ((@_buffer.offset + fbe_vector_offset + 4) > @_buffer.size)
+
1710 return 0
+
1711 end
+
1712
+
1713 read_uint32(fbe_vector_offset)
+
1714 end
+
1715
+
1716 # Vector index operator
+
1717 def [](index)
+
1718 raise RuntimeError, "Model is broken!" if (@_buffer.offset + fbe_offset + fbe_size) > @_buffer.size
+
1719 fbe_vector_offset = read_uint32(fbe_offset)
+
1720 raise RuntimeError, "Model is broken!" if (fbe_vector_offset <= 0) || ((@_buffer.offset + fbe_vector_offset + 4) > @_buffer.size)
+
1721 fbe_vector_size = read_uint32(fbe_vector_offset)
+
1722 raise IndexError, "Index is out of bounds!" if index >= fbe_vector_size
+
1723
+
1724 @_model.fbe_offset = fbe_vector_offset + 4
+
1725 @_model.fbe_shift(index * @_model.fbe_size)
+
1726 @_model
+
1727 end
+
1728
+
1729 # Resize the vector and get its first model
+
1730 def resize(size)
+
1731 fbe_vector_size = size * @_model.fbe_size
+
1732 fbe_vector_offset = @_buffer.allocate(4 + fbe_vector_size) - @_buffer.offset
+
1733 raise RuntimeError, "Model is broken!" if (fbe_vector_offset <= 0) || ((@_buffer.offset + fbe_vector_offset + 4) > @_buffer.size)
+
1734
+
1735 write_uint32(fbe_offset, fbe_vector_offset)
+
1736 write_uint32(fbe_vector_offset, size)
+
1737 write_count(fbe_vector_offset + 4, 0, fbe_vector_size)
+
1738
+
1739 @_model.fbe_offset = fbe_vector_offset + 4
+
1740 @_model
+
1741 end
+
1742
+
1743 # Is the vector valid?
+
1744 def valid?
+
1745 verify
+
1746 end
+
1747
+
1748 # Check if the vector is valid
+
1749 def verify
+
1750 if (@_buffer.offset + fbe_offset + fbe_size) > @_buffer.size
+
1751 return true
+
1752 end
+
1753
+
1754 fbe_vector_offset = read_uint32(fbe_offset)
+
1755 if fbe_vector_offset == 0
+
1756 return true
+
1757 end
+
1758
+
1759 if (@_buffer.offset + fbe_vector_offset + 4) > @_buffer.size
+
1760 return false
+
1761 end
+
1762
+
1763 fbe_vector_size = read_uint32(fbe_vector_offset)
+
1764
+
1765 @_model.fbe_offset = fbe_vector_offset + 4
+
1766 fbe_vector_size.times do
+
1767 unless @_model.verify
+
1768 return false
+
1769 end
+
1770 @_model.fbe_shift(@_model.fbe_size)
+
1771 end
+
1772
+
1773 true
+
1774 end
+
1775
+
1776 # Get the vector
+
1777 def get(values = Array.new)
+
1778 values.clear
+
1779
+
1780 fbe_vector_size = size
+
1781 if fbe_vector_size == 0
+
1782 return values
+
1783 end
+
1784
+
1785 fbe_model = self[0]
+
1786 fbe_vector_size.times do
+
1787 value = fbe_model.get
+
1788 values.append(value)
+
1789 fbe_model.fbe_shift(fbe_model.fbe_size)
+
1790 end
+
1791
+
1792 values
+
1793 end
+
1794
+
1795 # Set the vector
+
1796 def set(values)
+
1797 raise ArgumentError, "Invalid values parameter!" if values.nil? || !values.is_a?(Array)
+
1798
+
1799 if (@_buffer.offset + fbe_offset + fbe_size) > @_buffer.size
+
1800 return
+
1801 end
+
1802
+
1803 fbe_model = resize(values.length)
+
1804 values.each do |value|
+
1805 fbe_model.set(value)
+
1806 fbe_model.fbe_shift(fbe_model.fbe_size)
+
1807 end
+
1808 end
+
1809 end
+
1810)CODE";
+
1811
+
1812 // Prepare code template
+
1813 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
1814
+
1815 Write(code);
+
1816}
+
1817
+
1818void GeneratorRuby::GenerateFBEFieldModelSet()
+
1819{
+
1820 std::string code = R"CODE(
+
1821 # Fast Binary Encoding set field model
+
1822 class FieldModelSet < FieldModel
+
1823 def initialize(model, buffer, offset)
+
1824 super(buffer, offset)
+
1825 @_model = model
+
1826 end
+
1827
+
1828 # Get the field size
+
1829 def fbe_size
+
1830 4
+
1831 end
+
1832
+
1833 # Get the field extra size
+
1834 def fbe_extra
+
1835 if (@_buffer.offset + fbe_offset + fbe_size) > @_buffer.size
+
1836 return 0
+
1837 end
+
1838
+
1839 fbe_set_offset = read_uint32(fbe_offset)
+
1840 if (fbe_set_offset == 0) || ((@_buffer.offset + fbe_set_offset + 4) > @_buffer.size)
+
1841 return 0
+
1842 end
+
1843
+
1844 fbe_set_size = read_uint32(fbe_set_offset)
+
1845
+
1846 fbe_result = 4
+
1847 @_model.fbe_offset = fbe_set_offset + 4
+
1848 fbe_set_size.times do
+
1849 fbe_result += @_model.fbe_size + @_model.fbe_extra
+
1850 @_model.fbe_shift(@_model.fbe_size)
+
1851 end
+
1852 fbe_result
+
1853 end
+
1854
+
1855 # Get the set value offset
+
1856 def offset
+
1857 if (@_buffer.offset + fbe_offset + fbe_size) > @_buffer.size
+
1858 return 0
+
1859 end
+
1860
+
1861 read_uint32(fbe_offset)
+
1862 end
+
1863
+
1864 # Get the set value size
+
1865 def size
+
1866 if (@_buffer.offset + fbe_offset + fbe_size) > @_buffer.size
+
1867 return 0
+
1868 end
+
1869
+
1870 fbe_set_offset = read_uint32(fbe_offset)
+
1871 if (fbe_set_offset == 0) || ((@_buffer.offset + fbe_set_offset + 4) > @_buffer.size)
+
1872 return 0
+
1873 end
+
1874
+
1875 read_uint32(fbe_set_offset)
+
1876 end
+
1877
+
1878 # Set index operator
+
1879 def [](index)
+
1880 raise RuntimeError, "Model is broken!" if (@_buffer.offset + fbe_offset + fbe_size) > @_buffer.size
+
1881 fbe_set_offset = read_uint32(fbe_offset)
+
1882 raise RuntimeError, "Model is broken!" if (fbe_set_offset <= 0) || ((@_buffer.offset + fbe_set_offset + 4) > @_buffer.size)
+
1883 fbe_set_size = read_uint32(fbe_set_offset)
+
1884 raise IndexError, "Index is out of bounds!" if index >= fbe_set_size
+
1885
+
1886 @_model.fbe_offset = fbe_set_offset + 4
+
1887 @_model.fbe_shift(index * @_model.fbe_size)
+
1888 @_model
+
1889 end
+
1890
+
1891 # Resize the set and get its first model
+
1892 def resize(size)
+
1893 fbe_set_size = size * @_model.fbe_size
+
1894 fbe_set_offset = @_buffer.allocate(4 + fbe_set_size) - @_buffer.offset
+
1895 raise RuntimeError, "Model is broken!" if (fbe_set_offset <= 0) || ((@_buffer.offset + fbe_set_offset + 4) > @_buffer.size)
+
1896
+
1897 write_uint32(fbe_offset, fbe_set_offset)
+
1898 write_uint32(fbe_set_offset, size)
+
1899 write_count(fbe_set_offset + 4, 0, fbe_set_size)
+
1900
+
1901 @_model.fbe_offset = fbe_set_offset + 4
+
1902 @_model
+
1903 end
+
1904
+
1905 # Is the set valid?
+
1906 def valid?
+
1907 verify
+
1908 end
+
1909
+
1910 # Check if the set value is valid
+
1911 def verify
+
1912 if (@_buffer.offset + fbe_offset + fbe_size) > @_buffer.size
+
1913 return true
+
1914 end
+
1915
+
1916 fbe_set_offset = read_uint32(fbe_offset)
+
1917 if fbe_set_offset == 0
+
1918 return true
+
1919 end
+
1920
+
1921 if (@_buffer.offset + fbe_set_offset + 4) > @_buffer.size
+
1922 return false
+
1923 end
+
1924
+
1925 fbe_set_size = read_uint32(fbe_set_offset)
+
1926
+
1927 @_model.fbe_offset = fbe_set_offset + 4
+
1928 fbe_set_size.times do
+
1929 unless @_model.verify
+
1930 return false
+
1931 end
+
1932 @_model.fbe_shift(@_model.fbe_size)
+
1933 end
+
1934
+
1935 true
+
1936 end
+
1937
+
1938 # Get the set value
+
1939 def get(values = Set.new)
+
1940 values.clear
+
1941
+
1942 fbe_set_size = size
+
1943 if fbe_set_size == 0
+
1944 return values
+
1945 end
+
1946
+
1947 fbe_model = self[0]
+
1948 fbe_set_size.times do
+
1949 value = fbe_model.get
+
1950 values.add(value)
+
1951 fbe_model.fbe_shift(fbe_model.fbe_size)
+
1952 end
+
1953
+
1954 values
+
1955 end
+
1956
+
1957 # Set the set value
+
1958 def set(values)
+
1959 raise ArgumentError, "Invalid values parameter!" if values.nil? || !values.is_a?(Set)
+
1960
+
1961 if (@_buffer.offset + fbe_offset + fbe_size) > @_buffer.size
+
1962 return
+
1963 end
+
1964
+
1965 fbe_model = resize(values.length)
+
1966 values.each do |value|
+
1967 fbe_model.set(value)
+
1968 fbe_model.fbe_shift(fbe_model.fbe_size)
+
1969 end
+
1970 end
+
1971 end
+
1972)CODE";
+
1973
+
1974 // Prepare code template
+
1975 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
1976
+
1977 Write(code);
+
1978}
+
1979
+
1980void GeneratorRuby::GenerateFBEFieldModelMap()
+
1981{
+
1982 std::string code = R"CODE(
+
1983 # Fast Binary Encoding map field model
+
1984 class FieldModelMap < FieldModel
+
1985 def initialize(model_key, model_value, buffer, offset)
+
1986 super(buffer, offset)
+
1987 @_model_key = model_key
+
1988 @_model_value = model_value
+
1989 end
+
1990
+
1991 # Get the field size
+
1992 def fbe_size
+
1993 4
+
1994 end
+
1995
+
1996 # Get the field extra size
+
1997 def fbe_extra
+
1998 if (@_buffer.offset + fbe_offset + fbe_size) > @_buffer.size
+
1999 return 0
+
2000 end
+
2001
+
2002 fbe_map_offset = read_uint32(fbe_offset)
+
2003 if (fbe_map_offset == 0) || ((@_buffer.offset + fbe_map_offset + 4) > @_buffer.size)
+
2004 return 0
+
2005 end
+
2006
+
2007 fbe_map_size = read_uint32(fbe_map_offset)
+
2008
+
2009 fbe_result = 4
+
2010 @_model_key.fbe_offset = fbe_map_offset + 4
+
2011 @_model_value.fbe_offset = fbe_map_offset + 4 + @_model_key.fbe_size
+
2012 fbe_map_size.times do
+
2013 fbe_result += @_model_key.fbe_size + @_model_key.fbe_extra
+
2014 @_model_key.fbe_shift(@_model_key.fbe_size + @_model_value.fbe_size)
+
2015 fbe_result += @_model_value.fbe_size + @_model_value.fbe_extra
+
2016 @_model_value.fbe_shift(@_model_key.fbe_size + @_model_value.fbe_size)
+
2017 end
+
2018 fbe_result
+
2019 end
+
2020
+
2021 # Get the map offset
+
2022 def offset
+
2023 if (@_buffer.offset + fbe_offset + fbe_size) > @_buffer.size
+
2024 return 0
+
2025 end
+
2026
+
2027 read_uint32(fbe_offset)
+
2028 end
+
2029
+
2030 # Get the map size
+
2031 def size
+
2032 if (@_buffer.offset + fbe_offset + fbe_size) > @_buffer.size
+
2033 return 0
+
2034 end
+
2035
+
2036 fbe_map_offset = read_uint32(fbe_offset)
+
2037 if (fbe_map_offset == 0) || ((@_buffer.offset + fbe_map_offset + 4) > @_buffer.size)
+
2038 return 0
+
2039 end
+
2040
+
2041 read_uint32(fbe_map_offset)
+
2042 end
+
2043
+
2044 # Map index operator
+
2045 def [](index)
+
2046 raise RuntimeError, "Model is broken!" if (@_buffer.offset + fbe_offset + fbe_size) > @_buffer.size
+
2047 fbe_map_offset = read_uint32(fbe_offset)
+
2048 raise RuntimeError, "Model is broken!" if (fbe_map_offset <= 0) || ((@_buffer.offset + fbe_map_offset + 4) > @_buffer.size)
+
2049 fbe_map_size = read_uint32(fbe_map_offset)
+
2050 raise IndexError, "Index is out of bounds!" if index >= fbe_map_size
+
2051
+
2052 @_model_key.fbe_offset = fbe_map_offset + 4
+
2053 @_model_value.fbe_offset = fbe_map_offset + 4 + @_model_key.fbe_size
+
2054 @_model_key.fbe_shift(index * (@_model_key.fbe_size + @_model_value.fbe_size))
+
2055 @_model_value.fbe_shift(index * (@_model_key.fbe_size + @_model_value.fbe_size))
+
2056 [@_model_key, @_model_value]
+
2057 end
+
2058
+
2059 # Resize the map and get its first model
+
2060 def resize(size)
+
2061 fbe_map_size = size * (@_model_key.fbe_size + @_model_value.fbe_size)
+
2062 fbe_map_offset = @_buffer.allocate(4 + fbe_map_size) - @_buffer.offset
+
2063 raise RuntimeError, "Model is broken!" if (fbe_map_offset <= 0) || ((@_buffer.offset + fbe_map_offset + 4) > @_buffer.size)
+
2064
+
2065 write_uint32(fbe_offset, fbe_map_offset)
+
2066 write_uint32(fbe_map_offset, size)
+
2067 write_count(fbe_map_offset + 4, 0, fbe_map_size)
+
2068
+
2069 @_model_key.fbe_offset = fbe_map_offset + 4
+
2070 @_model_value.fbe_offset = fbe_map_offset + 4 + @_model_key.fbe_size
+
2071 [@_model_key, @_model_value]
+
2072 end
+
2073
+
2074 # Is the map valid?
+
2075 def valid?
+
2076 verify
+
2077 end
+
2078
+
2079 # Check if the map is valid
+
2080 def verify
+
2081 if (@_buffer.offset + fbe_offset + fbe_size) > @_buffer.size
+
2082 return true
+
2083 end
+
2084
+
2085 fbe_map_offset = read_uint32(fbe_offset)
+
2086 if fbe_map_offset == 0
+
2087 return true
+
2088 end
+
2089
+
2090 if (@_buffer.offset + fbe_map_offset + 4) > @_buffer.size
+
2091 return false
+
2092 end
+
2093
+
2094 fbe_map_size = read_uint32(fbe_map_offset)
+
2095
+
2096 @_model_key.fbe_offset = fbe_map_offset + 4
+
2097 @_model_value.fbe_offset = fbe_map_offset + 4 + @_model_key.fbe_size
+
2098 fbe_map_size.times do
+
2099 unless @_model_key.verify
+
2100 return false
+
2101 end
+
2102 @_model_key.fbe_shift(@_model_key.fbe_size + @_model_value.fbe_size)
+
2103 unless @_model_value.verify
+
2104 return false
+
2105 end
+
2106 @_model_value.fbe_shift(@_model_key.fbe_size + @_model_value.fbe_size)
+
2107 end
+
2108
+
2109 true
+
2110 end
+
2111
+
2112 # Get the map
+
2113 def get(values = Hash.new)
+
2114 values.clear
+
2115
+
2116 fbe_map_size = size
+
2117 if fbe_map_size == 0
+
2118 return values
+
2119 end
+
2120
+
2121 fbe_model_key, fbe_model_value = self[0]
+
2122 fbe_map_size.times do
+
2123 key = fbe_model_key.get
+
2124 value = fbe_model_value.get
+
2125 values[key] = value
+
2126 fbe_model_key.fbe_shift(fbe_model_key.fbe_size + fbe_model_value.fbe_size)
+
2127 fbe_model_value.fbe_shift(fbe_model_key.fbe_size + fbe_model_value.fbe_size)
+
2128 end
+
2129
+
2130 values
+
2131 end
+
2132
+
2133 # Set the map
+
2134 def set(values)
+
2135 raise ArgumentError, "Invalid values parameter!" if values.nil? || !values.is_a?(Hash)
+
2136
+
2137 if (@_buffer.offset + fbe_offset + fbe_size) > @_buffer.size
+
2138 return
+
2139 end
+
2140
+
2141 fbe_model_key, fbe_model_value = resize(values.length)
+
2142 values.each do |key, value|
+
2143 fbe_model_key.set(key)
+
2144 fbe_model_key.fbe_shift(fbe_model_key.fbe_size + fbe_model_value.fbe_size)
+
2145 fbe_model_value.set(value)
+
2146 fbe_model_value.fbe_shift(fbe_model_key.fbe_size + fbe_model_value.fbe_size)
+
2147 end
+
2148 end
+
2149 end
+
2150)CODE";
+
2151
+
2152 // Prepare code template
+
2153 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2154
+
2155 Write(code);
+
2156}
+
2157
+
2158void GeneratorRuby::GenerateFBEFinalModel()
+
2159{
+
2160 std::string code = R"CODE(
+
2161 # Fast Binary Encoding final model
+
2162 class FinalModel < FieldModelBase
+
2163 def initialize(buffer, offset)
+
2164 super(buffer, offset)
+
2165 end
+
2166
+
2167 # Is the value valid?
+
2168 def valid?
+
2169 verify
+
2170 end
+
2171
+
2172 # Check if the value is valid
+
2173 def verify
+
2174 raise NotImplementedError, "verify() method not implemented!"
+
2175 end
+
2176 end
+
2177)CODE";
+
2178
+
2179 // Prepare code template
+
2180 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2181
+
2182 Write(code);
+
2183}
+
2184
+
2185void GeneratorRuby::GenerateFBEFinalModel(const std::string& name, const std::string& type, const std::string& size, const std::string& defaults)
+
2186{
+
2187 std::string code = R"CODE(
+
2188 # Fast Binary Encoding _TYPE_ final model
+
2189 class FinalModel_NAME_ < FinalModel
+
2190 def initialize(buffer, offset)
+
2191 super(buffer, offset)
+
2192 end
+
2193
+
2194 # Get the allocation size
+
2195 # noinspection RubyUnusedLocalVariable
+
2196 def fbe_allocation_size(value)
+
2197 fbe_size
+
2198 end
+
2199
+
2200 # Get the final size
+
2201 def fbe_size
+
2202 _SIZE_
+
2203 end
+
2204
+
2205 # Is the value valid?
+
2206 def valid?
+
2207 verify
+
2208 end
+
2209
+
2210 # Check if the value is valid
+
2211 def verify
+
2212 if (@_buffer.offset + fbe_offset + fbe_size) > @_buffer.size
+
2213 return Integer::MAX
+
2214 end
+
2215
+
2216 fbe_size
+
2217 end
+
2218
+
2219 # Get the value
+
2220 def get
+
2221 if (@_buffer.offset + fbe_offset + fbe_size) > @_buffer.size
+
2222 return [_DEFAULTS_, 0]
+
2223 end
+
2224
+
2225 [read__TYPE_(fbe_offset), fbe_size]
+
2226 end
+
2227
+
2228 # Set the value
+
2229 def set(value)
+
2230 if (@_buffer.offset + fbe_offset + fbe_size) > @_buffer.size
+
2231 return 0
+
2232 end
+
2233
+
2234 write__TYPE_(fbe_offset, value)
+
2235 fbe_size
+
2236 end
+
2237 end
+
2238)CODE";
+
2239
+
2240 // Prepare code template
+
2241 code = std::regex_replace(code, std::regex("_NAME_"), name);
+
2242 code = std::regex_replace(code, std::regex("_TYPE_"), type);
+
2243 code = std::regex_replace(code, std::regex("_SIZE_"), size);
+
2244 code = std::regex_replace(code, std::regex("_DEFAULTS_"), defaults);
+
2245 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2246
+
2247 Write(code);
+
2248}
+
2249
+
2250void GeneratorRuby::GenerateFBEFinalModelDecimal()
+
2251{
+
2252 std::string code = R"CODE(
+
2253 # Fast Binary Encoding decimal final model
+
2254 class FinalModelDecimal < FieldModel
+
2255 def initialize(buffer, offset)
+
2256 super(buffer, offset)
+
2257 end
+
2258
+
2259 # Get the allocation size
+
2260 # noinspection RubyUnusedLocalVariable
+
2261 def fbe_allocation_size(value)
+
2262 fbe_size
+
2263 end
+
2264
+
2265 # Get the final size
+
2266 def fbe_size
+
2267 16
+
2268 end
+
2269
+
2270 # Is the decimal value valid?
+
2271 def valid?
+
2272 verify
+
2273 end
+
2274
+
2275 # Check if the decimal value is valid
+
2276 def verify
+
2277 if (@_buffer.offset + fbe_offset + fbe_size) > @_buffer.size
+
2278 return Integer::MAX
+
2279 end
+
2280
+
2281 fbe_size
+
2282 end
+
2283
+
2284 # Get the decimal value
+
2285 def get
+
2286 if (@_buffer.offset + fbe_offset + fbe_size) > @_buffer.size
+
2287 return [BigDecimal(0), 0]
+
2288 end
+
2289
+
2290 # Read decimal parts
+
2291 low = read_uint32(fbe_offset)
+
2292 mid = read_uint32(fbe_offset + 4)
+
2293 high = read_uint32(fbe_offset + 8)
+
2294 flags = read_uint32(fbe_offset + 12)
+
2295
+
2296 # Calculate decimal value
+
2297 negative = (flags & 0x80000000) != 0
+
2298 scale = (flags & 0x7FFFFFFF) >> 16
+
2299 result = BigDecimal(high) * 18446744073709551616
+
2300 result += BigDecimal(mid) * 4294967296
+
2301 result += BigDecimal(low)
+
2302 result /= 10 ** scale
+
2303 result = -result if negative
+
2304
+
2305 # Return decimal value
+
2306 [result, fbe_size]
+
2307 end
+
2308
+
2309 # Set the decimal value
+
2310 def set(value)
+
2311 if (@_buffer.offset + fbe_offset + fbe_size) > @_buffer.size
+
2312 return 0
+
2313 end
+
2314
+
2315 # Extract decimal parts
+
2316 sign, significant_digits, _, exponent = value.split
+
2317 number = significant_digits.to_i(10)
+
2318 if exponent > significant_digits.length
+
2319 number *= 10 ** (exponent - 1)
+
2320 scale = 0
+
2321 else
+
2322 scale = significant_digits.length - exponent
+
2323 end
+
2324
+
2325 # Check for decimal number overflow
+
2326 bits = number.bit_length
+
2327 if (bits < 0) || (bits > 96)
+
2328 # Value too big for .NET Decimal (bit length is limited to [0, 96])
+
2329 write_count(fbe_offset, 0, fbe_size)
+
2330 return
+
2331 end
+
2332
+
2333 # Check for decimal scale overflow
+
2334 if (scale < 0) || (scale > 28)
+
2335 # Value scale exceeds .NET Decimal limit of [0, 28]
+
2336 write_count(fbe_offset, 0, fbe_size)
+
2337 return
+
2338 end
+
2339
+
2340 # Write unscaled value to bytes 0-11
+
2341 bytes = []
+
2342 while number > 0
+
2343 bytes.insert(-1, number & 0xFF)
+
2344 number >>= 8
+
2345 end
+
2346 bytes = bytes.pack("C*")
+
2347 write_bytes(fbe_offset, bytes)
+
2348 write_count(fbe_offset + bytes.length, 0, 12 - bytes.length)
+
2349
+
2350 # Write scale at byte 14
+
2351 write_byte(fbe_offset + 14, scale)
+
2352
+
2353 # Write signum at byte 15
+
2354 write_byte(fbe_offset + 15, (sign == -1) ? 0x80 : 0)
+
2355
+
2356 fbe_size
+
2357 end
+
2358 end
+
2359)CODE";
+
2360
+
2361 // Prepare code template
+
2362 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2363
+
2364 Write(code);
+
2365}
+
2366
+
2367void GeneratorRuby::GenerateFBEFinalModelBytes()
+
2368{
+
2369 std::string code = R"CODE(
+
2370 # Fast Binary Encoding bytes final model
+
2371 class FinalModelBytes < FinalModel
+
2372 def initialize(buffer, offset)
+
2373 super(buffer, offset)
+
2374 end
+
2375
+
2376 # Get the allocation size
+
2377 def fbe_allocation_size(value)
+
2378 4 + value.length
+
2379 end
+
2380
+
2381 # Is the bytes value valid?
+
2382 def valid?
+
2383 verify
+
2384 end
+
2385
+
2386 # Check if the bytes value is valid
+
2387 def verify
+
2388 if (@_buffer.offset + fbe_offset + 4) > @_buffer.size
+
2389 return Integer::MAX
+
2390 end
+
2391
+
2392 fbe_bytes_size = read_uint32(fbe_offset)
+
2393 if (@_buffer.offset + fbe_offset + 4 + fbe_bytes_size) > @_buffer.size
+
2394 return Integer::MAX
+
2395 end
+
2396
+
2397 4 + fbe_bytes_size
+
2398 end
+
2399
+
2400 # Get the bytes value
+
2401 def get
+
2402 if (@_buffer.offset + fbe_offset + 4) > @_buffer.size
+
2403 return ['', 0]
+
2404 end
+
2405
+
2406 fbe_bytes_size = read_uint32(fbe_offset)
+
2407 if (@_buffer.offset + fbe_offset + 4 + fbe_bytes_size) > @_buffer.size
+
2408 return ['', 4]
+
2409 end
+
2410
+
2411 [read_bytes(fbe_offset + 4, fbe_bytes_size), (4 + fbe_bytes_size)]
+
2412 end
+
2413
+
2414 # Set the bytes value
+
2415 def set(value)
+
2416 raise ArgumentError, "Invalid bytes value!" if value.nil? || !value.is_a?(String)
+
2417
+
2418 if (@_buffer.offset + fbe_offset + 4) > @_buffer.size
+
2419 return 0
+
2420 end
+
2421
+
2422 fbe_bytes_size = value.length
+
2423 if (@_buffer.offset + fbe_offset + 4 + fbe_bytes_size) > @_buffer.size
+
2424 return 4
+
2425 end
+
2426
+
2427 write_uint32(fbe_offset, fbe_bytes_size)
+
2428 write_bytes(fbe_offset + 4, value)
+
2429 4 + fbe_bytes_size
+
2430 end
+
2431 end
+
2432)CODE";
+
2433
+
2434 // Prepare code template
+
2435 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2436
+
2437 Write(code);
+
2438}
+
2439
+
2440void GeneratorRuby::GenerateFBEFinalModelString()
+
2441{
+
2442 std::string code = R"CODE(
+
2443 # Fast Binary Encoding string final model
+
2444 class FinalModelString < FinalModel
+
2445 def initialize(buffer, offset)
+
2446 super(buffer, offset)
+
2447 end
+
2448
+
2449 # Get the allocation size
+
2450 def fbe_allocation_size(value)
+
2451 4 + 3 * (value.length + 1)
+
2452 end
+
2453
+
2454 # Is the string value valid?
+
2455 def valid?
+
2456 verify
+
2457 end
+
2458
+
2459 # Check if the string value is valid
+
2460 def verify
+
2461 if (@_buffer.offset + fbe_offset + 4) > @_buffer.size
+
2462 return Integer::MAX
+
2463 end
+
2464
+
2465 fbe_string_size = read_uint32(fbe_offset)
+
2466 if (@_buffer.offset + fbe_offset + 4 + fbe_string_size) > @_buffer.size
+
2467 return Integer::MAX
+
2468 end
+
2469
+
2470 4 + fbe_string_size
+
2471 end
+
2472
+
2473 # Get the string value
+
2474 def get
+
2475 if (@_buffer.offset + fbe_offset + 4) > @_buffer.size
+
2476 return ['', 0]
+
2477 end
+
2478
+
2479 fbe_string_size = read_uint32(fbe_offset)
+
2480 if (@_buffer.offset + fbe_offset + 4 + fbe_string_size) > @_buffer.size
+
2481 return ['', 4]
+
2482 end
+
2483
+
2484 data = read_bytes(fbe_offset + 4, fbe_string_size)
+
2485 [data.encode!('utf-8'), (4 + fbe_string_size)]
+
2486 end
+
2487
+
2488 # Set the string value
+
2489 def set(value)
+
2490 raise ArgumentError, "Invalid string value!" if value.nil? || !value.is_a?(String)
+
2491
+
2492 if (@_buffer.offset + fbe_offset + 4) > @_buffer.size
+
2493 return 0
+
2494 end
+
2495
+
2496 data = value.encode('utf-8')
+
2497
+
2498 fbe_string_size = data.length
+
2499 if (@_buffer.offset + fbe_offset + 4 + fbe_string_size) > @_buffer.size
+
2500 return 4
+
2501 end
+
2502
+
2503 write_uint32(fbe_offset, fbe_string_size)
+
2504 write_bytes(fbe_offset + 4, data)
+
2505 4 + fbe_string_size
+
2506 end
+
2507 end
+
2508)CODE";
+
2509
+
2510 // Prepare code template
+
2511 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2512
+
2513 Write(code);
+
2514}
+
2515
+
2516void GeneratorRuby::GenerateFBEFinalModelOptional()
+
2517{
+
2518 std::string code = R"CODE(
+
2519 # Fast Binary Encoding optional final model
+
2520 class FinalModelOptional < FinalModel
+
2521 def initialize(model, buffer, offset)
+
2522 super(buffer, offset)
+
2523 @_model = model
+
2524 @_model.fbe_offset = 0
+
2525 end
+
2526
+
2527 # Get the allocation size
+
2528 def fbe_allocation_size(optional)
+
2529 1 + (optional ? value.fbe_allocation_size(optional) : 0)
+
2530 end
+
2531
+
2532 # Checks if the object contains a value
+
2533 def empty?
+
2534 has_value?
+
2535 end
+
2536
+
2537 # Checks if the object contains a value
+
2538 def has_value?
+
2539 if (@_buffer.offset + fbe_offset + 1) > @_buffer.size
+
2540 return false
+
2541 end
+
2542
+
2543 fbe_has_value = read_uint8(fbe_offset)
+
2544 fbe_has_value != 0
+
2545 end
+
2546
+
2547 # Get the base final model value
+
2548 def value
+
2549 @_model
+
2550 end
+
2551
+
2552 # Is the optional value valid?
+
2553 def valid?
+
2554 verify
+
2555 end
+
2556
+
2557 # Check if the optional value is valid
+
2558 def verify
+
2559 if (@_buffer.offset + fbe_offset + 1) > @_buffer.size
+
2560 return Integer::MAX
+
2561 end
+
2562
+
2563 fbe_has_value = read_uint8(fbe_offset)
+
2564 if fbe_has_value == 0
+
2565 return 1
+
2566 end
+
2567
+
2568 @_buffer.shift(fbe_offset + 1)
+
2569 fbe_result = value.verify
+
2570 @_buffer.unshift(fbe_offset + 1)
+
2571 1 + fbe_result
+
2572 end
+
2573
+
2574 # Get the optional value
+
2575 def get
+
2576 if (@_buffer.offset + fbe_offset + 1) > @_buffer.size
+
2577 return [nil, 0]
+
2578 end
+
2579
+
2580 unless has_value?
+
2581 return [nil, 1]
+
2582 end
+
2583
+
2584 @_buffer.shift(fbe_offset + 1)
+
2585 optional = value.get
+
2586 @_buffer.unshift(fbe_offset + 1)
+
2587 [optional[0], (1 + optional[1])]
+
2588 end
+
2589
+
2590 # Set the optional value
+
2591 def set(optional)
+
2592 if (@_buffer.offset + fbe_offset + 1) > @_buffer.size
+
2593 return 0
+
2594 end
+
2595
+
2596 fbe_has_value = optional ? 1 : 0
+
2597 write_uint8(fbe_offset, fbe_has_value)
+
2598 if fbe_has_value == 0
+
2599 return 1
+
2600 end
+
2601
+
2602 @_buffer.shift(fbe_offset + 1)
+
2603 size = value.set(optional)
+
2604 @_buffer.unshift(fbe_offset + 1)
+
2605 1 + size
+
2606 end
+
2607 end
+
2608)CODE";
+
2609
+
2610 // Prepare code template
+
2611 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2612
+
2613 Write(code);
+
2614}
+
2615
+
2616void GeneratorRuby::GenerateFBEFinalModelArray()
+
2617{
+
2618 std::string code = R"CODE(
+
2619 # Fast Binary Encoding array final model
+
2620 class FinalModelArray < FinalModel
+
2621 def initialize(model, buffer, offset, size)
+
2622 super(buffer, offset)
+
2623 @_model = model
+
2624 @_size = size
+
2625 end
+
2626
+
2627 # Get the allocation size
+
2628 def fbe_allocation_size(values)
+
2629 size = 0
+
2630 [values.length, @_size].min.times do |i|
+
2631 size += @_model.fbe_allocation_size(values[i])
+
2632 end
+
2633 size
+
2634 end
+
2635
+
2636 # Is the array valid?
+
2637 def valid?
+
2638 verify
+
2639 end
+
2640
+
2641 # Check if the array is valid
+
2642 def verify
+
2643 if (@_buffer.offset + fbe_offset) > @_buffer.size
+
2644 return Integer::MAX
+
2645 end
+
2646
+
2647 size = 0
+
2648 @_model.fbe_offset = fbe_offset
+
2649 @_size.times do
+
2650 offset = @_model.verify
+
2651 if offset == Integer::MAX
+
2652 return Integer::MAX
+
2653 end
+
2654 @_model.fbe_shift(offset)
+
2655 size += offset
+
2656 end
+
2657 size
+
2658 end
+
2659
+
2660 # Get the array
+
2661 def get(values = Array.new)
+
2662 values.clear
+
2663
+
2664 if (@_buffer.offset + fbe_offset) > @_buffer.size
+
2665 return [values, 0]
+
2666 end
+
2667
+
2668 size = 0
+
2669 @_model.fbe_offset = fbe_offset
+
2670 @_size.times do
+
2671 value = @_model.get
+
2672 values.append(value[0])
+
2673 @_model.fbe_shift(value[1])
+
2674 size += value[1]
+
2675 end
+
2676 [values, size]
+
2677 end
+
2678
+
2679 # Set the array
+
2680 def set(values)
+
2681 raise ArgumentError, "Invalid values parameter!" if values.nil? || !values.is_a?(Array)
+
2682
+
2683 if (@_buffer.offset + fbe_offset) > @_buffer.size
+
2684 return 0
+
2685 end
+
2686
+
2687 size = 0
+
2688 @_model.fbe_offset = fbe_offset
+
2689 [values.length, @_size].min.times do |i|
+
2690 offset = @_model.set(values[i])
+
2691 @_model.fbe_shift(offset)
+
2692 size += offset
+
2693 end
+
2694 size
+
2695 end
+
2696 end
+
2697)CODE";
+
2698
+
2699 // Prepare code template
+
2700 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2701
+
2702 Write(code);
+
2703}
+
2704
+
2705void GeneratorRuby::GenerateFBEFinalModelVector()
+
2706{
+
2707 std::string code = R"CODE(
+
2708 # Fast Binary Encoding vector final model
+
2709 class FinalModelVector < FinalModel
+
2710 def initialize(model, buffer, offset)
+
2711 super(buffer, offset)
+
2712 @_model = model
+
2713 end
+
2714
+
2715 # Get the allocation size
+
2716 def fbe_allocation_size(values)
+
2717 size = 4
+
2718 values.each do |value|
+
2719 size += @_model.fbe_allocation_size(value)
+
2720 end
+
2721 size
+
2722 end
+
2723
+
2724 # Is the vector valid?
+
2725 def valid?
+
2726 verify
+
2727 end
+
2728
+
2729 # Check if the vector is valid
+
2730 def verify
+
2731 if (@_buffer.offset + fbe_offset + 4) > @_buffer.size
+
2732 return Integer::MAX
+
2733 end
+
2734
+
2735 fbe_vector_size = read_uint32(fbe_offset)
+
2736
+
2737 size = 4
+
2738 @_model.fbe_offset = fbe_offset + 4
+
2739 fbe_vector_size.times do
+
2740 offset = @_model.verify
+
2741 if offset == Integer::MAX
+
2742 return Integer::MAX
+
2743 end
+
2744 @_model.fbe_shift(offset)
+
2745 size += offset
+
2746 end
+
2747 size
+
2748 end
+
2749
+
2750 # Get the vector
+
2751 def get(values = Array.new)
+
2752 values.clear
+
2753
+
2754 if (@_buffer.offset + fbe_offset + 4) > @_buffer.size
+
2755 return [values, 0]
+
2756 end
+
2757
+
2758 fbe_vector_size = read_uint32(fbe_offset)
+
2759 if fbe_vector_size == 0
+
2760 return [values, 4]
+
2761 end
+
2762
+
2763 size = 4
+
2764 @_model.fbe_offset = fbe_offset + 4
+
2765 fbe_vector_size.times do
+
2766 value = @_model.get
+
2767 values.append(value[0])
+
2768 @_model.fbe_shift(value[1])
+
2769 size += value[1]
+
2770 end
+
2771 [values, size]
+
2772 end
+
2773
+
2774 # Set the vector
+
2775 def set(values)
+
2776 raise ArgumentError, "Invalid values parameter!" if values.nil? || !values.is_a?(Array)
+
2777
+
2778 if (@_buffer.offset + fbe_offset + 4) > @_buffer.size
+
2779 return 0
+
2780 end
+
2781
+
2782 write_uint32(fbe_offset, values.length)
+
2783
+
2784 size = 4
+
2785 @_model.fbe_offset = fbe_offset + 4
+
2786 values.each do |value|
+
2787 offset = @_model.set(value)
+
2788 @_model.fbe_shift(offset)
+
2789 size += offset
+
2790 end
+
2791 size
+
2792 end
+
2793 end
+
2794)CODE";
+
2795
+
2796 // Prepare code template
+
2797 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2798
+
2799 Write(code);
+
2800}
+
2801
+
2802void GeneratorRuby::GenerateFBEFinalModelSet()
+
2803{
+
2804 std::string code = R"CODE(
+
2805 # Fast Binary Encoding set final model
+
2806 class FinalModelSet < FinalModel
+
2807 def initialize(model, buffer, offset)
+
2808 super(buffer, offset)
+
2809 @_model = model
+
2810 end
+
2811
+
2812 # Get the allocation size
+
2813 def fbe_allocation_size(values)
+
2814 size = 4
+
2815 values.each do |value|
+
2816 size += @_model.fbe_allocation_size(value)
+
2817 end
+
2818 size
+
2819 end
+
2820
+
2821 # Is the set valid?
+
2822 def valid?
+
2823 verify
+
2824 end
+
2825
+
2826 # Check if the set value is valid
+
2827 def verify
+
2828 if (@_buffer.offset + fbe_offset + 4) > @_buffer.size
+
2829 return Integer::MAX
+
2830 end
+
2831
+
2832 fbe_set_size = read_uint32(fbe_offset)
+
2833
+
2834 size = 4
+
2835 @_model.fbe_offset = fbe_offset + 4
+
2836 fbe_set_size.times do
+
2837 offset = @_model.verify
+
2838 if offset == Integer::MAX
+
2839 return Integer::MAX
+
2840 end
+
2841 @_model.fbe_shift(offset)
+
2842 size += offset
+
2843 end
+
2844 size
+
2845 end
+
2846
+
2847 # Get the set value
+
2848 def get(values = Set.new)
+
2849 values.clear
+
2850
+
2851 if (@_buffer.offset + fbe_offset + 4) > @_buffer.size
+
2852 return [values, 0]
+
2853 end
+
2854
+
2855 fbe_set_size = read_uint32(fbe_offset)
+
2856 if fbe_set_size == 0
+
2857 return [values, 4]
+
2858 end
+
2859
+
2860 size = 4
+
2861 @_model.fbe_offset = fbe_offset + 4
+
2862 fbe_set_size.times do
+
2863 value = @_model.get
+
2864 values.add(value[0])
+
2865 @_model.fbe_shift(value[1])
+
2866 size += value[1]
+
2867 end
+
2868 [values, size]
+
2869 end
+
2870
+
2871 # Set the set value
+
2872 def set(values)
+
2873 raise ArgumentError, "Invalid values parameter!" if values.nil? || !values.is_a?(Set)
+
2874
+
2875 if (@_buffer.offset + fbe_offset + 4) > @_buffer.size
+
2876 return 0
+
2877 end
+
2878
+
2879 write_uint32(fbe_offset, values.length)
+
2880
+
2881 size = 4
+
2882 @_model.fbe_offset = fbe_offset + 4
+
2883 values.each do |value|
+
2884 offset = @_model.set(value)
+
2885 @_model.fbe_shift(offset)
+
2886 size += offset
+
2887 end
+
2888 size
+
2889 end
+
2890 end
+
2891)CODE";
+
2892
+
2893 // Prepare code template
+
2894 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2895
+
2896 Write(code);
+
2897}
+
2898
+
2899void GeneratorRuby::GenerateFBEFinalModelMap()
+
2900{
+
2901 std::string code = R"CODE(
+
2902 # Fast Binary Encoding map final model
+
2903 class FinalModelMap < FinalModel
+
2904 def initialize(model_key, model_value, buffer, offset)
+
2905 super(buffer, offset)
+
2906 @_model_key = model_key
+
2907 @_model_value = model_value
+
2908 end
+
2909
+
2910 # Get the allocation size
+
2911 def fbe_allocation_size(values)
+
2912 size = 4
+
2913 values.each do |key, value|
+
2914 size += @_model_key.fbe_allocation_size(key)
+
2915 size += @_model_value.fbe_allocation_size(value)
+
2916 end
+
2917 size
+
2918 end
+
2919
+
2920 # Is the map valid?
+
2921 def valid?
+
2922 verify
+
2923 end
+
2924
+
2925 # Check if the map is valid
+
2926 def verify
+
2927 if (@_buffer.offset + fbe_offset + 4) > @_buffer.size
+
2928 return Integer::MAX
+
2929 end
+
2930
+
2931 fbe_map_size = read_uint32(fbe_offset)
+
2932
+
2933 size = 4
+
2934 @_model_key.fbe_offset = fbe_offset + 4
+
2935 @_model_value.fbe_offset = fbe_offset + 4
+
2936 fbe_map_size.times do
+
2937 offset_key = @_model_key.verify
+
2938 if offset_key == Integer::MAX
+
2939 return Integer::MAX
+
2940 end
+
2941 @_model_key.fbe_shift(offset_key)
+
2942 @_model_value.fbe_shift(offset_key)
+
2943 size += offset_key
+
2944 offset_value = @_model_value.verify
+
2945 if offset_value == Integer::MAX
+
2946 return Integer::MAX
+
2947 end
+
2948 @_model_key.fbe_shift(offset_value)
+
2949 @_model_value.fbe_shift(offset_value)
+
2950 size += offset_value
+
2951 end
+
2952 size
+
2953 end
+
2954
+
2955 # Get the map
+
2956 def get(values = Hash.new)
+
2957 values.clear
+
2958
+
2959 if (@_buffer.offset + fbe_offset + 4) > @_buffer.size
+
2960 return [values, 0]
+
2961 end
+
2962
+
2963 fbe_map_size = read_uint32(fbe_offset)
+
2964 if fbe_map_size == 0
+
2965 return [values, 4]
+
2966 end
+
2967
+
2968 size = 4
+
2969 @_model_key.fbe_offset = fbe_offset + 4
+
2970 @_model_value.fbe_offset = fbe_offset + 4
+
2971 fbe_map_size.times do
+
2972 key = @_model_key.get
+
2973 @_model_key.fbe_shift(key[1])
+
2974 @_model_value.fbe_shift(key[1])
+
2975 size += key[1]
+
2976 value = @_model_value.get
+
2977 @_model_key.fbe_shift(value[1])
+
2978 @_model_value.fbe_shift(value[1])
+
2979 size += value[1]
+
2980 values[key[0]] = value[0]
+
2981 end
+
2982 [values, size]
+
2983 end
+
2984
+
2985 # Set the map
+
2986 def set(values)
+
2987 raise ArgumentError, "Invalid values parameter!" if values.nil? || !values.is_a?(Hash)
+
2988
+
2989 if (@_buffer.offset + fbe_offset + 4) > @_buffer.size
+
2990 return 0
+
2991 end
+
2992
+
2993 write_uint32(fbe_offset, values.length)
+
2994
+
2995 size = 4
+
2996 @_model_key.fbe_offset = fbe_offset + 4
+
2997 @_model_value.fbe_offset = fbe_offset + 4
+
2998 values.each do |key, value|
+
2999 offset_key = @_model_key.set(key)
+
3000 @_model_key.fbe_shift(offset_key)
+
3001 @_model_value.fbe_shift(offset_key)
+
3002 size += offset_key
+
3003 offset_value = @_model_value.set(value)
+
3004 @_model_key.fbe_shift(offset_value)
+
3005 @_model_value.fbe_shift(offset_value)
+
3006 size += offset_value
+
3007 end
+
3008 size
+
3009 end
+
3010 end
+
3011)CODE";
+
3012
+
3013 // Prepare code template
+
3014 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
3015
+
3016 Write(code);
+
3017}
+
3018
+
3019void GeneratorRuby::GenerateFBESender()
+
3020{
+
3021 std::string code = R"CODE(
+
3022 # Fast Binary Encoding base sender
+
3023 class Sender
+
3024 def initialize(buffer = WriteBuffer.new, final = false)
+
3025 @_buffer = buffer
+
3026 @_logging = false
+
3027 @_final = final
+
3028 end
+
3029
+
3030 # Get the bytes buffer
+
3031 def buffer
+
3032 @_buffer
+
3033 end
+
3034
+
3035 # Get the final protocol flag
+
3036 def final?
+
3037 @_final
+
3038 end
+
3039
+
3040 # Get the logging flag
+
3041 def logging?
+
3042 @_logging
+
3043 end
+
3044
+
3045 # Set the logging flag
+
3046 def logging=(logging)
+
3047 @_logging = logging
+
3048 end
+
3049
+
3050 # Reset the sender buffer
+
3051 def reset
+
3052 @_buffer.reset
+
3053 end
+
3054
+
3055 # Send serialized buffer.
+
3056 # Direct call of the method requires knowledge about internals of FBE models serialization.
+
3057 # Use it with care!
+
3058 def send_serialized(serialized)
+
3059 if serialized <= 0
+
3060 return 0
+
3061 end
+
3062
+
3063 # Shift the send buffer
+
3064 @_buffer.shift(serialized)
+
3065
+
3066 # Send the value
+
3067 sent = on_send(@_buffer.buffer, 0, @_buffer.size)
+
3068 @_buffer.remove(0, sent)
+
3069 sent
+
3070 end
+
3071
+
3072 protected
+
3073
+
3074 # Send message handler
+
3075 # noinspection RubyUnusedLocalVariable
+
3076 def on_send(buffer, offset, size)
+
3077 raise NotImplementedError, "Abstract method call!"
+
3078 end
+
3079
+
3080 # Send log message handler
+
3081 # noinspection RubyUnusedLocalVariable
+
3082 def on_send_log(message)
+
3083 end
+
3084 end
+
3085)CODE";
+
3086
+
3087 // Prepare code template
+
3088 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
3089
+
3090 Write(code);
+
3091}
+
3092
+
3093void GeneratorRuby::GenerateFBEReceiver()
+
3094{
+
3095 std::string code = R"CODE(
+
3096 # Fast Binary Encoding base receiver
+
3097 class Receiver
+
3098 def initialize(buffer = WriteBuffer.new, final = false)
+
3099 @_buffer = buffer
+
3100 @_logging = false
+
3101 @_final = final
+
3102 end
+
3103
+
3104 # Get the bytes buffer
+
3105 def buffer
+
3106 @_buffer
+
3107 end
+
3108
+
3109 # Get the final protocol flag
+
3110 def final?
+
3111 @_final
+
3112 end
+
3113
+
3114 # Get the logging flag
+
3115 def logging?
+
3116 @_logging
+
3117 end
+
3118
+
3119 # Set the logging flag
+
3120 def logging=(logging)
+
3121 @_logging = logging
+
3122 end
+
3123
+
3124 # Reset the receiver buffer
+
3125 def reset
+
3126 @_buffer.reset
+
3127 end
+
3128
+
3129 # Receive data
+
3130 def receive(buffer, offset = 0, size = nil)
+
3131 raise ArgumentError, "Invalid buffer!" if buffer.nil?
+
3132
+
3133 if buffer.is_a?(ReadBuffer) || buffer.is_a?(WriteBuffer)
+
3134 buffer = buffer.buffer
+
3135 end
+
3136
+
3137 if size.nil?
+
3138 size = buffer.length
+
3139 end
+
3140
+
3141 raise ArgumentError, "Invalid offset & size!" if (offset + size) > buffer.length
+
3142
+
3143 if size == 0
+
3144 return
+
3145 end
+
3146
+
3147 # Storage buffer
+
3148 offset0 = @_buffer.offset
+
3149 offset1 = @_buffer.size
+
3150 size1 = @_buffer.size
+
3151
+
3152 # Receive buffer
+
3153 offset2 = 0
+
3154 size2 = size
+
3155
+
3156 # While receive buffer is available to handle...
+
3157 while offset2 < size2
+
3158 message_buffer = nil
+
3159 message_offset = 0
+
3160 message_size = 0
+
3161
+
3162 # Try to receive message size
+
3163 message_size_copied = false
+
3164 message_size_found = false
+
3165 until message_size_found
+
3166 # Look into the storage buffer
+
3167 if offset0 < size1
+
3168 count = [size1 - offset0, 4].min
+
3169 if count == 4
+
3170 message_size_copied = true
+
3171 message_size_found = true
+
3172 message_size = Receiver.read_uint32(@_buffer.buffer, @_buffer.offset + offset0)
+
3173 offset0 += 4
+
3174 break
+
3175 else
+
3176 # Fill remaining data from the receive buffer
+
3177 if offset2 < size2
+
3178 count = [size2 - offset2, 4 - count].min
+
3179
+
3180 # Allocate and refresh the storage buffer
+
3181 @_buffer.allocate(count)
+
3182 size1 += count
+
3183
+
3184 @_buffer.buffer[offset1, count] = buffer[offset + offset2, count]
+
3185 offset1 += count
+
3186 offset2 += count
+
3187 next
+
3188 else
+
3189 break
+
3190 end
+
3191 end
+
3192 end
+
3193
+
3194 # Look into the receive buffer
+
3195 if offset2 < size2
+
3196 count = [size2 - offset2, 4].min
+
3197 if count == 4
+
3198 message_size_found = true
+
3199 message_size = Receiver.read_uint32(buffer, offset + offset2)
+
3200 offset2 += 4
+
3201 break
+
3202 else
+
3203 # Allocate and refresh the storage buffer
+
3204 @_buffer.allocate(count)
+
3205 size1 += count
+
3206
+
3207 @_buffer.buffer[offset1, count] = buffer[offset + offset2, count]
+
3208 offset1 += count
+
3209 offset2 += count
+
3210 next
+
3211 end
+
3212 else
+
3213 break
+
3214 end
+
3215 end
+
3216
+
3217 unless message_size_found
+
3218 return
+
3219 end
+
3220
+
3221 # Check the message full size
+
3222 min_size = @_final ? (4 + 4) : (4 + 4 + 4 + 4)
+
3223 if message_size < min_size
+
3224 return
+
3225 end
+
3226
+
3227 # Try to receive message body
+
3228 message_found = false
+
3229 until message_found
+
3230 # Look into the storage buffer
+
3231 if offset0 < size1
+
3232 count = [size1 - offset0, message_size - 4].min
+
3233 if count == (message_size - 4)
+
3234 message_found = true
+
3235 message_buffer = @_buffer.buffer
+
3236 message_offset = offset0 - 4
+
3237 offset0 += message_size - 4
+
3238 break
+
3239 else
+
3240 # Fill remaining data from the receive buffer
+
3241 if offset2 < size2
+
3242 # Copy message size into the storage buffer
+
3243 unless message_size_copied
+
3244 # Allocate and refresh the storage buffer
+
3245 @_buffer.allocate(4)
+
3246 size1 += 4
+
3247
+
3248 Receiver.write_uint32(@_buffer.buffer, @_buffer.offset + offset0, message_size)
+
3249 offset0 += 4
+
3250 offset1 += 4
+
3251
+
3252 message_size_copied = true
+
3253 end
+
3254
+
3255 count = [size2 - offset2, message_size - 4 - count].min
+
3256
+
3257 # Allocate and refresh the storage buffer
+
3258 @_buffer.allocate(count)
+
3259 size1 += count
+
3260
+
3261 @_buffer.buffer[offset1, count] = buffer[offset + offset2, count]
+
3262 offset1 += count
+
3263 offset2 += count
+
3264 next
+
3265 else
+
3266 break
+
3267 end
+
3268 end
+
3269 end
+
3270
+
3271 # Look into the receive buffer
+
3272 if offset2 < size2
+
3273 count = [size2 - offset2, message_size - 4].min
+
3274 if !message_size_copied && (count == (message_size - 4))
+
3275 message_found = true
+
3276 message_buffer = buffer
+
3277 message_offset = offset + offset2 - 4
+
3278 offset2 += message_size - 4
+
3279 break
+
3280 else
+
3281 # Copy message size into the storage buffer
+
3282 unless message_size_copied
+
3283 # Allocate and refresh the storage buffer
+
3284 @_buffer.allocate(4)
+
3285 size1 += 4
+
3286
+
3287 Receiver.write_uint32(@_buffer.buffer, @_buffer.offset + offset0, message_size)
+
3288 offset0 += 4
+
3289 offset1 += 4
+
3290
+
3291 message_size_copied = true
+
3292 end
+
3293
+
3294 # Allocate and refresh the storage buffer
+
3295 @_buffer.allocate(count)
+
3296 size1 += count
+
3297
+
3298 @_buffer.buffer[offset1, count] = buffer[offset + offset2, count]
+
3299 offset1 += count
+
3300 offset2 += count
+
3301 next
+
3302 end
+
3303 else
+
3304 break
+
3305 end
+
3306 end
+
3307
+
3308 unless message_found
+
3309 # Copy message size into the storage buffer
+
3310 unless message_size_copied
+
3311 # Allocate and refresh the storage buffer
+
3312 @_buffer.allocate(4)
+
3313 # noinspection RubyUnusedLocalVariable
+
3314 size1 += 4
+
3315
+
3316 Receiver.write_uint32(@_buffer.buffer, @_buffer.offset + offset0, message_size)
+
3317 # noinspection RubyUnusedLocalVariable
+
3318 offset0 += 4
+
3319 # noinspection RubyUnusedLocalVariable
+
3320 offset1 += 4
+
3321
+
3322 # noinspection RubyUnusedLocalVariable
+
3323 message_size_copied = true
+
3324 end
+
3325 return
+
3326 end
+
3327
+
3328 # Read the message parameters
+
3329 if @_final
+
3330 # noinspection RubyUnusedLocalVariable
+
3331 fbe_struct_size = Receiver.read_uint32(message_buffer, message_offset)
+
3332 fbe_struct_type = Receiver.read_uint32(message_buffer, message_offset + 4)
+
3333 else
+
3334 fbe_struct_offset = Receiver.read_uint32(message_buffer, message_offset + 4)
+
3335 # noinspection RubyUnusedLocalVariable
+
3336 fbe_struct_size = Receiver.read_uint32(message_buffer, message_offset + fbe_struct_offset)
+
3337 fbe_struct_type = Receiver.read_uint32(message_buffer, message_offset + fbe_struct_offset + 4)
+
3338 end
+
3339
+
3340 # Handle the message
+
3341 on_receive(fbe_struct_type, message_buffer, message_offset, message_size)
+
3342
+
3343 # Reset the storage buffer
+
3344 @_buffer.reset
+
3345
+
3346 # Refresh the storage buffer
+
3347 offset0 = @_buffer.offset
+
3348 offset1 = @_buffer.size
+
3349 size1 = @_buffer.size
+
3350 end
+
3351 end
+
3352
+
3353 protected
+
3354
+
3355 # Receive message handler
+
3356 # noinspection RubyUnusedLocalVariable
+
3357 def on_receive(type, buffer, offset, size)
+
3358 raise NotImplementedError, "Abstract method call!"
+
3359 end
+
3360
+
3361 # Receive log message handler
+
3362 # noinspection RubyUnusedLocalVariable
+
3363 def on_receive_log(message)
+
3364 end
+
3365
+
3366 private
+
3367
+
3368 # Buffer I/O methods
+
3369
+
3370 def self.read_uint32(buffer, offset)
+
3371 buffer.slice(offset, 4).unpack('L<')[0]
+
3372 end
+
3373
+
3374 def self.write_uint32(buffer, offset, value)
+
3375 buffer[offset, 4] = [value].pack('L<')
+
3376 end
+
3377 end
+
3378)CODE";
+
3379
+
3380 // Prepare code template
+
3381 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
3382
+
3383 Write(code);
+
3384}
+
3385
+
3386void GeneratorRuby::GenerateImports(const std::shared_ptr<Package>& p)
+
3387{
+
3388 // Generate common import
+
3389 GenerateImports();
+
3390
+
3391 // Generate FBE import
+
3392 WriteLine();
+
3393 WriteLineIndent("require_relative 'fbe'");
+
3394
+
3395 // Generate packages import
+
3396 if (p->import)
+
3397 for (const auto& import : p->import->imports)
+
3398 WriteLineIndent("require_relative '" + *import + "'");
+
3399}
+
3400
+
3401void GeneratorRuby::GeneratePackage(const std::shared_ptr<Package>& p)
+
3402{
+
3403 CppCommon::Path output = _output;
+
3404
+
3405 // Create package path
+
3406 CppCommon::Directory::CreateTree(output);
+
3407
+
3408 // Generate FBE file
+
3409 GenerateFBE(output);
+
3410
+
3411 // Generate the output file
+
3412 output /= *p->name + ".rb";
+
3413 WriteBegin();
+
3414
+
3415 // Generate package header
+
3416 GenerateHeader(CppCommon::Path(_input).filename().string());
+
3417 GenerateImports(p);
+
3418
+
3419 // Generate module begin
+
3420 WriteLine();
+
3421 WriteLineIndent("module " + ConvertTitle(*p->name));
+
3422 Indent(1);
+
3423
+
3424 // Generate namespace
+
3425 if (p->body)
+
3426 {
+
3427 // Generate child enums
+
3428 for (const auto& child_e : p->body->enums)
+
3429 GenerateEnum(child_e);
+
3430
+
3431 // Generate child flags
+
3432 for (const auto& child_f : p->body->flags)
+
3433 GenerateFlags(child_f);
+
3434
+
3435 // Generate child structs
+
3436 for (const auto& child_s : p->body->structs)
+
3437 GenerateStruct(child_s);
+
3438 }
+
3439
+
3440 // Generate protocol
+
3441 if (Proto())
+
3442 {
+
3443 // Generate protocol version
+
3444 GenerateProtocolVersion(p);
+
3445
+
3446 // Generate sender & receiver
+
3447 GenerateSender(p, false);
+
3448 GenerateReceiver(p, false);
+
3449 GenerateProxy(p, false);
+
3450 if (Final())
+
3451 {
+
3452 GenerateSender(p, true);
+
3453 GenerateReceiver(p, true);
+
3454 }
+
3455 }
+
3456
+
3457 // Generate module end
+
3458 Indent(-1);
+
3459 WriteLine();
+
3460 WriteLineIndent("end");
+
3461
+
3462 // Generate package footer
+
3463 GenerateFooter();
+
3464
+
3465 // Store the output file
+
3466 WriteEnd();
+
3467 Store(output);
+
3468}
+
3469
+
3470void GeneratorRuby::GenerateEnum(const std::shared_ptr<EnumType>& e)
+
3471{
+
3472 std::string enum_name = ConvertTitle(*e->name);
+
3473 std::string enum_type = (e->base && !e->base->empty()) ? *e->base : "int32";
+
3474
+
3475 // Generate enum module
+
3476 WriteLine();
+
3477 WriteLineIndent("module " + enum_name);
+
3478 Indent(1);
+
3479
+
3480 // Generate enum class
+
3481 WriteLineIndent("class Enum");
+
3482 Indent(1);
+
3483 WriteLineIndent("include FBE::Enum");
+
3484
+
3485 // Generate enum class body
+
3486 if (e->body && !e->body->values.empty())
+
3487 {
+
3488 WriteLine();
+
3489 int index = 0;
+
3490 std::string last = ConvertEnumConstant("int32", "0", false);
+
3491 for (const auto& value : e->body->values)
+
3492 {
+
3493 WriteIndent("define :" + *value->name + ", ");
+
3494 if (value->value)
+
3495 {
+
3496 if (value->value->constant && !value->value->constant->empty())
+
3497 {
+
3498 index = 0;
+
3499 last = ConvertEnumConstant(enum_type, *value->value->constant, false);
+
3500 Write(last + " + " + std::to_string(index++));
+
3501 }
+
3502 else if (value->value->reference && !value->value->reference->empty())
+
3503 {
+
3504 index = 0;
+
3505 last = ConvertEnumConstant("", *value->value->reference, false);
+
3506 Write(last);
+
3507 }
+
3508 }
+
3509 else
+
3510 Write(last + " + " + std::to_string(index++));
+
3511 WriteLine();
+
3512 }
+
3513 WriteLine();
+
3514 }
+
3515
+
3516 // Generate enum initialize method
+
3517 WriteLineIndent("def initialize(value = 0)");
+
3518 Indent(1);
+
3519 WriteLineIndent("@value = value.is_a?(Enum) ? value.value : value");
+
3520 Indent(-1);
+
3521 WriteLineIndent("end");
+
3522
+
3523 // Generate enum compare operators
+
3524 WriteLine();
+
3525 WriteLineIndent("# Enum compare operators");
+
3526 WriteLineIndent("def ==(value) @value == value.value end");
+
3527 WriteLineIndent("def !=(value) @value != value.value end");
+
3528
+
3529 // Generate enum hash & equals methods
+
3530 WriteLine();
+
3531 WriteLineIndent("# Enum equals");
+
3532 WriteLineIndent("def eql?(other)");
+
3533 Indent(1);
+
3534 WriteLineIndent("self == other");
+
3535 Indent(-1);
+
3536 WriteLineIndent("end");
+
3537 WriteLine();
+
3538 WriteLineIndent("# Enum hash code");
+
3539 WriteLineIndent("def hash");
+
3540 Indent(1);
+
3541 WriteLineIndent("@value.hash");
+
3542 Indent(-1);
+
3543 WriteLineIndent("end");
+
3544
+
3545 // Generate enum to_i method
+
3546 WriteLine();
+
3547 WriteLineIndent("# Get enum integer value");
+
3548 WriteLineIndent("def to_i");
+
3549 Indent(1);
+
3550 WriteLineIndent("@value");
+
3551 Indent(-1);
+
3552 WriteLineIndent("end");
+
3553
+
3554 // Generate enum to_s method
+
3555 WriteLine();
+
3556 WriteLineIndent("# Get enum string value");
+
3557 WriteLineIndent("def to_s");
+
3558 Indent(1);
+
3559 if (e->body && !e->body->values.empty())
+
3560 {
+
3561 for (auto it = e->body->values.begin(); it != e->body->values.end(); ++it)
+
3562 {
+
3563 WriteLineIndent("if @value == Enum." + *(*it)->name);
+
3564 Indent(1);
+
3565 WriteLineIndent("return '" + *(*it)->name + "'");
+
3566 Indent(-1);
+
3567 WriteLineIndent("end");
+
3568 }
+
3569 WriteLineIndent("'<unknown>'");
+
3570 }
+
3571 else
+
3572 WriteLineIndent("'<empty>'");
+
3573 Indent(-1);
+
3574 WriteLineIndent("end");
+
3575
+
3576 // Generate enum JSON methods
+
3577 WriteLine();
+
3578 WriteLineIndent("# Get enum JSON value");
+
3579 WriteLineIndent("def __to_json_map__");
+
3580 Indent(1);
+
3581 WriteLineIndent("@value");
+
3582 Indent(-1);
+
3583 WriteLineIndent("end");
+
3584
+
3585 // Generate enum class end
+
3586 Indent(-1);
+
3587 WriteLineIndent("end");
+
3588
+
3589 // Generate enum module class
+
3590 WriteLine();
+
3591 WriteLineIndent("class << self");
+
3592 Indent(1);
+
3593 if (e->body)
+
3594 for (auto it = e->body->values.begin(); it != e->body->values.end(); ++it)
+
3595 WriteLineIndent("attr_accessor :" + *(*it)->name);
+
3596 Indent(-1);
+
3597 WriteLineIndent("end");
+
3598
+
3599 // Generate enum module class attributes
+
3600 if (e->body && !e->body->values.empty())
+
3601 {
+
3602 WriteLine();
+
3603 for (auto it = e->body->values.begin(); it != e->body->values.end(); ++it)
+
3604 WriteLineIndent("self." + *(*it)->name + " = Enum.new(Enum." + *(*it)->name + ")");
+
3605 }
+
3606
+
3607 // Generate enum module class constructor
+
3608 WriteLine();
+
3609 WriteLineIndent("def self.new(value = 0)");
+
3610 Indent(1);
+
3611 WriteLineIndent("Enum.new(value)");
+
3612 Indent(-1);
+
3613 WriteLineIndent("end");
+
3614
+
3615 // Generate enum module JSON converter
+
3616 WriteLine();
+
3617 WriteLineIndent("# Get enum value from JSON");
+
3618 WriteLineIndent("def self.__from_json_map__(json)");
+
3619 Indent(1);
+
3620 WriteLineIndent("Enum.new(json)");
+
3621 Indent(-1);
+
3622 WriteLineIndent("end");
+
3623
+
3624 // Generate enum module end
+
3625 Indent(-1);
+
3626 WriteLineIndent("end");
+
3627
+
3628 // Generate enum module freeze
+
3629 WriteLine();
+
3630 WriteLineIndent(enum_name + ".freeze");
+
3631
+
3632 // Generate enum field model
+
3633 GenerateEnumFieldModel(e);
+
3634
+
3635 // Generate enum final model
+
3636 if (Final())
+
3637 GenerateEnumFinalModel(e);
+
3638}
+
3639
+
3640void GeneratorRuby::GenerateEnumFieldModel(const std::shared_ptr<EnumType>& e)
+
3641{
+
3642 std::string code = R"CODE(
+
3643 # Fast Binary Encoding _ENUM_NAME_ field model
+
3644 class FieldModel_ENUM_NAME_ < FBE::FieldModel
+
3645 def initialize(buffer, offset)
+
3646 super(buffer, offset)
+
3647 end
+
3648
+
3649 # Get the field size
+
3650 def fbe_size
+
3651 _ENUM_SIZE_
+
3652 end
+
3653
+
3654 # Get the value
+
3655 def get(defaults = _ENUM_NAME_.new)
+
3656 if (@_buffer.offset + fbe_offset + fbe_size) > @_buffer.size
+
3657 return defaults
+
3658 end
+
3659
+
3660 _ENUM_NAME_.new(read__ENUM_TYPE_(fbe_offset))
+
3661 end
+
3662
+
3663 # Set the value
+
3664 def set(value)
+
3665 if (@_buffer.offset + fbe_offset + fbe_size) > @_buffer.size
+
3666 return
+
3667 end
+
3668
+
3669 write__ENUM_TYPE_(fbe_offset, value.value)
+
3670 end
+
3671 end
+
3672)CODE";
+
3673
+
3674 std::string enum_name = ConvertTitle(*e->name);
+
3675 std::string enum_type = (e->base && !e->base->empty()) ? *e->base : "int32";
+
3676
+
3677 // Prepare code template
+
3678 code = std::regex_replace(code, std::regex("_ENUM_NAME_"), enum_name);
+
3679 code = std::regex_replace(code, std::regex("_ENUM_TYPE_"), ConvertEnumType(enum_type));
+
3680 code = std::regex_replace(code, std::regex("_ENUM_SIZE_"), ConvertEnumSize(enum_type));
+
3681 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
3682
+
3683 Write(code);
+
3684}
+
3685
+
3686void GeneratorRuby::GenerateEnumFinalModel(const std::shared_ptr<EnumType>& e)
+
3687{
+
3688 std::string code = R"CODE(
+
3689 # Fast Binary Encoding _ENUM_NAME_ final model
+
3690 class FinalModel_ENUM_NAME_ < FBE::FinalModel
+
3691 def initialize(buffer, offset)
+
3692 super(buffer, offset)
+
3693 end
+
3694
+
3695 # Get the allocation size
+
3696 # noinspection RubyUnusedLocalVariable
+
3697 def fbe_allocation_size(value)
+
3698 fbe_size
+
3699 end
+
3700
+
3701 # Get the final size
+
3702 def fbe_size
+
3703 _ENUM_SIZE_
+
3704 end
+
3705
+
3706 # Is the enum value valid?
+
3707 def valid?
+
3708 verify
+
3709 end
+
3710
+
3711 # Check if the value is valid
+
3712 def verify
+
3713 if (@_buffer.offset + fbe_offset + fbe_size) > @_buffer.size
+
3714 return FBE::Integer::MAX
+
3715 end
+
3716
+
3717 fbe_size
+
3718 end
+
3719
+
3720 # Get the value
+
3721 def get
+
3722 if (@_buffer.offset + fbe_offset + fbe_size) > @_buffer.size
+
3723 return [_ENUM_NAME_.new, 0]
+
3724 end
+
3725
+
3726 [_ENUM_NAME_.new(read__ENUM_TYPE_(fbe_offset)), fbe_size]
+
3727 end
+
3728
+
3729 # Set the value
+
3730 def set(value)
+
3731 if (@_buffer.offset + fbe_offset + fbe_size) > @_buffer.size
+
3732 return 0
+
3733 end
+
3734
+
3735 write__ENUM_TYPE_(fbe_offset, value.value)
+
3736 fbe_size
+
3737 end
+
3738 end
+
3739)CODE";
+
3740
+
3741 std::string enum_name = ConvertTitle(*e->name);
+
3742 std::string enum_type = (e->base && !e->base->empty()) ? *e->base : "int32";
+
3743
+
3744 // Prepare code template
+
3745 code = std::regex_replace(code, std::regex("_ENUM_NAME_"), enum_name);
+
3746 code = std::regex_replace(code, std::regex("_ENUM_TYPE_"), ConvertEnumType(enum_type));
+
3747 code = std::regex_replace(code, std::regex("_ENUM_SIZE_"), ConvertEnumSize(enum_type));
+
3748 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
3749
+
3750 Write(code);
+
3751}
+
3752
+
3753void GeneratorRuby::GenerateFlags(const std::shared_ptr<FlagsType>& f)
+
3754{
+
3755 std::string flags_name = ConvertTitle(*f->name);
+
3756 std::string flags_type = (f->base && !f->base->empty()) ? *f->base : "int32";
+
3757
+
3758 // Generate flags module
+
3759 WriteLine();
+
3760 WriteLineIndent("module " + flags_name);
+
3761 Indent(1);
+
3762
+
3763 // Generate flags class
+
3764 WriteLineIndent("class Flags");
+
3765 Indent(1);
+
3766 WriteLineIndent("include FBE::Flags");
+
3767
+
3768 // Generate flags class body
+
3769 if (f->body && !f->body->values.empty())
+
3770 {
+
3771 WriteLine();
+
3772 for (const auto& value : f->body->values)
+
3773 {
+
3774 WriteIndent("define :" + *value->name + ", ");
+
3775 if (value->value)
+
3776 {
+
3777 if (value->value->constant && !value->value->constant->empty())
+
3778 Write(ConvertEnumConstant(flags_type, *value->value->constant, true));
+
3779 else if (value->value->reference && !value->value->reference->empty())
+
3780 Write(ConvertEnumConstant("", *value->value->reference, true));
+
3781 }
+
3782 WriteLine();
+
3783 }
+
3784 WriteLine();
+
3785 }
+
3786
+
3787 // Generate flags initialize method
+
3788 WriteLineIndent("def initialize(value = 0)");
+
3789 Indent(1);
+
3790 WriteLineIndent("@value = value.is_a?(Flags) ? value.value : value");
+
3791 Indent(-1);
+
3792 WriteLineIndent("end");
+
3793
+
3794 // Generate flags compare operators
+
3795 WriteLine();
+
3796 WriteLineIndent("# Flags compare operators");
+
3797 WriteLineIndent("def ==(flags) @value == flags.value end");
+
3798 WriteLineIndent("def !=(flags) @value != flags.value end");
+
3799
+
3800 // Generate flags bit operators
+
3801 WriteLine();
+
3802 WriteLineIndent("# Flags bit operators");
+
3803 WriteLineIndent("def ~");
+
3804 Indent(1);
+
3805 WriteLineIndent("Flags.new(~@value)");
+
3806 Indent(-1);
+
3807 WriteLineIndent("end");
+
3808 WriteLineIndent("def &(flags) Flags.new(@value & flags.value) end");
+
3809 WriteLineIndent("def |(flags) Flags.new(@value | flags.value) end");
+
3810 WriteLineIndent("def ^(flags) Flags.new(@value ^ flags.value) end");
+
3811
+
3812 // Generate flags hash & equals methods
+
3813 WriteLine();
+
3814 WriteLineIndent("# Flags equals");
+
3815 WriteLineIndent("def eql?(other)");
+
3816 Indent(1);
+
3817 WriteLineIndent("self == other");
+
3818 Indent(-1);
+
3819 WriteLineIndent("end");
+
3820 WriteLine();
+
3821 WriteLineIndent("# Flags hash code");
+
3822 WriteLineIndent("def hash");
+
3823 Indent(1);
+
3824 WriteLineIndent("@value.hash");
+
3825 Indent(-1);
+
3826 WriteLineIndent("end");
+
3827
+
3828 // Generate flags manipulation methods
+
3829 WriteLine();
+
3830 WriteLineIndent("# Is flags set?");
+
3831 WriteLineIndent("def has_flags(flags)");
+
3832 Indent(1);
+
3833 WriteLineIndent("((@value & flags.value) != 0) && ((@value & flags.value) == flags.value)");
+
3834 Indent(-1);
+
3835 WriteLineIndent("end");
+
3836 WriteLine();
+
3837 WriteLineIndent("# Set flags");
+
3838 WriteLineIndent("def set_flags(flags)");
+
3839 Indent(1);
+
3840 WriteLineIndent("@value |= flags.value");
+
3841 WriteLineIndent("self");
+
3842 Indent(-1);
+
3843 WriteLineIndent("end");
+
3844 WriteLine();
+
3845 WriteLineIndent("# Remove flags");
+
3846 WriteLineIndent("def remove_flags(flags)");
+
3847 Indent(1);
+
3848 WriteLineIndent("@value &= ~flags.value");
+
3849 WriteLineIndent("self");
+
3850 Indent(-1);
+
3851 WriteLineIndent("end");
+
3852
+
3853 // Generate flags to_i method
+
3854 WriteLine();
+
3855 WriteLineIndent("# Get flags integer value");
+
3856 WriteLineIndent("def to_i");
+
3857 Indent(1);
+
3858 WriteLineIndent("@value");
+
3859 Indent(-1);
+
3860 WriteLineIndent("end");
+
3861
+
3862 // Generate flags to_s method
+
3863 WriteLine();
+
3864 WriteLineIndent("# Get flags string value");
+
3865 WriteLineIndent("def to_s");
+
3866 Indent(1);
+
3867 WriteLineIndent("result = ''");
+
3868 if (f->body && !f->body->values.empty())
+
3869 {
+
3870 WriteLineIndent("first = true");
+
3871 for (auto it = f->body->values.begin(); it != f->body->values.end(); ++it)
+
3872 {
+
3873 WriteLineIndent("if ((@value & Flags." + *(*it)->name + ") != 0) && ((@value & Flags." + *(*it)->name + ") == Flags." + *(*it)->name + ")");
+
3874 Indent(1);
+
3875 WriteLineIndent("if first");
+
3876 Indent(1);
+
3877 WriteLineIndent("# noinspection RubyUnusedLocalVariable");
+
3878 WriteLineIndent("first = false");
+
3879 Indent(-1);
+
3880 WriteLineIndent("else");
+
3881 Indent(1);
+
3882 WriteLineIndent("result << '|'");
+
3883 Indent(-1);
+
3884 WriteLineIndent("end");
+
3885 WriteLineIndent("result << '" + *(*it)->name + "'");
+
3886 Indent(-1);
+
3887 WriteLineIndent("end");
+
3888 }
+
3889 }
+
3890 WriteLineIndent("result");
+
3891 Indent(-1);
+
3892 WriteLineIndent("end");
+
3893
+
3894 // Generate flags JSON methods
+
3895 WriteLine();
+
3896 WriteLineIndent("# Get flags JSON value");
+
3897 WriteLineIndent("def __to_json_map__");
+
3898 Indent(1);
+
3899 WriteLineIndent("@value");
+
3900 Indent(-1);
+
3901 WriteLineIndent("end");
+
3902
+
3903 // Generate flags class end
+
3904 Indent(-1);
+
3905 WriteLineIndent("end");
+
3906
+
3907 // Generate flags module class
+
3908 WriteLine();
+
3909 WriteLineIndent("class << self");
+
3910 Indent(1);
+
3911 if (f->body)
+
3912 for (auto it = f->body->values.begin(); it != f->body->values.end(); ++it)
+
3913 WriteLineIndent("attr_accessor :" + *(*it)->name);
+
3914 Indent(-1);
+
3915 WriteLineIndent("end");
+
3916
+
3917 // Generate flags module class attributes
+
3918 if (f->body && !f->body->values.empty())
+
3919 {
+
3920 WriteLine();
+
3921 for (auto it = f->body->values.begin(); it != f->body->values.end(); ++it)
+
3922 WriteLineIndent("self." + *(*it)->name + " = Flags.new(Flags." + *(*it)->name + ")");
+
3923 }
+
3924
+
3925 // Generate flags module class constructor
+
3926 WriteLine();
+
3927 WriteLineIndent("def self.new(value = 0)");
+
3928 Indent(1);
+
3929 WriteLineIndent("Flags.new(value)");
+
3930 Indent(-1);
+
3931 WriteLineIndent("end");
+
3932
+
3933 // Generate flags module JSON converter
+
3934 WriteLine();
+
3935 WriteLineIndent("# Get flags value from JSON");
+
3936 WriteLineIndent("def self.__from_json_map__(json)");
+
3937 Indent(1);
+
3938 WriteLineIndent("Flags.new(json)");
+
3939 Indent(-1);
+
3940 WriteLineIndent("end");
+
3941
+
3942 // Generate flags module end
+
3943 Indent(-1);
+
3944 WriteLineIndent("end");
+
3945
+
3946 // Generate flags module freeze
+
3947 WriteLine();
+
3948 WriteLineIndent(flags_name + ".freeze");
+
3949
+
3950 // Generate flags field model
+
3951 GenerateFlagsFieldModel(f);
+
3952
+
3953 // Generate flags final model
+
3954 if (Final())
+
3955 GenerateFlagsFinalModel(f);
+
3956}
+
3957
+
3958void GeneratorRuby::GenerateFlagsFieldModel(const std::shared_ptr<FlagsType>& f)
+
3959{
+
3960 std::string code = R"CODE(
+
3961 # Fast Binary Encoding _FLAGS_NAME_ field model
+
3962 class FieldModel_FLAGS_NAME_ < FBE::FieldModel
+
3963 def initialize(buffer, offset)
+
3964 super(buffer, offset)
+
3965 end
+
3966
+
3967 # Get the field size
+
3968 def fbe_size
+
3969 _FLAGS_SIZE_
+
3970 end
+
3971
+
3972 # Get the value
+
3973 def get(defaults = _FLAGS_NAME_.new)
+
3974 if (@_buffer.offset + fbe_offset + fbe_size) > @_buffer.size
+
3975 return defaults
+
3976 end
+
3977
+
3978 _FLAGS_NAME_.new(read__FLAGS_TYPE_(fbe_offset))
+
3979 end
+
3980
+
3981 # Set the value
+
3982 def set(value)
+
3983 if (@_buffer.offset + fbe_offset + fbe_size) > @_buffer.size
+
3984 return
+
3985 end
+
3986
+
3987 write__FLAGS_TYPE_(fbe_offset, value.value)
+
3988 end
+
3989 end
+
3990)CODE";
+
3991
+
3992 std::string flags_name = ConvertTitle(*f->name);
+
3993 std::string flags_type = (f->base && !f->base->empty()) ? *f->base : "int32";
+
3994
+
3995 // Prepare code template
+
3996 code = std::regex_replace(code, std::regex("_FLAGS_NAME_"), flags_name);
+
3997 code = std::regex_replace(code, std::regex("_FLAGS_TYPE_"), ConvertEnumType(flags_type));
+
3998 code = std::regex_replace(code, std::regex("_FLAGS_SIZE_"), ConvertEnumSize(flags_type));
+
3999 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
4000
+
4001 Write(code);
+
4002}
+
4003
+
4004void GeneratorRuby::GenerateFlagsFinalModel(const std::shared_ptr<FlagsType>& f)
+
4005{
+
4006 std::string code = R"CODE(
+
4007 # Fast Binary Encoding _FLAGS_NAME_ final model
+
4008 class FinalModel_FLAGS_NAME_ < FBE::FinalModel
+
4009 def initialize(buffer, offset)
+
4010 super(buffer, offset)
+
4011 end
+
4012
+
4013 # Get the allocation size
+
4014 # noinspection RubyUnusedLocalVariable
+
4015 def fbe_allocation_size(value)
+
4016 fbe_size
+
4017 end
+
4018
+
4019 # Get the final size
+
4020 def fbe_size
+
4021 _FLAGS_SIZE_
+
4022 end
+
4023
+
4024 # Is the flags value valid?
+
4025 def valid?
+
4026 verify
+
4027 end
+
4028
+
4029 # Check if the value is valid
+
4030 def verify
+
4031 if (@_buffer.offset + fbe_offset + fbe_size) > @_buffer.size
+
4032 return FBE::Integer::MAX
+
4033 end
+
4034
+
4035 fbe_size
+
4036 end
+
4037
+
4038 # Get the value
+
4039 def get
+
4040 if (@_buffer.offset + fbe_offset + fbe_size) > @_buffer.size
+
4041 return [_FLAGS_NAME_.new, 0]
+
4042 end
+
4043
+
4044 [_FLAGS_NAME_.new(read__FLAGS_TYPE_(fbe_offset)), fbe_size]
+
4045 end
+
4046
+
4047 # Set the value
+
4048 def set(value)
+
4049 if (@_buffer.offset + fbe_offset + fbe_size) > @_buffer.size
+
4050 return 0
+
4051 end
+
4052
+
4053 write__FLAGS_TYPE_(fbe_offset, value.value)
+
4054 fbe_size
+
4055 end
+
4056 end
+
4057)CODE";
+
4058
+
4059 std::string flags_name = ConvertTitle(*f->name);
+
4060 std::string flags_type = (f->base && !f->base->empty()) ? *f->base : "int32";
+
4061
+
4062 // Prepare code template
+
4063 code = std::regex_replace(code, std::regex("_FLAGS_NAME_"), flags_name);
+
4064 code = std::regex_replace(code, std::regex("_FLAGS_TYPE_"), ConvertEnumType(flags_type));
+
4065 code = std::regex_replace(code, std::regex("_FLAGS_SIZE_"), ConvertEnumSize(flags_type));
+
4066 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
4067
+
4068 Write(code);
+
4069}
+
4070
+
4071void GeneratorRuby::GenerateStruct(const std::shared_ptr<StructType>& s)
+
4072{
+
4073 std::string struct_name = ConvertTitle(*s->name);
+
4074 std::string base_type = (s->base && !s->base->empty()) ? ConvertTypeName(*s->base, false) : "";
+
4075
+
4076 // Generate struct begin
+
4077 WriteLine();
+
4078 WriteLineIndent("# noinspection RubyResolve, RubyScope, RubyTooManyInstanceVariablesInspection, RubyTooManyMethodsInspection");
+
4079 if (s->base && !s->base->empty())
+
4080 WriteLineIndent("class " + struct_name + " < " + base_type);
+
4081 else
+
4082 WriteLineIndent("class " + struct_name);
+
4083 Indent(1);
+
4084
+
4085 // Generate struct include
+
4086 WriteLineIndent("include Comparable");
+
4087
+
4088 // Generate struct accessors
+
4089 if (s->body && !s->body->fields.empty())
+
4090 {
+
4091 WriteLine();
+
4092 for (const auto& field : s->body->fields)
+
4093 WriteLineIndent("attr_accessor :" + *field->name);
+
4094 WriteLine();
+
4095 }
+
4096
+
4097 // Generate struct constructor
+
4098 WriteIndent("def initialize(");
+
4099 bool first = true;
+
4100 if (s->base && !s->base->empty())
+
4101 {
+
4102 Write("parent = " + base_type + ".new");
+
4103 first = false;
+
4104 }
+
4105 if (s->body)
+
4106 {
+
4107 for (const auto& field : s->body->fields)
+
4108 {
+
4109 Write((first ? "" : ", ") + *field->name + " = ");
+
4110 if (field->value)
+
4111 Write(ConvertConstant(*field->type, *field->value, field->optional));
+
4112 else
+
4113 Write(ConvertDefault(*field));
+
4114 first = false;
+
4115 }
+
4116 }
+
4117 WriteLine(")");
+
4118 Indent(1);
+
4119 if (s->base && !s->base->empty())
+
4120 WriteLineIndent("method(:initialize_copy).super_method.call(parent)");
+
4121 if (s->body)
+
4122 {
+
4123 for (const auto& field : s->body->fields)
+
4124 WriteLineIndent("@" + *field->name + " = " + *field->name);
+
4125 }
+
4126 Indent(-1);
+
4127 WriteLineIndent("end");
+
4128
+
4129 // Generate struct copy constructor
+
4130 WriteLine();
+
4131 WriteLineIndent("def initialize_copy(other)");
+
4132 Indent(1);
+
4133 if (s->base && !s->base->empty())
+
4134 WriteLineIndent("super(other)");
+
4135 if (s->body)
+
4136 for (const auto& field : s->body->fields)
+
4137 WriteLineIndent("@" + *field->name + " = other." + *field->name);
+
4138 Indent(-1);
+
4139 WriteLineIndent("end");
+
4140
+
4141 // Generate struct copy() method
+
4142 WriteLine();
+
4143 WriteLineIndent("# Struct shallow copy");
+
4144 WriteLineIndent("def copy(other)");
+
4145 Indent(1);
+
4146 WriteLineIndent("initialize_copy(other)");
+
4147 WriteLineIndent("self");
+
4148 Indent(-1);
+
4149 WriteLineIndent("end");
+
4150
+
4151 // Generate struct clone() method
+
4152 WriteLine();
+
4153 WriteLineIndent("# Struct deep clone");
+
4154 WriteLineIndent("def clone");
+
4155 Indent(1);
+
4156 WriteLineIndent("data = Marshal.dump(self)");
+
4157 WriteLineIndent("clone = Marshal.load(data)");
+
4158 WriteLineIndent("clone.freeze if frozen?");
+
4159 WriteLineIndent("clone");
+
4160 Indent(-1);
+
4161 WriteLineIndent("end");
+
4162
+
4163 // Generate struct compare operators
+
4164 WriteLine();
+
4165 WriteLineIndent("# Struct compare operators");
+
4166 WriteLineIndent("def <=>(other)");
+
4167 Indent(1);
+
4168 WriteLineIndent("return nil unless other.is_a?(" + struct_name + ")");
+
4169 WriteLine();
+
4170 WriteLineIndent("# noinspection RubyUnusedLocalVariable");
+
4171 WriteLineIndent("result = 0");
+
4172 if (s->base && !s->base->empty())
+
4173 {
+
4174 WriteLineIndent("result = super");
+
4175 WriteLineIndent("if result != 0");
+
4176 Indent(1);
+
4177 WriteLineIndent("return result");
+
4178 Indent(-1);
+
4179 WriteLineIndent("end");
+
4180 }
+
4181 if (s->body)
+
4182 {
+
4183 for (const auto& field : s->body->fields)
+
4184 {
+
4185 if (field->keys)
+
4186 {
+
4187 WriteLineIndent("result = @" + *field->name + " <=> other." + *field->name);
+
4188 WriteLineIndent("if result != 0");
+
4189 Indent(1);
+
4190 WriteLineIndent("return false");
+
4191 Indent(-1);
+
4192 WriteLineIndent("end");
+
4193 }
+
4194 }
+
4195 }
+
4196 WriteLineIndent("# noinspection RubyUnnecessaryReturnValue");
+
4197 WriteLineIndent("result");
+
4198 Indent(-1);
+
4199 WriteLineIndent("end");
+
4200
+
4201 // Generate struct hash & equals methods
+
4202 WriteLine();
+
4203 WriteLineIndent("# Struct equals");
+
4204 WriteLineIndent("def eql?(other)");
+
4205 Indent(1);
+
4206 WriteLineIndent("self == other");
+
4207 Indent(-1);
+
4208 WriteLineIndent("end");
+
4209 WriteLine();
+
4210 WriteLineIndent("# Struct keys");
+
4211 WriteLineIndent("def key");
+
4212 Indent(1);
+
4213 WriteLineIndent("result = []");
+
4214 if (s->base && !s->base->empty())
+
4215 WriteLineIndent("result.push(super)");
+
4216 if (s->body)
+
4217 {
+
4218 for (const auto& field : s->body->fields)
+
4219 if (field->keys)
+
4220 WriteLineIndent("result.push(@" + *field->name + ")");
+
4221 }
+
4222 WriteLineIndent("# noinspection RubyUnnecessaryReturnValue");
+
4223 WriteLineIndent("result");
+
4224 Indent(-1);
+
4225 WriteLineIndent("end");
+
4226 WriteLine();
+
4227 WriteLineIndent("# Struct hash code");
+
4228 WriteLineIndent("def hash");
+
4229 Indent(1);
+
4230 WriteLineIndent("key.hash");
+
4231 Indent(-1);
+
4232 WriteLineIndent("end");
+
4233
+
4234 // Generate struct __str__ method
+
4235 WriteLine();
+
4236 WriteLineIndent("# Get struct string value");
+
4237 WriteLineIndent("def to_s");
+
4238 Indent(1);
+
4239 WriteLineIndent("result = ''");
+
4240 WriteLineIndent("result << '" + *s->name + "('");
+
4241 first = true;
+
4242 if (s->base && !s->base->empty())
+
4243 {
+
4244 WriteLineIndent("result << super");
+
4245 first = false;
+
4246 }
+
4247 if (s->body)
+
4248 {
+
4249 for (const auto& field : s->body->fields)
+
4250 {
+
4251 WriteLineIndent("result << '" + std::string(first ? "" : ",") + *field->name + "='");
+
4252 if (field->attributes && field->attributes->hidden)
+
4253 WriteLineIndent("result << '***'");
+
4254 else if (field->array || field->vector)
+
4255 {
+
4256 WriteLineIndent("if @" + *field->name + ".nil?");
+
4257 Indent(1);
+
4258 WriteLineIndent("result << '[0][]'");
+
4259 Indent(-1);
+
4260 WriteLineIndent("else");
+
4261 Indent(1);
+
4262 WriteLineIndent("first = true");
+
4263 WriteLineIndent("result << '[' << @" + *field->name + ".length.to_s << ']['");
+
4264 WriteLineIndent("@" + *field->name + ".each do |item|");
+
4265 Indent(1);
+
4266 WriteOutputStreamValue(*field->type, "item", true);
+
4267 WriteLineIndent("first = false");
+
4268 Indent(-1);
+
4269 WriteLineIndent("end");
+
4270 WriteLineIndent("result << ']'");
+
4271 Indent(-1);
+
4272 WriteLineIndent("end");
+
4273 }
+
4274 else if (field->list)
+
4275 {
+
4276 WriteLineIndent("if @" + *field->name + ".nil?");
+
4277 Indent(1);
+
4278 WriteLineIndent("result << '[0]<>'");
+
4279 Indent(-1);
+
4280 WriteLineIndent("else");
+
4281 Indent(1);
+
4282 WriteLineIndent("first = true");
+
4283 WriteLineIndent("result << '[' << @" + *field->name + ".length.to_s << ']<'");
+
4284 WriteLineIndent("@" + *field->name + ".each do |item|");
+
4285 Indent(1);
+
4286 WriteOutputStreamValue(*field->type, "item", true);
+
4287 WriteLineIndent("first = false");
+
4288 Indent(-1);
+
4289 WriteLineIndent("end");
+
4290 WriteLineIndent("result << '>'");
+
4291 Indent(-1);
+
4292 WriteLineIndent("end");
+
4293 }
+
4294 else if (field->set)
+
4295 {
+
4296 WriteLineIndent("if @" + *field->name + ".nil?");
+
4297 Indent(1);
+
4298 WriteLineIndent("result << '[0]{}'");
+
4299 Indent(-1);
+
4300 WriteLineIndent("else");
+
4301 Indent(1);
+
4302 WriteLineIndent("first = true");
+
4303 WriteLineIndent("result << '[' << @" + *field->name + ".length.to_s << ']{'");
+
4304 WriteLineIndent("@" + *field->name + ".each do |item|");
+
4305 Indent(1);
+
4306 WriteOutputStreamValue(*field->type, "item", true);
+
4307 WriteLineIndent("first = false");
+
4308 Indent(-1);
+
4309 WriteLineIndent("end");
+
4310 WriteLineIndent("result << '}'");
+
4311 Indent(-1);
+
4312 WriteLineIndent("end");
+
4313 }
+
4314 else if (field->map)
+
4315 {
+
4316 WriteLineIndent("if @" + *field->name + ".nil?");
+
4317 Indent(1);
+
4318 WriteLineIndent("result << '[0]<{}>'");
+
4319 Indent(-1);
+
4320 WriteLineIndent("else");
+
4321 Indent(1);
+
4322 WriteLineIndent("first = true");
+
4323 WriteLineIndent("result << '[' << @" + *field->name + ".length.to_s << ']<{'");
+
4324 WriteLineIndent("@" + *field->name + ".each do |key, value|");
+
4325 Indent(1);
+
4326 WriteOutputStreamValue(*field->key, "key", true);
+
4327 WriteLineIndent("result << '->'");
+
4328 WriteOutputStreamValue(*field->type, "value", false);
+
4329 WriteLineIndent("first = false");
+
4330 Indent(-1);
+
4331 WriteLineIndent("end");
+
4332 WriteLineIndent("result << '}>'");
+
4333 Indent(-1);
+
4334 WriteLineIndent("end");
+
4335 }
+
4336 else if (field->hash)
+
4337 {
+
4338 WriteLineIndent("if @" + *field->name + ".nil?");
+
4339 Indent(1);
+
4340 WriteLineIndent("result << '[0][{}]'");
+
4341 Indent(-1);
+
4342 WriteLineIndent("else");
+
4343 Indent(1);
+
4344 WriteLineIndent("first = true");
+
4345 WriteLineIndent("result << '[' << @" + *field->name + ".length.to_s << '][{'");
+
4346 WriteLineIndent("@" + *field->name + ".each do |key, value|");
+
4347 Indent(1);
+
4348 WriteOutputStreamValue(*field->key, "key", true);
+
4349 WriteLineIndent("result << '->'");
+
4350 WriteOutputStreamValue(*field->type, "value", false);
+
4351 WriteLineIndent("first = false");
+
4352 Indent(-1);
+
4353 WriteLineIndent("end");
+
4354 WriteLineIndent("result << '}]'");
+
4355 Indent(-1);
+
4356 WriteLineIndent("end");
+
4357 }
+
4358 else
+
4359 WriteOutputStreamValue(*field->type, "@" + *field->name, false);
+
4360 first = false;
+
4361 }
+
4362 }
+
4363 WriteLineIndent("result << ')'");
+
4364 WriteLineIndent("result");
+
4365 Indent(-1);
+
4366 WriteLineIndent("end");
+
4367
+
4368 // Generate struct marshal_dump & marshal_load methods
+
4369 WriteLine();
+
4370 WriteLineIndent("# Dump the struct");
+
4371 WriteLineIndent("def marshal_dump");
+
4372 Indent(1);
+
4373 WriteLineIndent("# Serialize the struct to the FBE stream");
+
4374 WriteLineIndent("writer = " + *s->name + "Model.new(FBE::WriteBuffer.new)");
+
4375 WriteLineIndent("writer.serialize(self)");
+
4376 WriteLineIndent("writer.buffer");
+
4377 Indent(-1);
+
4378 WriteLineIndent("end");
+
4379 WriteLine();
+
4380 WriteLineIndent("# Load the struct");
+
4381 WriteLineIndent("def marshal_load(data)");
+
4382 Indent(1);
+
4383 WriteLineIndent("# Deserialize the struct from the FBE stream");
+
4384 WriteLineIndent("reader = " + *s->name + "Model.new(FBE::ReadBuffer.new)");
+
4385 WriteLineIndent("reader.attach_buffer(data)");
+
4386 WriteLineIndent("initialize_copy(reader.deserialize[0])");
+
4387 Indent(-1);
+
4388 WriteLineIndent("end");
+
4389
+
4390 if (JSON())
+
4391 {
+
4392 // Generate struct to_json method
+
4393 WriteLine();
+
4394 WriteLineIndent("# Get struct JSON value");
+
4395 WriteLineIndent("def to_json");
+
4396 Indent(1);
+
4397 WriteLineIndent("JSON.generate(__to_json_map__)");
+
4398 Indent(-1);
+
4399 WriteLineIndent("end");
+
4400
+
4401 // Generate struct __to_json_map__ method
+
4402 WriteLine();
+
4403 WriteLineIndent("# Get struct JSON map (internal method)");
+
4404 WriteLineIndent("def __to_json_map__");
+
4405 Indent(1);
+
4406 WriteLineIndent("result = {}");
+
4407 if (s->base && !s->base->empty())
+
4408 WriteLineIndent("result.update(super)");
+
4409 if (s->body)
+
4410 {
+
4411 for (const auto& field : s->body->fields)
+
4412 {
+
4413 WriteLineIndent("key = '" + *field->name + "'");
+
4414 if (field->array || field->vector || field->list || field->set)
+
4415 WriteLineIndent("value = " + *field->name + ".map { |item| " + ConvertValueToJson(*field->type, "item", field->optional) + " }");
+
4416 else if (field->map || field->hash)
+
4417 WriteLineIndent("value = " + *field->name + ".map { |key, value| [key.to_s, " + ConvertValueToJson(*field->type, "value", field->optional) + "] }.to_h");
+
4418 else
+
4419 WriteLineIndent("value = " + ConvertValueToJson(*field->type, *field->name, field->optional));
+
4420 WriteLineIndent("result.store(key, value)");
+
4421 }
+
4422 }
+
4423 WriteLineIndent("result");
+
4424 Indent(-1);
+
4425 WriteLineIndent("end");
+
4426
+
4427 // Generate struct from_json method
+
4428 WriteLine();
+
4429 WriteLineIndent("# Get struct from JSON");
+
4430 WriteLineIndent("def self.from_json(json)");
+
4431 Indent(1);
+
4432 WriteLineIndent("__from_json_map__(JSON.parse(json))");
+
4433 Indent(-1);
+
4434 WriteLineIndent("end");
+
4435
+
4436 // Generate struct __from_json_map__ method
+
4437 WriteLine();
+
4438 WriteLineIndent("# Get struct map from JSON (internal method)");
+
4439 WriteLineIndent("def self.__from_json_map__(json)");
+
4440 Indent(1);
+
4441 WriteLineIndent("result = " + struct_name + ".new");
+
4442 if (s->base && !s->base->empty())
+
4443 WriteLineIndent("result.method(:initialize_copy).super_method.call(" + struct_name + ".method(:__from_json_map__).super_method.call(json))");
+
4444 if (s->body)
+
4445 {
+
4446 for (const auto& field : s->body->fields)
+
4447 {
+
4448 WriteLineIndent("value = json.fetch('" + *field->name + "', nil)");
+
4449 if (field->array || field->vector || field->list)
+
4450 WriteLineIndent("result." + *field->name + " = value.map { |item| " + ConvertValueFromJson(*field->type, "item", field->optional) + " }");
+
4451 else if (field->set)
+
4452 WriteLineIndent("result." + *field->name + " = (value.map { |item| " + ConvertValueFromJson(*field->type, "item", field->optional) + " }).to_set");
+
4453 else if (field->map || field->hash)
+
4454 WriteLineIndent("result." + *field->name + " = (value.map { |key, value| [" + ConvertKeyFromJson(*field->key, "key", false) + ", " + ConvertValueFromJson(*field->type, "value", field->optional) + "] }).to_h");
+
4455 else
+
4456 WriteLineIndent("result." + *field->name + " = " + ConvertValueFromJson(*field->type, "value", field->optional));
+
4457 }
+
4458 }
+
4459 WriteLineIndent("result");
+
4460 Indent(-1);
+
4461 WriteLineIndent("end");
+
4462 }
+
4463
+
4464 // Generate struct FBE type property
+
4465 WriteLine();
+
4466 WriteLineIndent("# Get the FBE type");
+
4467 WriteLineIndent("def fbe_type");
+
4468 Indent(1);
+
4469 WriteLineIndent("TYPE");
+
4470 Indent(-1);
+
4471 WriteLineIndent("end");
+
4472
+
4473 // Generate struct FBE type
+
4474 WriteLine();
+
4475 if (s->base && !s->base->empty() && (s->type == 0))
+
4476 WriteLineIndent("TYPE = " + base_type + "::TYPE");
+
4477 else
+
4478 WriteLineIndent("TYPE = " + std::to_string(s->type));
+
4479
+
4480 // Generate struct end
+
4481 Indent(-1);
+
4482 WriteLineIndent("end");
+
4483
+
4484 // Generate struct field model
+
4485 GenerateStructFieldModel(s);
+
4486
+
4487 // Generate struct model
+
4488 GenerateStructModel(s);
+
4489
+
4490 // Generate struct final models
+
4491 if (Final())
+
4492 {
+
4493 GenerateStructFinalModel(s);
+
4494 GenerateStructModelFinal(s);
+
4495 }
+
4496}
+
4497
+
4498void GeneratorRuby::GenerateStructFieldModel(const std::shared_ptr<StructType>& s)
+
4499{
+
4500 std::string struct_name = ConvertTitle(*s->name);
+
4501 std::string base_type = (s->base && !s->base->empty()) ? ConvertTypeFieldName(*s->base, false) : "";
+
4502
+
4503 // Generate struct field model begin
+
4504 WriteLine();
+
4505 WriteLineIndent("# noinspection RubyResolve, RubyScope, RubyTooManyInstanceVariablesInspection, RubyTooManyMethodsInspection");
+
4506 WriteLineIndent("class FieldModel" + struct_name + " < FBE::FieldModel");
+
4507 Indent(1);
+
4508
+
4509 // Generate struct field model constructor
+
4510 WriteLineIndent("def initialize(buffer, offset)");
+
4511 Indent(1);
+
4512 WriteLineIndent("super(buffer, offset)");
+
4513 std::string prev_offset("4");
+
4514 std::string prev_size("4");
+
4515 if (s->base && !s->base->empty())
+
4516 {
+
4517 WriteLineIndent("@_parent = " + base_type + ".new(self.buffer, " + prev_offset + " + " + prev_size + ")");
+
4518 prev_offset = "@_parent.fbe_offset";
+
4519 prev_size = "@_parent.fbe_body - 4 - 4";
+
4520 }
+
4521 if (s->body)
+
4522 {
+
4523 for (const auto& field : s->body->fields)
+
4524 {
+
4525 WriteLineIndent("@_" + *field->name + " = " + ConvertTypeFieldInitialization(*field, prev_offset + " + " + prev_size, false));
+
4526 prev_offset = "@_" + *field->name + ".fbe_offset";
+
4527 prev_size = "@_" + *field->name + ".fbe_size";
+
4528 }
+
4529 }
+
4530 Indent(-1);
+
4531 WriteLineIndent("end");
+
4532
+
4533 // Generate struct field model accessors
+
4534 if (s->base && !s->base->empty())
+
4535 {
+
4536 WriteLine();
+
4537 WriteLineIndent("def parent");
+
4538 Indent(1);
+
4539 WriteLineIndent("@_parent");
+
4540 Indent(-1);
+
4541 WriteLineIndent("end");
+
4542 }
+
4543 if (s->body)
+
4544 {
+
4545 for (const auto& field : s->body->fields)
+
4546 {
+
4547 WriteLine();
+
4548 WriteLineIndent("def " + *field->name);
+
4549 Indent(1);
+
4550 WriteLineIndent("@_" + *field->name);
+
4551 Indent(-1);
+
4552 WriteLineIndent("end");
+
4553 }
+
4554 }
+
4555
+
4556 // Generate struct field model FBE properties
+
4557 WriteLine();
+
4558 WriteLineIndent("# Get the field size");
+
4559 WriteLineIndent("def fbe_size");
+
4560 Indent(1);
+
4561 WriteLineIndent("4");
+
4562 Indent(-1);
+
4563 WriteLineIndent("end");
+
4564 WriteLine();
+
4565 WriteLineIndent("# Get the field body size");
+
4566 WriteLineIndent("def fbe_body");
+
4567 Indent(1);
+
4568 WriteLineIndent("4 + 4 \\");
+
4569 Indent(1);
+
4570 if (s->base && !s->base->empty())
+
4571 WriteLineIndent("+ parent.fbe_body - 4 - 4 \\");
+
4572 if (s->body)
+
4573 for (const auto& field : s->body->fields)
+
4574 WriteLineIndent("+ " + *field->name + ".fbe_size \\");
+
4575 Indent(-1);
+
4576 Indent(-1);
+
4577 WriteLineIndent("end");
+
4578 WriteLine();
+
4579 WriteLineIndent("# Get the field extra size");
+
4580 WriteLineIndent("def fbe_extra");
+
4581 Indent(1);
+
4582 WriteLineIndent("if (@_buffer.offset + fbe_offset + fbe_size) > @_buffer.size");
+
4583 Indent(1);
+
4584 WriteLineIndent("return 0");
+
4585 Indent(-1);
+
4586 WriteLineIndent("end");
+
4587 WriteLine();
+
4588 WriteLineIndent("fbe_struct_offset = read_uint32(fbe_offset)");
+
4589 WriteLineIndent("if (fbe_struct_offset == 0) || ((@_buffer.offset + fbe_struct_offset + 4) > @_buffer.size)");
+
4590 Indent(1);
+
4591 WriteLineIndent("return 0");
+
4592 Indent(-1);
+
4593 WriteLineIndent("end");
+
4594 WriteLine();
+
4595 WriteLineIndent("@_buffer.shift(fbe_struct_offset)");
+
4596 WriteLine();
+
4597 WriteLineIndent("fbe_result = fbe_body \\");
+
4598 Indent(1);
+
4599 if (s->base && !s->base->empty())
+
4600 WriteLineIndent("+ parent.fbe_extra \\");
+
4601 if (s->body)
+
4602 for (const auto& field : s->body->fields)
+
4603 WriteLineIndent("+ " + *field->name + ".fbe_extra \\");
+
4604 Indent(-1);
+
4605 WriteLine();
+
4606 WriteLineIndent("@_buffer.unshift(fbe_struct_offset)");
+
4607 WriteLine();
+
4608 WriteLineIndent("fbe_result");
+
4609 Indent(-1);
+
4610 WriteLineIndent("end");
+
4611 WriteLine();
+
4612 WriteLineIndent("# Get the field type");
+
4613 WriteLineIndent("def fbe_type");
+
4614 Indent(1);
+
4615 WriteLineIndent("TYPE");
+
4616 Indent(-1);
+
4617 WriteLineIndent("end");
+
4618
+
4619 // Generate struct field model type
+
4620 WriteLine();
+
4621 if (s->base && !s->base->empty() && (s->type == 0))
+
4622 WriteLineIndent("TYPE = " + base_type + "::TYPE");
+
4623 else
+
4624 WriteLineIndent("TYPE = " + std::to_string(s->type));
+
4625
+
4626 // Generate struct field model verify() method
+
4627 WriteLine();
+
4628 WriteLineIndent("# Is the struct value valid?");
+
4629 WriteLineIndent("def valid?");
+
4630 Indent(1);
+
4631 WriteLineIndent("verify");
+
4632 Indent(-1);
+
4633 WriteLineIndent("end");
+
4634 WriteLine();
+
4635 WriteLineIndent("# Check if the struct value is valid");
+
4636 WriteLineIndent("def verify(fbe_verify_type = true)");
+
4637 Indent(1);
+
4638 WriteLineIndent("if (@_buffer.offset + fbe_offset + fbe_size) > @_buffer.size");
+
4639 Indent(1);
+
4640 WriteLineIndent("return true");
+
4641 Indent(-1);
+
4642 WriteLineIndent("end");
+
4643 WriteLine();
+
4644 WriteLineIndent("fbe_struct_offset = read_uint32(fbe_offset)");
+
4645 WriteLineIndent("if (fbe_struct_offset == 0) || ((@_buffer.offset + fbe_struct_offset + 4 + 4) > @_buffer.size)");
+
4646 Indent(1);
+
4647 WriteLineIndent("return false");
+
4648 Indent(-1);
+
4649 WriteLineIndent("end");
+
4650 WriteLine();
+
4651 WriteLineIndent("fbe_struct_size = read_uint32(fbe_struct_offset)");
+
4652 WriteLineIndent("if fbe_struct_size < (4 + 4)");
+
4653 Indent(1);
+
4654 WriteLineIndent("return false");
+
4655 Indent(-1);
+
4656 WriteLineIndent("end");
+
4657 WriteLine();
+
4658 WriteLineIndent("fbe_struct_type = read_uint32(fbe_struct_offset + 4)");
+
4659 WriteLineIndent("if fbe_verify_type && (fbe_struct_type != fbe_type)");
+
4660 Indent(1);
+
4661 WriteLineIndent("return false");
+
4662 Indent(-1);
+
4663 WriteLineIndent("end");
+
4664 WriteLine();
+
4665 WriteLineIndent("@_buffer.shift(fbe_struct_offset)");
+
4666 WriteLineIndent("fbe_result = verify_fields(fbe_struct_size)");
+
4667 WriteLineIndent("@_buffer.unshift(fbe_struct_offset)");
+
4668 WriteLineIndent("fbe_result");
+
4669 Indent(-1);
+
4670 WriteLineIndent("end");
+
4671
+
4672 // Generate struct field model verify_fields() method
+
4673 WriteLine();
+
4674 WriteLineIndent("# Check if the struct fields are valid");
+
4675 WriteLineIndent("def verify_fields(fbe_struct_size)");
+
4676 Indent(1);
+
4677 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
4678 {
+
4679 WriteLineIndent("fbe_current_size = 4 + 4");
+
4680 if (s->base && !s->base->empty())
+
4681 {
+
4682 WriteLine();
+
4683 WriteLineIndent("if (fbe_current_size + parent.fbe_body - 4 - 4) > fbe_struct_size");
+
4684 Indent(1);
+
4685 WriteLineIndent("return true");
+
4686 Indent(-1);
+
4687 WriteLineIndent("end");
+
4688 WriteLineIndent("unless parent.verify_fields(fbe_struct_size)");
+
4689 Indent(1);
+
4690 WriteLineIndent("return false");
+
4691 Indent(-1);
+
4692 WriteLineIndent("end");
+
4693 WriteLineIndent("# noinspection RubyUnusedLocalVariable");
+
4694 WriteLineIndent("fbe_current_size += parent.fbe_body - 4 - 4");
+
4695 }
+
4696 if (s->body)
+
4697 {
+
4698 for (const auto& field : s->body->fields)
+
4699 {
+
4700 WriteLine();
+
4701 WriteLineIndent("if (fbe_current_size + " + *field->name + ".fbe_size) > fbe_struct_size");
+
4702 Indent(1);
+
4703 WriteLineIndent("return true");
+
4704 Indent(-1);
+
4705 WriteLineIndent("end");
+
4706 WriteLineIndent("unless " + *field->name + ".verify");
+
4707 Indent(1);
+
4708 WriteLineIndent("return false");
+
4709 Indent(-1);
+
4710 WriteLineIndent("end");
+
4711 WriteLineIndent("# noinspection RubyUnusedLocalVariable");
+
4712 WriteLineIndent("fbe_current_size += " + *field->name + ".fbe_size");
+
4713 }
+
4714 }
+
4715 WriteLine();
+
4716 }
+
4717 WriteLineIndent("true");
+
4718 Indent(-1);
+
4719 WriteLineIndent("end");
+
4720
+
4721 // Generate struct field model get_begin() method
+
4722 WriteLine();
+
4723 WriteLineIndent("# Get the struct value (begin phase)");
+
4724 WriteLineIndent("def get_begin");
+
4725 Indent(1);
+
4726 WriteLineIndent("if (@_buffer.offset + fbe_offset + fbe_size) > @_buffer.size");
+
4727 Indent(1);
+
4728 WriteLineIndent("return 0");
+
4729 Indent(-1);
+
4730 WriteLineIndent("end");
+
4731 WriteLine();
+
4732 WriteLineIndent("fbe_struct_offset = read_uint32(fbe_offset)");
+
4733 WriteLineIndent("if (fbe_struct_offset == 0) || ((@_buffer.offset + fbe_struct_offset + 4 + 4) > @_buffer.size)");
+
4734 Indent(1);
+
4735 WriteLineIndent("return 0");
+
4736 Indent(-1);
+
4737 WriteLineIndent("end");
+
4738 WriteLine();
+
4739 WriteLineIndent("fbe_struct_size = read_uint32(fbe_struct_offset)");
+
4740 WriteLineIndent("if fbe_struct_size < (4 + 4)");
+
4741 Indent(1);
+
4742 WriteLineIndent("return 0");
+
4743 Indent(-1);
+
4744 WriteLineIndent("end");
+
4745 WriteLine();
+
4746 WriteLineIndent("@_buffer.shift(fbe_struct_offset)");
+
4747 WriteLineIndent("fbe_struct_offset");
+
4748 Indent(-1);
+
4749 WriteLineIndent("end");
+
4750
+
4751 // Generate struct field model get_end() method
+
4752 WriteLine();
+
4753 WriteLineIndent("# Get the struct value (end phase)");
+
4754 WriteLineIndent("def get_end(fbe_begin)");
+
4755 Indent(1);
+
4756 WriteLineIndent("@_buffer.unshift(fbe_begin)");
+
4757 Indent(-1);
+
4758 WriteLineIndent("end");
+
4759
+
4760 // Generate struct field model get() method
+
4761 WriteLine();
+
4762 WriteLineIndent("# Get the struct value");
+
4763 WriteLineIndent("def get(fbe_value = " + struct_name + ".new)");
+
4764 Indent(1);
+
4765 WriteLineIndent("fbe_begin = get_begin");
+
4766 WriteLineIndent("if fbe_begin == 0");
+
4767 Indent(1);
+
4768 WriteLineIndent("return fbe_value");
+
4769 Indent(-1);
+
4770 WriteLineIndent("end");
+
4771 WriteLine();
+
4772 WriteLineIndent("fbe_struct_size = read_uint32(0)");
+
4773 WriteLineIndent("get_fields(fbe_value, fbe_struct_size)");
+
4774 WriteLineIndent("get_end(fbe_begin)");
+
4775 WriteLineIndent("fbe_value");
+
4776 Indent(-1);
+
4777 WriteLineIndent("end");
+
4778
+
4779 // Generate struct field model get_fields() method
+
4780 WriteLine();
+
4781 WriteLineIndent("# Get the struct fields values");
+
4782 WriteLineIndent("def get_fields(fbe_value, fbe_struct_size)");
+
4783 Indent(1);
+
4784 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
4785 {
+
4786 WriteLineIndent("fbe_current_size = 4 + 4");
+
4787 if (s->base && !s->base->empty())
+
4788 {
+
4789 WriteLine();
+
4790 WriteLineIndent("if (fbe_current_size + parent.fbe_body - 4 - 4) <= fbe_struct_size");
+
4791 Indent(1);
+
4792 WriteLineIndent("parent.get_fields(fbe_value, fbe_struct_size)");
+
4793 Indent(-1);
+
4794 WriteLineIndent("end");
+
4795 WriteLineIndent("# noinspection RubyUnusedLocalVariable");
+
4796 WriteLineIndent("fbe_current_size += parent.fbe_body - 4 - 4");
+
4797 }
+
4798 if (s->body)
+
4799 {
+
4800 for (const auto& field : s->body->fields)
+
4801 {
+
4802 WriteLine();
+
4803 WriteLineIndent("if (fbe_current_size + " + *field->name + ".fbe_size) <= fbe_struct_size");
+
4804 Indent(1);
+
4805 if (field->array || field->vector || field->list || field->set || field->map || field->hash)
+
4806 WriteLineIndent(*field->name + ".get(fbe_value." + *field->name + ")");
+
4807 else
+
4808 WriteLineIndent("fbe_value." + *field->name + " = " + *field->name + ".get" + (field->value ? ("(" + ConvertConstant(*field->type, *field->value, field->optional) + ")") : ""));
+
4809 Indent(-1);
+
4810 WriteLineIndent("else");
+
4811 Indent(1);
+
4812 if (field->array || field->vector || field->list || field->set || field->map || field->hash)
+
4813 WriteLineIndent("fbe_value." + *field->name + ".clear");
+
4814 else
+
4815 WriteLineIndent("fbe_value." + *field->name + " = " + ConvertDefault(*field));
+
4816 Indent(-1);
+
4817 WriteLineIndent("end");
+
4818 WriteLineIndent("# noinspection RubyUnusedLocalVariable");
+
4819 WriteLineIndent("fbe_current_size += " + *field->name + ".fbe_size");
+
4820 }
+
4821 }
+
4822 }
+
4823 Indent(-1);
+
4824 WriteLineIndent("end");
+
4825
+
4826 // Generate struct field model set_begin() method
+
4827 WriteLine();
+
4828 WriteLineIndent("# Set the struct value (begin phase)");
+
4829 WriteLineIndent("def set_begin");
+
4830 Indent(1);
+
4831 WriteLineIndent("if (@_buffer.offset + fbe_offset + fbe_size) > @_buffer.size");
+
4832 Indent(1);
+
4833 WriteLineIndent("return 0");
+
4834 Indent(-1);
+
4835 WriteLineIndent("end");
+
4836 WriteLine();
+
4837 WriteLineIndent("fbe_struct_size = fbe_body");
+
4838 WriteLineIndent("fbe_struct_offset = @_buffer.allocate(fbe_struct_size) - @_buffer.offset");
+
4839 WriteLineIndent("if (fbe_struct_offset <= 0) || ((@_buffer.offset + fbe_struct_offset + fbe_struct_size) > @_buffer.size)");
+
4840 Indent(1);
+
4841 WriteLineIndent("return 0");
+
4842 Indent(-1);
+
4843 WriteLineIndent("end");
+
4844 WriteLine();
+
4845 WriteLineIndent("write_uint32(fbe_offset, fbe_struct_offset)");
+
4846 WriteLineIndent("write_uint32(fbe_struct_offset, fbe_struct_size)");
+
4847 WriteLineIndent("write_uint32(fbe_struct_offset + 4, fbe_type)");
+
4848 WriteLine();
+
4849 WriteLineIndent("@_buffer.shift(fbe_struct_offset)");
+
4850 WriteLineIndent("fbe_struct_offset");
+
4851 Indent(-1);
+
4852 WriteLineIndent("end");
+
4853
+
4854 // Generate struct field model set_end() method
+
4855 WriteLine();
+
4856 WriteLineIndent("# Set the struct value (end phase)");
+
4857 WriteLineIndent("def set_end(fbe_begin)");
+
4858 Indent(1);
+
4859 WriteLineIndent("@_buffer.unshift(fbe_begin)");
+
4860 Indent(-1);
+
4861 WriteLineIndent("end");
+
4862
+
4863 // Generate struct field model set() method
+
4864 WriteLine();
+
4865 WriteLineIndent("# Set the struct value");
+
4866 WriteLineIndent("def set(fbe_value)");
+
4867 Indent(1);
+
4868 WriteLineIndent("fbe_begin = set_begin");
+
4869 WriteLineIndent("if fbe_begin == 0");
+
4870 Indent(1);
+
4871 WriteLineIndent("return");
+
4872 Indent(-1);
+
4873 WriteLineIndent("end");
+
4874 WriteLine();
+
4875 WriteLineIndent("set_fields(fbe_value)");
+
4876 WriteLineIndent("set_end(fbe_begin)");
+
4877 Indent(-1);
+
4878 WriteLineIndent("end");
+
4879
+
4880 // Generate struct field model set_fields() method
+
4881 WriteLine();
+
4882 WriteLineIndent("# Set the struct fields values");
+
4883 WriteLineIndent("def set_fields(fbe_value)");
+
4884 Indent(1);
+
4885 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
4886 {
+
4887 if (s->base && !s->base->empty())
+
4888 WriteLineIndent("parent.set_fields(fbe_value)");
+
4889 if (s->body)
+
4890 for (const auto& field : s->body->fields)
+
4891 WriteLineIndent(*field->name + ".set(fbe_value." + *field->name + ")");
+
4892 }
+
4893 Indent(-1);
+
4894 WriteLineIndent("end");
+
4895
+
4896 // Generate struct field model end
+
4897 Indent(-1);
+
4898 WriteLineIndent("end");
+
4899}
+
4900
+
4901void GeneratorRuby::GenerateStructModel(const std::shared_ptr<StructType>& s)
+
4902{
+
4903 std::string struct_name = ConvertTitle(*s->name);
+
4904
+
4905 // Generate struct model begin
+
4906 WriteLine();
+
4907 WriteLineIndent("# Fast Binary Encoding " + struct_name + " model");
+
4908 WriteLineIndent("class " + struct_name + "Model < FBE::Model");
+
4909 Indent(1);
+
4910
+
4911 // Generate struct model constructor
+
4912 WriteLineIndent("def initialize(buffer = FBE::WriteBuffer.new)");
+
4913 Indent(1);
+
4914 WriteLineIndent("super(buffer)");
+
4915 WriteLineIndent("@_model = FieldModel" + struct_name + ".new(self.buffer, 4)");
+
4916 Indent(-1);
+
4917 WriteLineIndent("end");
+
4918
+
4919 // Generate struct model accessor
+
4920 WriteLine();
+
4921 WriteLineIndent("def model");
+
4922 Indent(1);
+
4923 WriteLineIndent("@_model");
+
4924 Indent(-1);
+
4925 WriteLineIndent("end");
+
4926
+
4927 // Generate struct model FBE properties
+
4928 WriteLine();
+
4929 WriteLineIndent("# Get the model size");
+
4930 WriteLineIndent("def fbe_size");
+
4931 Indent(1);
+
4932 WriteLineIndent("@_model.fbe_size + @_model.fbe_extra");
+
4933 Indent(-1);
+
4934 WriteLineIndent("end");
+
4935 WriteLine();
+
4936 WriteLineIndent("# Get the model type");
+
4937 WriteLineIndent("def fbe_type");
+
4938 Indent(1);
+
4939 WriteLineIndent("TYPE");
+
4940 Indent(-1);
+
4941 WriteLineIndent("end");
+
4942
+
4943 // Generate struct model type
+
4944 WriteLine();
+
4945 WriteLineIndent("TYPE = FieldModel" + struct_name + "::TYPE");
+
4946
+
4947 // Generate struct model verify() method
+
4948 WriteLine();
+
4949 WriteLineIndent("# Is the struct value valid?");
+
4950 WriteLineIndent("def valid?");
+
4951 Indent(1);
+
4952 WriteLineIndent("verify");
+
4953 Indent(-1);
+
4954 WriteLineIndent("end");
+
4955 WriteLine();
+
4956 WriteLineIndent("# Check if the struct value is valid");
+
4957 WriteLineIndent("def verify");
+
4958 Indent(1);
+
4959 WriteLineIndent("if (buffer.offset + @_model.fbe_offset - 4) > buffer.size");
+
4960 Indent(1);
+
4961 WriteLineIndent("return false");
+
4962 Indent(-1);
+
4963 WriteLineIndent("end");
+
4964 WriteLine();
+
4965 WriteLineIndent("fbe_full_size = read_uint32(@_model.fbe_offset - 4)");
+
4966 WriteLineIndent("if fbe_full_size < @_model.fbe_size");
+
4967 Indent(1);
+
4968 WriteLineIndent("return false");
+
4969 Indent(-1);
+
4970 WriteLineIndent("end");
+
4971 WriteLine();
+
4972 WriteLineIndent("@_model.verify");
+
4973 Indent(-1);
+
4974 WriteLineIndent("end");
+
4975
+
4976 // Generate struct model create_begin() method
+
4977 WriteLine();
+
4978 WriteLineIndent("# Create a new model (begin phase)");
+
4979 WriteLineIndent("def create_begin");
+
4980 Indent(1);
+
4981 WriteLineIndent("buffer.allocate(4 + @_model.fbe_size)");
+
4982 Indent(-1);
+
4983 WriteLineIndent("end");
+
4984
+
4985 // Generate struct model create_end() method
+
4986 WriteLine();
+
4987 WriteLineIndent("# Create a new model (end phase)");
+
4988 WriteLineIndent("def create_end(fbe_begin)");
+
4989 Indent(1);
+
4990 WriteLineIndent("fbe_end = buffer.size");
+
4991 WriteLineIndent("fbe_full_size = fbe_end - fbe_begin");
+
4992 WriteLineIndent("write_uint32(@_model.fbe_offset - 4, fbe_full_size)");
+
4993 WriteLineIndent("fbe_full_size");
+
4994 Indent(-1);
+
4995 WriteLineIndent("end");
+
4996
+
4997 // Generate struct model serialize() method
+
4998 WriteLine();
+
4999 WriteLineIndent("# Serialize the struct value");
+
5000 WriteLineIndent("def serialize(value)");
+
5001 Indent(1);
+
5002 WriteLineIndent("fbe_begin = create_begin");
+
5003 WriteLineIndent("@_model.set(value)");
+
5004 WriteLineIndent("create_end(fbe_begin)");
+
5005 Indent(-1);
+
5006 WriteLineIndent("end");
+
5007
+
5008 // Generate struct model deserialize() methods
+
5009 WriteLine();
+
5010 WriteLineIndent("# Deserialize the struct value");
+
5011 WriteLineIndent("def deserialize(value = " + struct_name + ".new)");
+
5012 Indent(1);
+
5013 WriteLineIndent("if (buffer.offset + @_model.fbe_offset - 4) > buffer.size");
+
5014 Indent(1);
+
5015 WriteLineIndent("[" + struct_name + ".new, 0]");
+
5016 Indent(-1);
+
5017 WriteLineIndent("end");
+
5018 WriteLine();
+
5019 WriteLineIndent("fbe_full_size = read_uint32(@_model.fbe_offset - 4)");
+
5020 WriteLineIndent("if fbe_full_size < @_model.fbe_size");
+
5021 Indent(1);
+
5022 WriteLineIndent("[" + struct_name + ".new, 0]");
+
5023 Indent(-1);
+
5024 WriteLineIndent("end");
+
5025 WriteLine();
+
5026 WriteLineIndent("@_model.get(value)");
+
5027 WriteLineIndent("[value, fbe_full_size]");
+
5028 Indent(-1);
+
5029 WriteLineIndent("end");
+
5030
+
5031 // Generate struct model next() method
+
5032 WriteLine();
+
5033 WriteLineIndent("# Move to the next struct value");
+
5034 WriteLineIndent("def next(prev)");
+
5035 Indent(1);
+
5036 WriteLineIndent("@_model.fbe_shift(prev)");
+
5037 Indent(-1);
+
5038 WriteLineIndent("end");
+
5039
+
5040 // Generate struct model end
+
5041 Indent(-1);
+
5042 WriteLineIndent("end");
+
5043}
+
5044
+
5045void GeneratorRuby::GenerateStructFinalModel(const std::shared_ptr<StructType>& s)
+
5046{
+
5047 std::string struct_name = ConvertTitle(*s->name);
+
5048 std::string base_type = (s->base && !s->base->empty()) ? ConvertTypeFieldName(*s->base, true) : "";
+
5049
+
5050 // Generate struct final model begin
+
5051 WriteLine();
+
5052 WriteLineIndent("# noinspection RubyResolve, RubyScope, RubyTooManyInstanceVariablesInspection, RubyTooManyMethodsInspection");
+
5053 WriteLineIndent("class FinalModel" + struct_name + " < FBE::FinalModel");
+
5054 Indent(1);
+
5055
+
5056 // Generate struct final model constructor
+
5057 WriteLineIndent("def initialize(buffer, offset)");
+
5058 Indent(1);
+
5059 WriteLineIndent("super(buffer, offset)");
+
5060 if (s->base && !s->base->empty())
+
5061 WriteLineIndent("@_parent = " + base_type + ".new(self.buffer, 0)");
+
5062 if (s->body)
+
5063 for (const auto& field : s->body->fields)
+
5064 WriteLineIndent("@_" + *field->name + " = " + ConvertTypeFieldInitialization(*field, "0", true));
+
5065 Indent(-1);
+
5066 WriteLineIndent("end");
+
5067
+
5068 // Generate struct final model accessors
+
5069 if (s->base && !s->base->empty())
+
5070 {
+
5071 WriteLine();
+
5072 WriteLineIndent("def parent");
+
5073 Indent(1);
+
5074 WriteLineIndent("@_parent");
+
5075 Indent(-1);
+
5076 WriteLineIndent("end");
+
5077 }
+
5078 if (s->body)
+
5079 {
+
5080 for (const auto& field : s->body->fields)
+
5081 {
+
5082 WriteLine();
+
5083 WriteLineIndent("def " + *field->name);
+
5084 Indent(1);
+
5085 WriteLineIndent("@_" + *field->name);
+
5086 Indent(-1);
+
5087 WriteLineIndent("end");
+
5088 }
+
5089 }
+
5090
+
5091 // Generate struct final model FBE properties
+
5092 WriteLine();
+
5093 WriteLineIndent("# Get the allocation size");
+
5094 WriteLineIndent("def fbe_allocation_size(fbe_value)");
+
5095 Indent(1);
+
5096 WriteLineIndent("0 \\");
+
5097 Indent(1);
+
5098 if (s->base && !s->base->empty())
+
5099 WriteLineIndent("+ parent.fbe_allocation_size(fbe_value) \\");
+
5100 if (s->body)
+
5101 for (const auto& field : s->body->fields)
+
5102 WriteLineIndent("+ " + *field->name + ".fbe_allocation_size(fbe_value." + *field->name + ") \\");
+
5103 Indent(-1);
+
5104 Indent(-1);
+
5105 WriteLineIndent("end");
+
5106 WriteLine();
+
5107 WriteLineIndent("# Get the final type");
+
5108 WriteLineIndent("def fbe_type");
+
5109 Indent(1);
+
5110 WriteLineIndent("TYPE");
+
5111 Indent(-1);
+
5112 WriteLineIndent("end");
+
5113
+
5114 // Generate struct final model type
+
5115 WriteLine();
+
5116 if (s->base && !s->base->empty() && (s->type == 0))
+
5117 WriteLineIndent("TYPE = " + base_type + "::TYPE");
+
5118 else
+
5119 WriteLineIndent("TYPE = " + std::to_string(s->type));
+
5120
+
5121 // Generate struct final model verify() method
+
5122 WriteLine();
+
5123 WriteLineIndent("# Is the struct value valid?");
+
5124 WriteLineIndent("def valid?");
+
5125 Indent(1);
+
5126 WriteLineIndent("verify");
+
5127 Indent(-1);
+
5128 WriteLineIndent("end");
+
5129 WriteLine();
+
5130 WriteLineIndent("# Check if the struct value is valid");
+
5131 WriteLineIndent("def verify");
+
5132 Indent(1);
+
5133 WriteLineIndent("@_buffer.shift(fbe_offset)");
+
5134 WriteLineIndent("fbe_result = verify_fields");
+
5135 WriteLineIndent("@_buffer.unshift(fbe_offset)");
+
5136 WriteLineIndent("fbe_result");
+
5137 Indent(-1);
+
5138 WriteLineIndent("end");
+
5139
+
5140 // Generate struct final model verify_fields() method
+
5141 WriteLine();
+
5142 WriteLineIndent("# Check if the struct fields are valid");
+
5143 WriteLineIndent("def verify_fields");
+
5144 Indent(1);
+
5145 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
5146 {
+
5147 WriteLineIndent("fbe_current_offset = 0");
+
5148 if (s->base && !s->base->empty())
+
5149 {
+
5150 WriteLine();
+
5151 WriteLineIndent("parent.fbe_offset = fbe_current_offset");
+
5152 WriteLineIndent("fbe_field_size = parent.verify_fields");
+
5153 WriteLineIndent("if fbe_field_size == FBE::Integer::MAX");
+
5154 Indent(1);
+
5155 WriteLineIndent("return FBE::Integer::MAX");
+
5156 Indent(-1);
+
5157 WriteLineIndent("end");
+
5158 WriteLineIndent("fbe_current_offset += fbe_field_size");
+
5159 }
+
5160 if (s->body)
+
5161 {
+
5162 for (const auto& field : s->body->fields)
+
5163 {
+
5164 WriteLine();
+
5165 WriteLineIndent(*field->name + ".fbe_offset = fbe_current_offset");
+
5166 WriteLineIndent("fbe_field_size = " + *field->name + ".verify");
+
5167 WriteLineIndent("if fbe_field_size == FBE::Integer::MAX");
+
5168 Indent(1);
+
5169 WriteLineIndent("return FBE::Integer::MAX");
+
5170 Indent(-1);
+
5171 WriteLineIndent("end");
+
5172 WriteLineIndent("fbe_current_offset += fbe_field_size");
+
5173 }
+
5174 }
+
5175 WriteLine();
+
5176 WriteLineIndent("# noinspection RubyUnnecessaryReturnValue");
+
5177 WriteLineIndent("fbe_current_offset");
+
5178 }
+
5179 else
+
5180 WriteLineIndent("0");
+
5181 Indent(-1);
+
5182 WriteLineIndent("end");
+
5183
+
5184 // Generate struct final model get() method
+
5185 WriteLine();
+
5186 WriteLineIndent("# Get the struct value");
+
5187 WriteLineIndent("def get(fbe_value = " + struct_name + ".new)");
+
5188 Indent(1);
+
5189 WriteLineIndent("@_buffer.shift(fbe_offset)");
+
5190 WriteLineIndent("fbe_size = get_fields(fbe_value)");
+
5191 WriteLineIndent("@_buffer.unshift(fbe_offset)");
+
5192 WriteLineIndent("[fbe_value, fbe_size]");
+
5193 Indent(-1);
+
5194 WriteLineIndent("end");
+
5195
+
5196 // Generate struct final model get_fields() method
+
5197 WriteLine();
+
5198 WriteLineIndent("# Get the struct fields values");
+
5199 WriteLineIndent("def get_fields(fbe_value)");
+
5200 Indent(1);
+
5201 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
5202 {
+
5203 WriteLineIndent("fbe_current_offset = 0");
+
5204 WriteLineIndent("fbe_current_size = 0");
+
5205 if (s->base && !s->base->empty())
+
5206 {
+
5207 WriteLine();
+
5208 WriteLineIndent("parent.fbe_offset = fbe_current_offset");
+
5209 WriteLineIndent("fbe_result = parent.get_fields(fbe_value)");
+
5210 WriteLineIndent("# noinspection RubyUnusedLocalVariable");
+
5211 WriteLineIndent("fbe_current_offset += fbe_result");
+
5212 WriteLineIndent("fbe_current_size += fbe_result");
+
5213 }
+
5214 if (s->body)
+
5215 {
+
5216 for (const auto& field : s->body->fields)
+
5217 {
+
5218 WriteLine();
+
5219 WriteLineIndent(*field->name + ".fbe_offset = fbe_current_offset");
+
5220 if (field->array || field->vector || field->list || field->set || field->map || field->hash)
+
5221 WriteLineIndent("fbe_result = " + *field->name + ".get(fbe_value." + *field->name + ")");
+
5222 else
+
5223 {
+
5224 WriteLineIndent("fbe_result = " + *field->name + ".get");
+
5225 WriteLineIndent("fbe_value." + *field->name + " = fbe_result[0]");
+
5226 }
+
5227 WriteLineIndent("# noinspection RubyUnusedLocalVariable");
+
5228 WriteLineIndent("fbe_current_offset += fbe_result[1]");
+
5229 WriteLineIndent("fbe_current_size += fbe_result[1]");
+
5230 }
+
5231 }
+
5232 WriteLine();
+
5233 WriteLineIndent("# noinspection RubyUnnecessaryReturnValue");
+
5234 WriteLineIndent("fbe_current_size");
+
5235 }
+
5236 else
+
5237 WriteLineIndent("0");
+
5238 Indent(-1);
+
5239 WriteLineIndent("end");
+
5240
+
5241 // Generate struct final model set() method
+
5242 WriteLine();
+
5243 WriteLineIndent("# Set the struct value");
+
5244 WriteLineIndent("def set(fbe_value)");
+
5245 Indent(1);
+
5246 WriteLineIndent("@_buffer.shift(fbe_offset)");
+
5247 WriteLineIndent("fbe_size = set_fields(fbe_value)");
+
5248 WriteLineIndent("@_buffer.unshift(fbe_offset)");
+
5249 WriteLineIndent("fbe_size");
+
5250 Indent(-1);
+
5251 WriteLineIndent("end");
+
5252
+
5253 // Generate struct final model set_fields() method
+
5254 WriteLine();
+
5255 WriteLineIndent("# Set the struct fields values");
+
5256 WriteLineIndent("def set_fields(fbe_value)");
+
5257 Indent(1);
+
5258 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
5259 {
+
5260 WriteLineIndent("fbe_current_offset = 0");
+
5261 WriteLineIndent("fbe_current_size = 0");
+
5262 if (s->base && !s->base->empty())
+
5263 {
+
5264 WriteLine();
+
5265 WriteLineIndent("parent.fbe_offset = fbe_current_offset");
+
5266 WriteLineIndent("fbe_field_size = parent.set_fields(fbe_value)");
+
5267 WriteLineIndent("# noinspection RubyUnusedLocalVariable");
+
5268 WriteLineIndent("fbe_current_offset += fbe_field_size");
+
5269 WriteLineIndent("fbe_current_size += fbe_field_size");
+
5270 }
+
5271 if (s->body)
+
5272 {
+
5273 for (const auto& field : s->body->fields)
+
5274 {
+
5275 WriteLine();
+
5276 WriteLineIndent(*field->name + ".fbe_offset = fbe_current_offset");
+
5277 WriteLineIndent("fbe_field_size = " + *field->name + ".set(fbe_value." + *field->name + ")");
+
5278 WriteLineIndent("# noinspection RubyUnusedLocalVariable");
+
5279 WriteLineIndent("fbe_current_offset += fbe_field_size");
+
5280 WriteLineIndent("fbe_current_size += fbe_field_size");
+
5281 }
+
5282 }
+
5283 WriteLine();
+
5284 WriteLineIndent("# noinspection RubyUnnecessaryReturnValue");
+
5285 WriteLineIndent("fbe_current_size");
+
5286 }
+
5287 else
+
5288 WriteLineIndent("0");
+
5289 Indent(-1);
+
5290 WriteLineIndent("end");
+
5291
+
5292 // Generate struct final model end
+
5293 Indent(-1);
+
5294 WriteLineIndent("end");
+
5295}
+
5296
+
5297void GeneratorRuby::GenerateStructModelFinal(const std::shared_ptr<StructType>& s)
+
5298{
+
5299 std::string struct_name = ConvertTitle(*s->name);
+
5300
+
5301 // Generate struct model final begin
+
5302 WriteLine();
+
5303 WriteLineIndent("# Fast Binary Encoding " + struct_name + " final model");
+
5304 WriteLineIndent("class " + struct_name + "FinalModel < FBE::Model");
+
5305 Indent(1);
+
5306
+
5307 // Generate struct model final constructor
+
5308 WriteLineIndent("def initialize(buffer = FBE::WriteBuffer.new)");
+
5309 Indent(1);
+
5310 WriteLineIndent("super(buffer)");
+
5311 WriteLineIndent("@_model = FinalModel" + struct_name + ".new(self.buffer, 8)");
+
5312 Indent(-1);
+
5313 WriteLineIndent("end");
+
5314
+
5315 // Generate struct model final FBE properties
+
5316 WriteLine();
+
5317 WriteLineIndent("# Get the model type");
+
5318 WriteLineIndent("def fbe_type");
+
5319 Indent(1);
+
5320 WriteLineIndent("TYPE");
+
5321 Indent(-1);
+
5322 WriteLineIndent("end");
+
5323
+
5324 // Generate struct model type
+
5325 WriteLine();
+
5326 WriteLineIndent("TYPE = FinalModel" + struct_name + "::TYPE");
+
5327
+
5328 // Generate struct model final verify() method
+
5329 WriteLine();
+
5330 WriteLineIndent("# Is the struct value valid?");
+
5331 WriteLineIndent("def valid?");
+
5332 Indent(1);
+
5333 WriteLineIndent("verify");
+
5334 Indent(-1);
+
5335 WriteLineIndent("end");
+
5336 WriteLine();
+
5337 WriteLineIndent("# Check if the struct value is valid");
+
5338 WriteLineIndent("def verify");
+
5339 Indent(1);
+
5340 WriteLineIndent("if (buffer.offset + @_model.fbe_offset) > buffer.size");
+
5341 Indent(1);
+
5342 WriteLineIndent("return false");
+
5343 Indent(-1);
+
5344 WriteLineIndent("end");
+
5345 WriteLine();
+
5346 WriteLineIndent("fbe_struct_size = read_uint32(@_model.fbe_offset - 8)");
+
5347 WriteLineIndent("fbe_struct_type = read_uint32(@_model.fbe_offset - 4)");
+
5348 WriteLineIndent("if (fbe_struct_size <= 0) or (fbe_struct_type != fbe_type)");
+
5349 Indent(1);
+
5350 WriteLineIndent("return false");
+
5351 Indent(-1);
+
5352 WriteLineIndent("end");
+
5353 WriteLine();
+
5354 WriteLineIndent("(8 + @_model.verify) == fbe_struct_size");
+
5355 Indent(-1);
+
5356 WriteLineIndent("end");
+
5357
+
5358 // Generate struct model final serialize() method
+
5359 WriteLine();
+
5360 WriteLineIndent("# Serialize the struct value");
+
5361 WriteLineIndent("def serialize(value)");
+
5362 Indent(1);
+
5363 WriteLineIndent("fbe_initial_size = buffer.size");
+
5364 WriteLine();
+
5365 WriteLineIndent("fbe_struct_type = fbe_type");
+
5366 WriteLineIndent("fbe_struct_size = 8 + @_model.fbe_allocation_size(value)");
+
5367 WriteLineIndent("fbe_struct_offset = buffer.allocate(fbe_struct_size) - buffer.offset");
+
5368 WriteLineIndent("if (buffer.offset + fbe_struct_offset + fbe_struct_size) > buffer.size");
+
5369 Indent(1);
+
5370 WriteLineIndent("return 0");
+
5371 Indent(-1);
+
5372 WriteLineIndent("end");
+
5373 WriteLine();
+
5374 WriteLineIndent("fbe_struct_size = 8 + @_model.set(value)");
+
5375 WriteLineIndent("buffer.resize(fbe_initial_size + fbe_struct_size)");
+
5376 WriteLine();
+
5377 WriteLineIndent("write_uint32(@_model.fbe_offset - 8, fbe_struct_size)");
+
5378 WriteLineIndent("write_uint32(@_model.fbe_offset - 4, fbe_struct_type)");
+
5379 WriteLine();
+
5380 WriteLineIndent("fbe_struct_size");
+
5381 Indent(-1);
+
5382 WriteLineIndent("end");
+
5383
+
5384 // Generate struct model final deserialize() methods
+
5385 WriteLine();
+
5386 WriteLineIndent("# Deserialize the struct value");
+
5387 WriteLineIndent("def deserialize(value = " + struct_name + ".new)");
+
5388 Indent(1);
+
5389 WriteLineIndent("if (buffer.offset + @_model.fbe_offset) > buffer.size");
+
5390 Indent(1);
+
5391 WriteLineIndent("[" + struct_name + ".new, 0]");
+
5392 Indent(-1);
+
5393 WriteLineIndent("end");
+
5394 WriteLine();
+
5395 WriteLineIndent("fbe_struct_size = read_uint32(@_model.fbe_offset - 8)");
+
5396 WriteLineIndent("fbe_struct_type = read_uint32(@_model.fbe_offset - 4)");
+
5397 WriteLineIndent("if (fbe_struct_size <= 0) || (fbe_struct_type != fbe_type)");
+
5398 Indent(1);
+
5399 WriteLineIndent("[" + struct_name + ".new, 8]");
+
5400 Indent(-1);
+
5401 WriteLineIndent("end");
+
5402 WriteLine();
+
5403 WriteLineIndent("fbe_result = @_model.get(value)");
+
5404 WriteLineIndent("[fbe_result[0], (8 + fbe_result[1])]");
+
5405 Indent(-1);
+
5406 WriteLineIndent("end");
+
5407
+
5408 // Generate struct model final next() method
+
5409 WriteLine();
+
5410 WriteLineIndent("# Move to the next struct value");
+
5411 WriteLineIndent("def next(prev)");
+
5412 Indent(1);
+
5413 WriteLineIndent("@_model.fbe_shift(prev)");
+
5414 Indent(-1);
+
5415 WriteLineIndent("end");
+
5416
+
5417 // Generate struct model final end
+
5418 Indent(-1);
+
5419 WriteLineIndent("end");
+
5420}
+
5421
+
5422void GeneratorRuby::GenerateProtocolVersion(const std::shared_ptr<Package>& p)
+
5423{
+
5424 std::string package = ConvertTitle(*p->name);
+
5425
+
5426 // Generate protocol version class
+
5427 WriteLine();
+
5428 WriteLineIndent("# Fast Binary Encoding " + package + " protocol version");
+
5429 WriteLineIndent("class ProtocolVersion");
+
5430 Indent(1);
+
5431 WriteLineIndent("# Protocol major version");
+
5432 WriteLineIndent("MAJOR = " + std::to_string(p->version->major));
+
5433 WriteLineIndent("# Protocol minor version");
+
5434 WriteLineIndent("MINOR = " + std::to_string(p->version->minor));
+
5435 Indent(-1);
+
5436 WriteLineIndent("end");
+
5437}
+
5438
+
5439void GeneratorRuby::GenerateSender(const std::shared_ptr<Package>& p, bool final)
+
5440{
+
5441 std::string package = ConvertTitle(*p->name);
+
5442 std::string sender = (final ? "FinalSender" : "Sender");
+
5443 std::string model = (final ? "FinalModel" : "Model");
+
5444
+
5445 // Generate sender begin
+
5446 WriteLine();
+
5447 if (final)
+
5448 WriteLineIndent("# Fast Binary Encoding " + package + " final sender");
+
5449 else
+
5450 WriteLineIndent("# Fast Binary Encoding " + package + " sender");
+
5451 WriteLineIndent("# noinspection RubyResolve, RubyScope, RubyTooManyInstanceVariablesInspection, RubyTooManyMethodsInspection");
+
5452 WriteLineIndent("class " + sender + " < FBE::Sender");
+
5453 Indent(1);
+
5454
+
5455 // Generate sender constructor
+
5456 WriteLineIndent("def initialize(buffer = FBE::WriteBuffer.new)");
+
5457 Indent(1);
+
5458 WriteLineIndent("super(buffer, " + std::string(final ? "true" : "false") + ")");
+
5459 if (p->import)
+
5460 {
+
5461 for (const auto& import : p->import->imports)
+
5462 WriteLineIndent("@_" + CppCommon::StringUtils::ToLower(*import) + "_sender = " + ConvertTitle(*import) + "::" + sender + ".new(self.buffer)");
+
5463 }
+
5464 if (p->body)
+
5465 {
+
5466 for (const auto& s : p->body->structs)
+
5467 if (s->message)
+
5468 WriteLineIndent("@_" + CppCommon::StringUtils::ToLower(*s->name) + "_model = " + ConvertTitle(*s->name) + model + ".new(self.buffer)");
+
5469 }
+
5470 Indent(-1);
+
5471 WriteLineIndent("end");
+
5472
+
5473 // Generate imported senders accessors
+
5474 if (p->import)
+
5475 {
+
5476 WriteLine();
+
5477 WriteLineIndent("# Imported senders");
+
5478 for (const auto& import : p->import->imports)
+
5479 {
+
5480 WriteLine();
+
5481 WriteLineIndent("def " + CppCommon::StringUtils::ToLower(*import) + "_sender");
+
5482 Indent(1);
+
5483 WriteLineIndent("@_" + CppCommon::StringUtils::ToLower(*import) + "_sender");
+
5484 Indent(-1);
+
5485 WriteLineIndent("end");
+
5486 }
+
5487 }
+
5488
+
5489 // Generate sender models accessors
+
5490 if (p->body)
+
5491 {
+
5492 WriteLine();
+
5493 WriteLineIndent("# Sender models accessors");
+
5494 for (const auto& s : p->body->structs)
+
5495 {
+
5496 if (s->message)
+
5497 {
+
5498 WriteLine();
+
5499 WriteLineIndent("def " + CppCommon::StringUtils::ToLower(*s->name) + "_model");
+
5500 Indent(1);
+
5501 WriteLineIndent("@_" + CppCommon::StringUtils::ToLower(*s->name) + "_model");
+
5502 Indent(-1);
+
5503 WriteLineIndent("end");
+
5504 }
+
5505 }
+
5506 }
+
5507
+
5508 // Generate sender methods
+
5509 WriteLine();
+
5510 WriteLineIndent("# Send methods");
+
5511 WriteLine();
+
5512 WriteLineIndent("def send(value)");
+
5513 Indent(1);
+
5514 if (p->body)
+
5515 {
+
5516 for (const auto& s : p->body->structs)
+
5517 {
+
5518 if (s->message)
+
5519 {
+
5520 WriteLineIndent("if value.is_a?(" + ConvertTitle(*s->name) + ") && (value.fbe_type == " + CppCommon::StringUtils::ToLower(*s->name) + "_model.fbe_type)");
+
5521 Indent(1);
+
5522 WriteLineIndent("return send_" + CppCommon::StringUtils::ToLower(*s->name) + "(value)");
+
5523 Indent(-1);
+
5524 WriteLineIndent("end");
+
5525 }
+
5526 }
+
5527 }
+
5528 if (p->import)
+
5529 {
+
5530 for (const auto& import : p->import->imports)
+
5531 {
+
5532 WriteLineIndent("result = @_" + CppCommon::StringUtils::ToLower(*import) + "_sender.send(value)");
+
5533 WriteLineIndent("if result > 0");
+
5534 Indent(1);
+
5535 WriteLineIndent("return result");
+
5536 Indent(-1);
+
5537 WriteLineIndent("end");
+
5538 }
+
5539 }
+
5540 WriteLineIndent("0");
+
5541 Indent(-1);
+
5542 WriteLineIndent("end");
+
5543 if (p->body)
+
5544 {
+
5545 for (const auto& s : p->body->structs)
+
5546 {
+
5547 if (s->message)
+
5548 {
+
5549 WriteLine();
+
5550 WriteLineIndent("def send_" + CppCommon::StringUtils::ToLower(*s->name) + "(value)");
+
5551 Indent(1);
+
5552 WriteLineIndent("# Serialize the value into the FBE stream");
+
5553 WriteLineIndent("serialized = " + CppCommon::StringUtils::ToLower(*s->name) + "_model.serialize(value)");
+
5554 WriteLineIndent("raise RuntimeError, \"" + package + "." + ConvertTitle(*s->name) + " serialization failed!\" if serialized <= 0");
+
5555 WriteLineIndent("raise RuntimeError, \"" + package + "." + ConvertTitle(*s->name) + " validation failed!\" unless " + CppCommon::StringUtils::ToLower(*s->name) + "_model.verify");
+
5556 WriteLine();
+
5557 WriteLineIndent("# Log the value");
+
5558 WriteLineIndent("if logging?");
+
5559 Indent(1);
+
5560 WriteLineIndent("message = value.to_s");
+
5561 WriteLineIndent("on_send_log(message)");
+
5562 Indent(-1);
+
5563 WriteLineIndent("end");
+
5564 WriteLine();
+
5565 WriteLineIndent("# Send the serialized value");
+
5566 WriteLineIndent("send_serialized(serialized)");
+
5567 Indent(-1);
+
5568 WriteLineIndent("end");
+
5569 }
+
5570 }
+
5571 }
+
5572
+
5573 // Generate sender message handler
+
5574 WriteLine();
+
5575 WriteLineIndent("protected");
+
5576 WriteLine();
+
5577 WriteLineIndent("# Send message handler");
+
5578 WriteLineIndent("def on_send(buffer, offset, size)");
+
5579 Indent(1);
+
5580 WriteLineIndent("raise NotImplementedError, \"" + package + ".Sender.on_send() not implemented!\"");
+
5581 Indent(-1);
+
5582 WriteLineIndent("end");
+
5583
+
5584 // Generate sender end
+
5585 Indent(-1);
+
5586 WriteLineIndent("end");
+
5587}
+
5588
+
5589void GeneratorRuby::GenerateReceiver(const std::shared_ptr<Package>& p, bool final)
+
5590{
+
5591 std::string package = ConvertTitle(*p->name);
+
5592 std::string receiver = (final ? "FinalReceiver" : "Receiver");
+
5593 std::string model = (final ? "FinalModel" : "Model");
+
5594
+
5595 // Generate receiver begin
+
5596 WriteLine();
+
5597 if (final)
+
5598 WriteLineIndent("# Fast Binary Encoding " + package + " final receiver");
+
5599 else
+
5600 WriteLineIndent("# Fast Binary Encoding " + package + " receiver");
+
5601 WriteLineIndent("# noinspection RubyResolve, RubyScope, RubyTooManyInstanceVariablesInspection, RubyTooManyMethodsInspection");
+
5602 WriteLineIndent("class " + receiver + " < FBE::Receiver");
+
5603 Indent(1);
+
5604
+
5605 // Generate receiver constructor
+
5606 WriteLineIndent("def initialize(buffer = FBE::WriteBuffer.new)");
+
5607 Indent(1);
+
5608 WriteLineIndent("super(buffer, " + std::string(final ? "true" : "false") + ")");
+
5609 if (p->import)
+
5610 {
+
5611 for (const auto& import : p->import->imports)
+
5612 WriteLineIndent("@_" + CppCommon::StringUtils::ToLower(*import) + "_receiver = " + ConvertTitle(*import) + "::" + receiver + ".new(self.buffer)");
+
5613 }
+
5614 if (p->body)
+
5615 {
+
5616 for (const auto& s : p->body->structs)
+
5617 {
+
5618 if (s->message)
+
5619 {
+
5620 WriteLineIndent("@_" + CppCommon::StringUtils::ToLower(*s->name) + "_value = " + ConvertTitle(*s->name) + ".new");
+
5621 WriteLineIndent("@_" + CppCommon::StringUtils::ToLower(*s->name) + "_model = " + ConvertTitle(*s->name) + model + ".new");
+
5622 }
+
5623 }
+
5624 }
+
5625 Indent(-1);
+
5626 WriteLineIndent("end");
+
5627
+
5628 // Generate imported receiver accessors
+
5629 if (p->import)
+
5630 {
+
5631 WriteLine();
+
5632 WriteLineIndent("# Imported receivers");
+
5633 for (const auto& import : p->import->imports)
+
5634 {
+
5635 WriteLine();
+
5636 WriteLineIndent("def " + CppCommon::StringUtils::ToLower(*import) + "_receiver");
+
5637 Indent(1);
+
5638 WriteLineIndent("@_" + CppCommon::StringUtils::ToLower(*import) + "_receiver");
+
5639 Indent(-1);
+
5640 WriteLineIndent("end");
+
5641 WriteLine();
+
5642 WriteLineIndent("def " + CppCommon::StringUtils::ToLower(*import) + "_receiver=(receiver)");
+
5643 Indent(1);
+
5644 WriteLineIndent("@_" + CppCommon::StringUtils::ToLower(*import) + "_receiver = receiver");
+
5645 Indent(-1);
+
5646 WriteLineIndent("end");
+
5647 }
+
5648 }
+
5649
+
5650 WriteLine();
+
5651 WriteLineIndent("protected");
+
5652
+
5653 // Generate receiver handlers
+
5654 if (p->body)
+
5655 {
+
5656 WriteLine();
+
5657 WriteLineIndent("# Receive handlers");
+
5658 for (const auto& s : p->body->structs)
+
5659 {
+
5660 if (s->message)
+
5661 {
+
5662 WriteLine();
+
5663 WriteLineIndent("# noinspection RubyUnusedLocalVariable");
+
5664 WriteLineIndent("def on_receive_" + CppCommon::StringUtils::ToLower(*s->name) + "(value)");
+
5665 WriteLineIndent("end");
+
5666 }
+
5667 }
+
5668 }
+
5669
+
5670 WriteLine();
+
5671 WriteLineIndent("public");
+
5672
+
5673 bool messages = false;
+
5674 for (const auto& s : p->body->structs)
+
5675 if (s->message)
+
5676 messages = true;
+
5677
+
5678 // Generate receiver message handler
+
5679 WriteLine();
+
5680 WriteLineIndent("def on_receive(type, buffer, offset, size)");
+
5681 Indent(1);
+
5682 if (p->body && messages)
+
5683 {
+
5684 WriteLineIndent("case type");
+
5685 for (const auto& s : p->body->structs)
+
5686 {
+
5687 if (s->message)
+
5688 {
+
5689 WriteLineIndent("when " + ConvertTitle(*s->name) + model + "::TYPE");
+
5690 Indent(1);
+
5691 WriteLineIndent("# Deserialize the value from the FBE stream");
+
5692 WriteLineIndent("@_" + CppCommon::StringUtils::ToLower(*s->name) + "_model.attach_buffer(buffer, offset)");
+
5693 WriteLineIndent("unless @_" + CppCommon::StringUtils::ToLower(*s->name) + "_model.verify");
+
5694 Indent(1);
+
5695 WriteLineIndent("return false");
+
5696 Indent(-1);
+
5697 WriteLineIndent("end");
+
5698 WriteLineIndent("_, deserialized = @_" + CppCommon::StringUtils::ToLower(*s->name) + "_model.deserialize(@_" + CppCommon::StringUtils::ToLower(*s->name) + "_value)");
+
5699 WriteLineIndent("if deserialized <= 0");
+
5700 Indent(1);
+
5701 WriteLineIndent("return false");
+
5702 Indent(-1);
+
5703 WriteLineIndent("end");
+
5704 WriteLine();
+
5705 WriteLineIndent("# Log the value");
+
5706 WriteLineIndent("if logging?");
+
5707 Indent(1);
+
5708 WriteLineIndent("message = @_" + CppCommon::StringUtils::ToLower(*s->name) + "_value.to_s");
+
5709 WriteLineIndent("on_receive_log(message)");
+
5710 Indent(-1);
+
5711 WriteLineIndent("end");
+
5712 WriteLine();
+
5713 WriteLineIndent("# Call receive handler with deserialized value");
+
5714 WriteLineIndent("on_receive_" + CppCommon::StringUtils::ToLower(*s->name) + "(@_" + CppCommon::StringUtils::ToLower(*s->name) + "_value)");
+
5715 WriteLineIndent("true");
+
5716 Indent(-1);
+
5717 }
+
5718 }
+
5719 WriteLineIndent("else");
+
5720 Indent(1);
+
5721 WriteLineIndent("# Do nothing here...");
+
5722 Indent(-1);
+
5723 WriteLineIndent("end");
+
5724 }
+
5725 if (p->import)
+
5726 {
+
5727 WriteLine();
+
5728 for (const auto& import : p->import->imports)
+
5729 {
+
5730 WriteLineIndent("if !" + CppCommon::StringUtils::ToLower(*import) + "_receiver.nil? && " + CppCommon::StringUtils::ToLower(*import) + "_receiver.on_receive(type, buffer, offset, size)");
+
5731 Indent(1);
+
5732 WriteLineIndent("return true");
+
5733 Indent(-1);
+
5734 WriteLineIndent("end");
+
5735 }
+
5736 }
+
5737 WriteLine();
+
5738 WriteLineIndent("false");
+
5739 Indent(-1);
+
5740 WriteLineIndent("end");
+
5741
+
5742 // Generate receiver end
+
5743 Indent(-1);
+
5744 WriteLineIndent("end");
+
5745}
+
5746
+
5747void GeneratorRuby::GenerateProxy(const std::shared_ptr<Package>& p, bool final)
+
5748{
+
5749 std::string package = ConvertTitle(*p->name);
+
5750 std::string proxy = (final ? "FinalProxy" : "Proxy");
+
5751 std::string model = (final ? "FinalModel" : "Model");
+
5752
+
5753 // Generate proxy begin
+
5754 WriteLine();
+
5755 if (final)
+
5756 WriteLineIndent("# Fast Binary Encoding " + package + " final proxy");
+
5757 else
+
5758 WriteLineIndent("# Fast Binary Encoding " + package + " proxy");
+
5759 WriteLineIndent("# noinspection RubyResolve, RubyScope, RubyTooManyInstanceVariablesInspection, RubyTooManyMethodsInspection");
+
5760 WriteLineIndent("class " + proxy + " < FBE::Receiver");
+
5761 Indent(1);
+
5762
+
5763 // Generate proxy constructor
+
5764 WriteLineIndent("def initialize(buffer = FBE::WriteBuffer.new)");
+
5765 Indent(1);
+
5766 WriteLineIndent("super(buffer, " + std::string(final ? "true" : "false") + ")");
+
5767 if (p->import)
+
5768 {
+
5769 for (const auto& import : p->import->imports)
+
5770 WriteLineIndent("@_" + CppCommon::StringUtils::ToLower(*import) + "_proxy = " + ConvertTitle(*import) + "::" + proxy + ".new(self.buffer)");
+
5771 }
+
5772 if (p->body)
+
5773 {
+
5774 for (const auto& s : p->body->structs)
+
5775 if (s->message)
+
5776 WriteLineIndent("@_" + CppCommon::StringUtils::ToLower(*s->name) + "_model = " + ConvertTitle(*s->name) + model + ".new");
+
5777 }
+
5778 Indent(-1);
+
5779 WriteLineIndent("end");
+
5780
+
5781 // Generate imported proxy accessors
+
5782 if (p->import)
+
5783 {
+
5784 WriteLine();
+
5785 WriteLineIndent("# Imported proxy");
+
5786 for (const auto& import : p->import->imports)
+
5787 {
+
5788 WriteLine();
+
5789 WriteLineIndent("def " + CppCommon::StringUtils::ToLower(*import) + "_proxy");
+
5790 Indent(1);
+
5791 WriteLineIndent("@_" + CppCommon::StringUtils::ToLower(*import) + "_proxy");
+
5792 Indent(-1);
+
5793 WriteLineIndent("end");
+
5794 WriteLine();
+
5795 WriteLineIndent("def " + CppCommon::StringUtils::ToLower(*import) + "_proxy=(proxy)");
+
5796 Indent(1);
+
5797 WriteLineIndent("@_" + CppCommon::StringUtils::ToLower(*import) + "_proxy = proxy");
+
5798 Indent(-1);
+
5799 WriteLineIndent("end");
+
5800 }
+
5801 }
+
5802
+
5803 WriteLine();
+
5804 WriteLineIndent("protected");
+
5805
+
5806 // Generate proxy handlers
+
5807 if (p->body)
+
5808 {
+
5809 WriteLine();
+
5810 WriteLineIndent("# Receive handlers");
+
5811 for (const auto& s : p->body->structs)
+
5812 {
+
5813 if (s->message)
+
5814 {
+
5815 WriteLine();
+
5816 WriteLineIndent("# noinspection RubyUnusedLocalVariable");
+
5817 WriteLineIndent("def on_proxy_" + CppCommon::StringUtils::ToLower(*s->name) + "(model, type, buffer, offset, size)");
+
5818 WriteLineIndent("end");
+
5819 }
+
5820 }
+
5821 }
+
5822
+
5823 WriteLine();
+
5824 WriteLineIndent("public");
+
5825
+
5826 bool messages = false;
+
5827 for (const auto& s : p->body->structs)
+
5828 if (s->message)
+
5829 messages = true;
+
5830
+
5831 // Generate proxy message handler
+
5832 WriteLine();
+
5833 WriteLineIndent("def on_receive(type, buffer, offset, size)");
+
5834 Indent(1);
+
5835 if (p->body && messages)
+
5836 {
+
5837 WriteLineIndent("case type");
+
5838 for (const auto& s : p->body->structs)
+
5839 {
+
5840 if (s->message)
+
5841 {
+
5842 WriteLineIndent("when " + ConvertTitle(*s->name) + model + "::TYPE");
+
5843 Indent(1);
+
5844 WriteLineIndent("# Attach the FBE stream to the proxy model");
+
5845 WriteLineIndent("@_" + CppCommon::StringUtils::ToLower(*s->name) + "_model.attach_buffer(buffer, offset)");
+
5846 WriteLineIndent("unless @_" + CppCommon::StringUtils::ToLower(*s->name) + "_model.verify");
+
5847 Indent(1);
+
5848 WriteLineIndent("return false");
+
5849 Indent(-1);
+
5850 WriteLineIndent("end");
+
5851 WriteLine();
+
5852 WriteLineIndent("fbe_begin = @_" + CppCommon::StringUtils::ToLower(*s->name) + "_model.model.get_begin");
+
5853 WriteLineIndent("if fbe_begin == 0");
+
5854 Indent(1);
+
5855 WriteLineIndent("return false");
+
5856 Indent(-1);
+
5857 WriteLineIndent("end");
+
5858 WriteLineIndent("# Call proxy handler");
+
5859 WriteLineIndent("on_proxy_" + CppCommon::StringUtils::ToLower(*s->name) + "(@_" + CppCommon::StringUtils::ToLower(*s->name) + "_model, type, buffer, offset, size)");
+
5860 WriteLineIndent("@_" + CppCommon::StringUtils::ToLower(*s->name) + "_model.model.get_end(fbe_begin)");
+
5861 WriteLineIndent("true");
+
5862 Indent(-1);
+
5863 }
+
5864 }
+
5865 WriteLineIndent("else");
+
5866 Indent(1);
+
5867 WriteLineIndent("# Do nothing here...");
+
5868 Indent(-1);
+
5869 WriteLineIndent("end");
+
5870 }
+
5871 if (p->import)
+
5872 {
+
5873 WriteLine();
+
5874 for (const auto& import : p->import->imports)
+
5875 {
+
5876 WriteLineIndent("if !" + CppCommon::StringUtils::ToLower(*import) + "_proxy.nil? && " + CppCommon::StringUtils::ToLower(*import) + "_proxy.on_receive(type, buffer, offset, size)");
+
5877 Indent(1);
+
5878 WriteLineIndent("return true");
+
5879 Indent(-1);
+
5880 WriteLineIndent("end");
+
5881 }
+
5882 }
+
5883 WriteLine();
+
5884 WriteLineIndent("false");
+
5885 Indent(-1);
+
5886 WriteLineIndent("end");
+
5887
+
5888 // Generate proxy end
+
5889 Indent(-1);
+
5890 WriteLineIndent("end");
+
5891}
+
5892
+
5893bool GeneratorRuby::IsPrimitiveType(const std::string& type)
+
5894{
+
5895 return ((type == "bool") || (type == "byte") ||
+
5896 (type == "char") || (type == "wchar") ||
+
5897 (type == "int8") || (type == "uint8") ||
+
5898 (type == "int16") || (type == "uint16") ||
+
5899 (type == "int32") || (type == "uint32") ||
+
5900 (type == "int64") || (type == "uint64") ||
+
5901 (type == "float") || (type == "double"));
+
5902}
+
5903
+
5904bool GeneratorRuby::IsRubyType(const std::string& type)
+
5905{
+
5906 return IsPrimitiveType(type) || (type == "bytes") || (type == "decimal") || (type == "string") || (type == "timestamp") || (type == "uuid");
+
5907}
+
5908
+
5909std::string GeneratorRuby::ConvertTitle(const std::string& type)
+
5910{
+
5911 std::vector<std::string> parts = CppCommon::StringUtils::Split(type, '.', false);
+
5912
+
5913 if (!parts.empty())
+
5914 {
+
5915 std::string result = "";
+
5916 bool first = true;
+
5917 for (const auto& it : parts)
+
5918 {
+
5919 std::string value = CppCommon::StringUtils::ToTrim(it);
+
5920 value[0] = std::toupper(value[0]);
+
5921 result += (first ? "" : "::") + value;
+
5922 first = false;
+
5923 }
+
5924 return result;
+
5925 }
+
5926
+
5927 std::string result = type;
+
5928 result[0] = std::toupper(result[0]);
+
5929 return result;
+
5930}
+
5931
+
5932std::string GeneratorRuby::ConvertEnumSize(const std::string& type)
+
5933{
+
5934 if (type == "byte")
+
5935 return "1";
+
5936 else if (type == "char")
+
5937 return "1";
+
5938 else if (type == "wchar")
+
5939 return "4";
+
5940 else if (type == "int8")
+
5941 return "1";
+
5942 else if (type == "uint8")
+
5943 return "1";
+
5944 else if (type == "int16")
+
5945 return "2";
+
5946 else if (type == "uint16")
+
5947 return "2";
+
5948 else if (type == "int32")
+
5949 return "4";
+
5950 else if (type == "uint32")
+
5951 return "4";
+
5952 else if (type == "int64")
+
5953 return "8";
+
5954 else if (type == "uint64")
+
5955 return "8";
+
5956
+
5957 yyerror("Unsupported enum base type - " + type);
+
5958 return "";
+
5959}
+
5960
+
5961std::string GeneratorRuby::ConvertEnumType(const std::string& type)
+
5962{
+
5963 if (type == "byte")
+
5964 return "byte";
+
5965 else if (type == "char")
+
5966 return "uint8";
+
5967 else if (type == "wchar")
+
5968 return "uint32";
+
5969 else if (type == "int8")
+
5970 return "int8";
+
5971 else if (type == "uint8")
+
5972 return "uint8";
+
5973 else if (type == "int16")
+
5974 return "int16";
+
5975 else if (type == "uint16")
+
5976 return "uint16";
+
5977 else if (type == "int32")
+
5978 return "int32";
+
5979 else if (type == "uint32")
+
5980 return "uint32";
+
5981 else if (type == "int64")
+
5982 return "int64";
+
5983 else if (type == "uint64")
+
5984 return "uint64";
+
5985
+
5986 yyerror("Unsupported enum base type - " + type);
+
5987 return "";
+
5988}
+
5989
+
5990std::string GeneratorRuby::ConvertEnumConstant(const std::string& type, const std::string& value, bool flag)
+
5991{
+
5992 std::string prefix = flag ? "Flags.value(:" : "Enum.value(:";
+
5993
+
5994 if (((type == "char") || (type == "wchar")) && CppCommon::StringUtils::StartsWith(value, "'"))
+
5995 return value + ".ord";
+
5996 else if (type.empty())
+
5997 {
+
5998 // Fill flags values
+
5999 std::vector<std::string> flags = CppCommon::StringUtils::Split(value, '|', true);
+
6000
+
6001 // Generate flags combination
+
6002 if (!flags.empty())
+
6003 {
+
6004 std::string result = "";
+
6005 bool first = true;
+
6006 for (const auto& it : flags)
+
6007 {
+
6008 result += std::string(first ? "" : "|") + prefix + CppCommon::StringUtils::ToTrim(it) + ")";
+
6009 first = false;
+
6010 }
+
6011 return result;
+
6012 }
+
6013
+
6014 return prefix + CppCommon::StringUtils::ToTrim(value) + ")";
+
6015 }
+
6016
+
6017 return value;
+
6018}
+
6019
+
6020std::string GeneratorRuby::ConvertTypeName(const std::string& type, bool optional)
+
6021{
+
6022 return ConvertTitle(type);
+
6023}
+
6024
+
6025std::string GeneratorRuby::ConvertTypeName(const StructField& field)
+
6026{
+
6027 if (field.array)
+
6028 return "Array";
+
6029 else if (field.vector)
+
6030 return "Array";
+
6031 else if (field.list)
+
6032 return "Array";
+
6033 else if (field.set)
+
6034 return "Set";
+
6035 else if (field.map)
+
6036 return "Hash";
+
6037 else if (field.hash)
+
6038 return "Hash";
+
6039
+
6040 return ConvertTypeName(*field.type, field.optional);
+
6041}
+
6042
+
6043std::string GeneratorRuby::ConvertTypeFieldName(const std::string& type, bool final)
+
6044{
+
6045 std::string modelType = final ? "Final" : "Field";
+
6046
+
6047 if (type == "bool")
+
6048 return "FBE::" + modelType + "ModelBool";
+
6049 else if (type == "byte")
+
6050 return "FBE::" + modelType + "ModelByte";
+
6051 else if (type == "bytes")
+
6052 return "FBE::" + modelType + "ModelBytes";
+
6053 else if (type == "char")
+
6054 return "FBE::" + modelType + "ModelChar";
+
6055 else if (type == "wchar")
+
6056 return "FBE::" + modelType + "ModelWChar";
+
6057 else if (type == "int8")
+
6058 return "FBE::" + modelType + "ModelInt8";
+
6059 else if (type == "uint8")
+
6060 return "FBE::" + modelType + "ModelUInt8";
+
6061 else if (type == "int16")
+
6062 return "FBE::" + modelType + "ModelInt16";
+
6063 else if (type == "uint16")
+
6064 return "FBE::" + modelType + "ModelUInt16";
+
6065 else if (type == "int32")
+
6066 return "FBE::" + modelType + "ModelInt32";
+
6067 else if (type == "uint32")
+
6068 return "FBE::" + modelType + "ModelUInt32";
+
6069 else if (type == "int64")
+
6070 return "FBE::" + modelType + "ModelInt64";
+
6071 else if (type == "uint64")
+
6072 return "FBE::" + modelType + "ModelUInt64";
+
6073 else if (type == "float")
+
6074 return "FBE::" + modelType + "ModelFloat";
+
6075 else if (type == "double")
+
6076 return "FBE::" + modelType + "ModelDouble";
+
6077 else if (type == "decimal")
+
6078 return "FBE::" + modelType + "ModelDecimal";
+
6079 else if (type == "timestamp")
+
6080 return "FBE::" + modelType + "ModelTimestamp";
+
6081 else if (type == "string")
+
6082 return "FBE::" + modelType + "ModelString";
+
6083 else if (type == "uuid")
+
6084 return "FBE::" + modelType + "ModelUUID";
+
6085
+
6086 std::string ns = "";
+
6087 std::string t = type;
+
6088
+
6089 size_t pos = type.find_last_of('.');
+
6090 if (pos != std::string::npos)
+
6091 {
+
6092 ns.assign(type, 0, pos + 1);
+
6093 t.assign(type, pos + 1, type.size() - pos);
+
6094 }
+
6095
+
6096 return ConvertTitle(ns) + modelType + "Model" + ConvertTypeName(t, false);
+
6097}
+
6098
+
6099std::string GeneratorRuby::ConvertTypeFieldInitialization(const std::string& type, bool optional, const std::string& offset, bool final)
+
6100{
+
6101 std::string modelType = final ? "Final" : "Field";
+
6102
+
6103 if (optional)
+
6104 return "FBE::" + modelType + "ModelOptional.new(" + ConvertTypeFieldInitialization(type, false, offset, final)+ ", self.buffer, " + offset + ")";
+
6105 else
+
6106 return ConvertTypeFieldName(type, final) + ".new(self.buffer, " + offset + ")";
+
6107}
+
6108
+
6109std::string GeneratorRuby::ConvertTypeFieldInitialization(const StructField& field, const std::string& offset, bool final)
+
6110{
+
6111 std::string modelType = final ? "Final" : "Field";
+
6112
+
6113 if (field.array)
+
6114 return "FBE::" + modelType + "ModelArray.new(" + ConvertTypeFieldInitialization(*field.type, field.optional, offset, final) + ", self.buffer, " + offset + ", " + std::to_string(field.N) + ")";
+
6115 else if (field.vector || field.list)
+
6116 return "FBE::" + modelType + "ModelVector.new(" + ConvertTypeFieldInitialization(*field.type, field.optional, offset, final) + ", self.buffer, " + offset + ")";
+
6117 else if (field.set)
+
6118 return "FBE::" + modelType + "ModelSet.new(" + ConvertTypeFieldInitialization(*field.type, field.optional, offset, final) + ", self.buffer, " + offset + ")";
+
6119 else if (field.map || field.hash)
+
6120 return "FBE::" + modelType + "ModelMap.new(" + ConvertTypeFieldInitialization(*field.key, false, offset, final) + ", " + ConvertTypeFieldInitialization(*field.type, field.optional, offset, final) + ", self.buffer, " + offset + ")";
+
6121 else
+
6122 return ConvertTypeFieldInitialization(*field.type, field.optional, offset, final);
+
6123}
+
6124
+
6125std::string GeneratorRuby::ConvertConstant(const std::string& type, const std::string& value, bool optional)
+
6126{
+
6127 if (value == "true")
+
6128 return "true";
+
6129 else if (value == "false")
+
6130 return "false";
+
6131 else if (value == "null")
+
6132 return "nil";
+
6133 else if (value == "min")
+
6134 {
+
6135 if ((type == "byte") || (type == "uint8") || (type == "uint16") || (type == "uint32") || (type == "uint64"))
+
6136 return "0";
+
6137 else if (type == "int8")
+
6138 return "-128";
+
6139 else if (type == "int16")
+
6140 return "-32768";
+
6141 else if (type == "int32")
+
6142 return "-2147483648";
+
6143 else if (type == "int64")
+
6144 return "-9223372036854775808";
+
6145
+
6146 yyerror("Unsupported type " + type + " for 'min' constant");
+
6147 return "";
+
6148 }
+
6149 else if (value == "max")
+
6150 {
+
6151 if (type == "byte")
+
6152 return "255";
+
6153 else if (type == "int8")
+
6154 return "127";
+
6155 else if (type == "uint8")
+
6156 return "255";
+
6157 else if (type == "int16")
+
6158 return "32767";
+
6159 else if (type == "uint16")
+
6160 return "65535";
+
6161 else if (type == "int32")
+
6162 return "2147483647";
+
6163 else if (type == "uint32")
+
6164 return "4294967295";
+
6165 else if (type == "int64")
+
6166 return "9223372036854775807";
+
6167 else if (type == "uint64")
+
6168 return "18446744073709551615";
+
6169
+
6170 yyerror("Unsupported type " + type + " for 'max' constant");
+
6171 return "";
+
6172 }
+
6173 else if (value == "epoch")
+
6174 return "Time.utc(1970)";
+
6175 else if (value == "utc")
+
6176 return "Time.now.utc";
+
6177 else if (value == "uuid0")
+
6178 return "UUIDTools::UUID.parse_int(0)";
+
6179 else if (value == "uuid1")
+
6180 return "UUIDTools::UUID.timestamp_create";
+
6181 else if (value == "uuid4")
+
6182 return "UUIDTools::UUID.random_create";
+
6183
+
6184 if (type == "bool")
+
6185 return value + " != 0";
+
6186 else if ((type == "char") && !CppCommon::StringUtils::StartsWith(value, "'"))
+
6187 return value + ".chr";
+
6188 else if ((type == "wchar") && !CppCommon::StringUtils::StartsWith(value, "'"))
+
6189 return value + ".chr(Encoding::UTF_8)";
+
6190 else if (type == "decimal")
+
6191 return "BigDecimal('" + value + "')";
+
6192 else if (type == "uuid")
+
6193 return "UUIDTools::UUID.parse(" + value + ")";
+
6194
+
6195 return value;
+
6196}
+
6197
+
6198std::string GeneratorRuby::ConvertDefault(const std::string& type, bool optional)
+
6199{
+
6200 if (optional)
+
6201 return "nil";
+
6202
+
6203 if (type == "bool")
+
6204 return "false";
+
6205 else if (type == "byte")
+
6206 return "0";
+
6207 else if (type == "bytes")
+
6208 return "''";
+
6209 else if ((type == "char") || (type == "wchar"))
+
6210 return "\"\\0\"";
+
6211 else if ((type == "int8") || (type == "uint8") || (type == "int16") || (type == "uint16") || (type == "int32") || (type == "uint32") || (type == "int64") || (type == "uint64"))
+
6212 return "0";
+
6213 else if ((type == "float") || (type == "double"))
+
6214 return "0.0";
+
6215 else if (type == "decimal")
+
6216 return "BigDecimal(0)";
+
6217 else if (type == "timestamp")
+
6218 return "Time.utc(1970)";
+
6219 else if (type == "string")
+
6220 return "''";
+
6221 else if (type == "uuid")
+
6222 return "UUIDTools::UUID.parse_int(0)";
+
6223
+
6224 return ConvertTitle(type) + ".new";
+
6225}
+
6226
+
6227std::string GeneratorRuby::ConvertDefault(const StructField& field)
+
6228{
+
6229 if (field.value)
+
6230 return ConvertConstant(*field.type, *field.value, field.optional);
+
6231
+
6232 if (field.array)
+
6233 return "Array.new(" + std::to_string(field.N) + ", " + ConvertDefault(*field.type, field.optional) + ")";
+
6234 else if (field.vector || field.list || field.set || field.map || field.hash)
+
6235 return ConvertTypeName(field) + ".new";
+
6236
+
6237 return ConvertDefault(*field.type, field.optional);
+
6238}
+
6239
+
6240std::string GeneratorRuby::ConvertValueToJson(const std::string& type, const std::string& value, bool optional)
+
6241{
+
6242 if ((type == "char") || (type == "wchar"))
+
6243 return "(" + value + ".nil? ? nil : " + value + ".ord)";
+
6244 else if (type == "bytes")
+
6245 return "(" + value + ".nil? ? nil : Base64.encode64(" + value + ").chomp!)";
+
6246 else if (type == "decimal")
+
6247 return "(" + value + ".nil? ? nil : " + value + ".to_s('F'))";
+
6248 else if (type == "timestamp")
+
6249 return "(" + value + ".nil? ? nil : (" + value + ".to_i * 1000000000 + " + value + ".nsec))";
+
6250 else if (IsRubyType(type))
+
6251 return "(" + value + ".nil? ? nil : " + value + ")";
+
6252 else
+
6253 return "(" + value + ".nil? ? nil : " + value + ".__to_json_map__)";
+
6254}
+
6255
+
6256std::string GeneratorRuby::ConvertValueFromJson(const std::string& type, const std::string& value, bool optional)
+
6257{
+
6258 if (type == "char")
+
6259 return "(" + value + ".nil? ? nil : " + value + ".chr)";
+
6260 if (type == "wchar")
+
6261 return "(" + value + ".nil? ? nil : " + value + ".chr(Encoding::UTF_8))";
+
6262 else if (type == "bytes")
+
6263 return "(" + value + ".nil? ? nil : Base64.decode64(" + value + "))";
+
6264 else if (type == "decimal")
+
6265 return "(" + value + ".nil? ? nil : BigDecimal(" + value + "))";
+
6266 else if (type == "timestamp")
+
6267 return "(" + value + ".nil? ? nil : Time.at(" + value + " / 1000000000, (" + value + " % 1000000000) / 1000.0).utc)";
+
6268 else if (type == "uuid")
+
6269 return "(" + value + ".nil? ? nil : UUIDTools::UUID.parse(" + value + "))";
+
6270 else if (IsRubyType(type))
+
6271 return "(" + value + ".nil? ? nil : " + value + ")";
+
6272 else
+
6273 return "(" + value + ".nil? ? nil : " + ConvertTitle(type) + ".__from_json_map__(" + value + "))";
+
6274}
+
6275
+
6276std::string GeneratorRuby::ConvertKeyFromJson(const std::string& type, const std::string& value, bool optional)
+
6277{
+
6278 if (type == "byte")
+
6279 return value + ".to_i";
+
6280 else if (type == "bytes")
+
6281 return "Base64.decode64(" + value + ")";
+
6282 if ((type == "int8") || (type == "uint8") || (type == "int16") || (type == "uint16") || (type == "int32") || (type == "uint32") || (type == "int64") || (type == "uint64"))
+
6283 return value + ".to_i";
+
6284 if ((type == "float") || (type == "double"))
+
6285 return value + ".to_f";
+
6286 else if (type == "decimal")
+
6287 return "BigDecimal(" + value + ")";
+
6288 else if (type == "timestamp")
+
6289 return "Time.at(" + value + ".to_i / 1000000000, (" + value + ".to_i % 1000000000) / 1000.0).utc";
+
6290 else if (type == "uuid")
+
6291 return "UUIDTools::UUID.parse(" + value + ")";
+
6292 else
+
6293 return value;
+
6294}
+
6295
+
6296void GeneratorRuby::WriteOutputStreamType(const std::string& type, const std::string& name)
+
6297{
+
6298 if (type == "bool")
+
6299 WriteLineIndent("result << (" + name + " ? 'true' : 'false')");
+
6300 else if (type == "bytes")
+
6301 WriteLineIndent("result << 'bytes[' << " + name + ".length.to_s << ']'");
+
6302 else if ((type == "char") || (type == "wchar"))
+
6303 WriteLineIndent("result << \"'\" << " + name + " << \"'\"");
+
6304 else if (type == "decimal")
+
6305 WriteLineIndent("result << " + name + ".to_s('F')");
+
6306 else if ((type == "string") || (type == "uuid"))
+
6307 WriteLineIndent("result << '\"' << " + name + ".to_s << '\"'");
+
6308 else if (type == "timestamp")
+
6309 WriteLineIndent("result << (" + name + ".to_i * 1000000000 + " + name + ".nsec).to_s");
+
6310 else
+
6311 WriteLineIndent("result << " + name + ".to_s");
+
6312}
+
6313
+
6314void GeneratorRuby::WriteOutputStreamValue(const std::string& type, const std::string& name, bool separate)
+
6315{
+
6316 WriteLineIndent("if !" + name + ".nil?");
+
6317 Indent(1);
+
6318 if (separate)
+
6319 WriteLineIndent("result << (first ? '' : ',')");
+
6320 WriteOutputStreamType(type, name);
+
6321 Indent(-1);
+
6322 WriteLineIndent("else");
+
6323 Indent(1);
+
6324 if (separate)
+
6325 WriteLineIndent("result << (first ? '' : ',')");
+
6326 WriteLineIndent("result << 'null'");
+
6327 Indent(-1);
+
6328 WriteLineIndent("end");
+
6329}
+
6330
+
6331} // namespace FBE
+
void WriteBegin()
Definition generator.inl:24
+
void Store(const CppCommon::Path &filename)
Definition generator.cpp:17
+
static std::string EndLine()
Definition generator.inl:68
+
std::string _input
Definition generator.h:25
+ +
std::string _output
Definition generator.h:26
+
void WriteLineIndent(const std::string &str)
Definition generator.inl:58
+
void Write(const std::string &str)
Definition generator.inl:29
+ +
void Indent(int count)
Definition generator.inl:19
+
void WriteIndent()
Definition generator.inl:34
+
bool Final() const noexcept
+
bool Proto() const noexcept
+
bool JSON() const noexcept
+
void Generate(const std::shared_ptr< Package > &package) override
+
int yyerror(const char *msg)
Definition fbe.l:163
+
Fast binary encoding Ruby generator definition.
+
Definition fbe.h:33
+
const char version[]
Definition version.h:15
+
+ + +
+ + diff --git a/documents/html/generator__ruby_8h.html b/documents/html/generator__ruby_8h.html new file mode 100644 index 000000000..1bf83e899 --- /dev/null +++ b/documents/html/generator__ruby_8h.html @@ -0,0 +1,114 @@ + + + + + + + +FastBinaryEncoding: include/generator_ruby.h File Reference + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+ +
generator_ruby.h File Reference
+
+
+ +

Fast binary encoding Ruby generator definition. +More...

+
#include "generator.h"
+
+

Go to the source code of this file.

+ + + +

+Classes

class  FBE::GeneratorRuby
+ + +

+Namespaces

namespace  FBE
+

Detailed Description

+

Fast binary encoding Ruby generator definition.

+
Author
Ivan Shynkarenka
+
Date
15.10.2018
+ + +

Definition in file generator_ruby.h.

+
+ + +
+ + diff --git a/documents/html/generator__ruby_8h_source.html b/documents/html/generator__ruby_8h_source.html new file mode 100644 index 000000000..d71b3ba42 --- /dev/null +++ b/documents/html/generator__ruby_8h_source.html @@ -0,0 +1,214 @@ + + + + + + + +FastBinaryEncoding: include/generator_ruby.h Source File + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+
generator_ruby.h
+
+
+Go to the documentation of this file.
1
+
8
+
9#ifndef GENERATOR_RUBY_H
+
10#define GENERATOR_RUBY_H
+
11
+
12#include "generator.h"
+
13
+
14namespace FBE {
+
15
+
+ +
17{
+
18public:
+ +
20
+
21 // Final protocol code generation
+
22 bool Final() const noexcept { return _final; }
+
23 GeneratorRuby& Final(bool final) noexcept { _final = final; return *this; }
+
24
+
25 // JSON protocol code generation
+
26 bool JSON() const noexcept { return _json; }
+
27 GeneratorRuby& JSON(bool json) noexcept { _json = json; return *this; }
+
28
+
29 // Sender/Receiver protocol code generation
+
30 bool Proto() const noexcept { return _proto; }
+
31 GeneratorRuby& Proto(bool proto) noexcept { _proto = proto; return *this; }
+
32
+
33 void Generate(const std::shared_ptr<Package>& package) override;
+
34
+
35private:
+
36 bool _final{false};
+
37 bool _json{false};
+
38 bool _proto{false};
+
39
+
40 void GenerateHeader(const std::string& source);
+
41 void GenerateFooter();
+
42 void GenerateImports();
+
43 void GenerateFBE(const CppCommon::Path& path);
+
44 void GenerateFBEEnum();
+
45 void GenerateFBEFlags();
+
46 void GenerateFBEInteger();
+
47 void GenerateFBEWriteBuffer();
+
48 void GenerateFBEReadBuffer();
+
49 void GenerateFBEModel();
+
50 void GenerateFBEFieldModelBase();
+
51 void GenerateFBEFieldModel();
+
52 void GenerateFBEFieldModel(const std::string& name, const std::string& type, const std::string& size, const std::string& defaults);
+
53 void GenerateFBEFieldModelDecimal();
+
54 void GenerateFBEFieldModelBytes();
+
55 void GenerateFBEFieldModelString();
+
56 void GenerateFBEFieldModelOptional();
+
57 void GenerateFBEFieldModelArray();
+
58 void GenerateFBEFieldModelVector();
+
59 void GenerateFBEFieldModelSet();
+
60 void GenerateFBEFieldModelMap();
+
61 void GenerateFBEFinalModel();
+
62 void GenerateFBEFinalModel(const std::string& name, const std::string& type, const std::string& size, const std::string& defaults);
+
63 void GenerateFBEFinalModelDecimal();
+
64 void GenerateFBEFinalModelBytes();
+
65 void GenerateFBEFinalModelString();
+
66 void GenerateFBEFinalModelOptional();
+
67 void GenerateFBEFinalModelArray();
+
68 void GenerateFBEFinalModelVector();
+
69 void GenerateFBEFinalModelSet();
+
70 void GenerateFBEFinalModelMap();
+
71 void GenerateFBESender();
+
72 void GenerateFBEReceiver();
+
73 void GenerateImports(const std::shared_ptr<Package>& p);
+
74
+
75 void GeneratePackage(const std::shared_ptr<Package>& p);
+
76 void GenerateEnum(const std::shared_ptr<EnumType>& e);
+
77 void GenerateEnumFieldModel(const std::shared_ptr<EnumType>& e);
+
78 void GenerateEnumFinalModel(const std::shared_ptr<EnumType>& e);
+
79 void GenerateFlags(const std::shared_ptr<FlagsType>& f);
+
80 void GenerateFlagsFieldModel(const std::shared_ptr<FlagsType>& f);
+
81 void GenerateFlagsFinalModel(const std::shared_ptr<FlagsType>& f);
+
82 void GenerateStruct(const std::shared_ptr<StructType>& s);
+
83 void GenerateStructFieldModel(const std::shared_ptr<StructType>& s);
+
84 void GenerateStructModel(const std::shared_ptr<StructType>& s);
+
85 void GenerateStructFinalModel(const std::shared_ptr<StructType>& s);
+
86 void GenerateStructModelFinal(const std::shared_ptr<StructType>& s);
+
87 void GenerateProtocolVersion(const std::shared_ptr<Package>& p);
+
88 void GenerateSender(const std::shared_ptr<Package>& p, bool final);
+
89 void GenerateReceiver(const std::shared_ptr<Package>& p, bool final);
+
90 void GenerateProxy(const std::shared_ptr<Package>& p, bool final);
+
91
+
92 bool IsPrimitiveType(const std::string& type);
+
93 bool IsRubyType(const std::string& type);
+
94
+
95 std::string ConvertTitle(const std::string& type);
+
96 std::string ConvertEnumSize(const std::string& type);
+
97 std::string ConvertEnumType(const std::string& type);
+
98 std::string ConvertEnumConstant(const std::string& type, const std::string& value, bool flag);
+
99 std::string ConvertTypeName(const std::string& type, bool optional);
+
100 std::string ConvertTypeName(const StructField& field);
+
101 std::string ConvertTypeFieldName(const std::string& type, bool final);
+
102 std::string ConvertTypeFieldInitialization(const std::string& type, bool optional, const std::string& offset, bool final);
+
103 std::string ConvertTypeFieldInitialization(const StructField& field, const std::string& offset, bool final);
+
104 std::string ConvertConstant(const std::string& type, const std::string& value, bool optional);
+
105 std::string ConvertDefault(const std::string& type, bool optional);
+
106 std::string ConvertDefault(const StructField& field);
+
107 std::string ConvertValueToJson(const std::string& type, const std::string& value, bool optional);
+
108 std::string ConvertValueFromJson(const std::string& type, const std::string& value, bool optional);
+
109 std::string ConvertKeyFromJson(const std::string& type, const std::string& value, bool optional);
+
110
+
111 void WriteOutputStreamType(const std::string& type, const std::string& name);
+
112 void WriteOutputStreamValue(const std::string& type, const std::string& name, bool separate);
+
113};
+
+
114
+
115} // namespace FBE
+
116
+
117#endif // GENERATOR_RUBY_H
+
Generator(const std::string &input, const std::string &output, int indent, char space)
Definition generator.inl:11
+ +
GeneratorRuby & Final(bool final) noexcept
+
bool Final() const noexcept
+
GeneratorRuby & JSON(bool json) noexcept
+
bool Proto() const noexcept
+
GeneratorRuby & Proto(bool proto) noexcept
+
Generator(const std::string &input, const std::string &output, int indent, char space)
Definition generator.inl:11
+
bool JSON() const noexcept
+
void Generate(const std::shared_ptr< Package > &package) override
+
Fast binary encoding generator definition.
+
Definition fbe.h:33
+
+ + +
+ + diff --git a/documents/html/generator__swift_8cpp.html b/documents/html/generator__swift_8cpp.html new file mode 100644 index 000000000..e874f29dc --- /dev/null +++ b/documents/html/generator__swift_8cpp.html @@ -0,0 +1,110 @@ + + + + + + + +FastBinaryEncoding: source/generator_swift.cpp File Reference + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+ +
generator_swift.cpp File Reference
+
+
+ +

Fast binary encoding Swift generator implementation. +More...

+
#include "generator_swift.h"
+#include <iostream>
+
+

Go to the source code of this file.

+ + + +

+Namespaces

namespace  FBE
+

Detailed Description

+

Fast binary encoding Swift generator implementation.

+
Author
Andrey Zbranevich \ Based on original Fast binary encoding generator design by \ Ivan Shynkarenka
+
Date
01.08.2019
+ + +

Definition in file generator_swift.cpp.

+
+ + +
+ + diff --git a/documents/html/generator__swift_8cpp_source.html b/documents/html/generator__swift_8cpp_source.html new file mode 100644 index 000000000..86d733e47 --- /dev/null +++ b/documents/html/generator__swift_8cpp_source.html @@ -0,0 +1,8589 @@ + + + + + + + +FastBinaryEncoding: source/generator_swift.cpp Source File + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+
generator_swift.cpp
+
+
+Go to the documentation of this file.
1
+
10
+
11#include "generator_swift.h"
+
12#include <iostream>
+
13
+
14namespace FBE {
+
15
+
+
16void GeneratorSwift::Generate(const std::shared_ptr<Package>& package)
+
17{
+
18 std::string domain = ConvertDomain(package);
+
19
+
20 GenerateFBEPackage(domain, "Fbe");
+
21 GenerateFBEUUIDGenerator(domain, "Fbe");
+
22 GenerateFBEBuffer(domain, "Fbe");
+
23 GenerateFBEModel(domain, "Fbe");
+
24 GenerateFBEFieldModel(domain, "Fbe");
+
25 GenerateFBEFieldModel(domain, "Fbe", "Boolean", "Bool", "", "1", "false");
+
26 GenerateFBEFieldModel(domain, "Fbe", "Byte", "UInt8", "", "1", "0");
+
27 GenerateFBEFieldModel(domain, "Fbe", "Char", "Character", ".utf8.map { UInt8($$0) }[0]", "1", "Character(\"0\")");
+
28 GenerateFBEFieldModel(domain, "Fbe", "WChar", "Character", ".utf16.map { UInt32($$0) }[0]", "4", "Character(\"0\")");
+
29 GenerateFBEFieldModel(domain, "Fbe", "Int8", "Int8", "", "1", "0");
+
30 GenerateFBEFieldModel(domain, "Fbe", "UInt8", "UInt8", "", "1", "0");
+
31 GenerateFBEFieldModel(domain, "Fbe", "Int16", "Int16", "", "2", "0");
+
32 GenerateFBEFieldModel(domain, "Fbe", "UInt16", "UInt16", "", "2", "0");
+
33 GenerateFBEFieldModel(domain, "Fbe", "Int32", "Int32", "", "4", "0");
+
34 GenerateFBEFieldModel(domain, "Fbe", "UInt32", "UInt32", "", "4", "0");
+
35 GenerateFBEFieldModel(domain, "Fbe", "Int64", "Int64", "", "8", "0");
+
36 GenerateFBEFieldModel(domain, "Fbe", "UInt64", "UInt64", "", "8", "0");
+
37 GenerateFBEFieldModel(domain, "Fbe", "Float", "Float", "", "4", "0.0");
+
38 GenerateFBEFieldModel(domain, "Fbe", "Double", "Double", "", "8", "0.0");
+
39 GenerateFBEFieldModel(domain, "Fbe", "UUID", "UUID", "", "16", "UUIDGenerator.nil()");
+
40 GenerateFBEFieldModelDecimal(domain, "Fbe");
+
41 GenerateFBEFieldModelTimestamp(domain, "Fbe");
+
42 GenerateFBEFieldModelBytes(domain, "Fbe");
+
43 GenerateFBEFieldModelString(domain, "Fbe");
+
44 if (Final())
+
45 {
+
46 GenerateFBESize(domain, "Fbe");
+
47 GenerateFBEFinalModel(domain, "Fbe");
+
48 GenerateFBEFinalModel(domain, "Fbe", "Boolean", "Bool", "", "1", "false");
+
49 GenerateFBEFinalModel(domain, "Fbe", "Byte", "UInt8", "", "1", "0");
+
50 GenerateFBEFinalModel(domain, "Fbe", "Char", "Character", ".utf8.map { UInt8($$0) }[0]", "1", "Character(\"0\")");
+
51 GenerateFBEFinalModel(domain, "Fbe", "WChar", "Character", ".utf16.map { UInt32($$0) }[0]", "4", "Character(\"0\")");
+
52 GenerateFBEFinalModel(domain, "Fbe", "Int8", "Int8", "", "1", "0");
+
53 GenerateFBEFinalModel(domain, "Fbe", "UInt8", "UInt8", "", "1", "0");
+
54 GenerateFBEFinalModel(domain, "Fbe", "Int16", "Int16", "", "2", "0");
+
55 GenerateFBEFinalModel(domain, "Fbe", "UInt16", "UInt16", "", "2", "0");
+
56 GenerateFBEFinalModel(domain, "Fbe", "Int32", "Int32", "", "4", "0");
+
57 GenerateFBEFinalModel(domain, "Fbe", "UInt32", "UInt32", "", "4", "0");
+
58 GenerateFBEFinalModel(domain, "Fbe", "Int64", "Int64", "", "8", "0");
+
59 GenerateFBEFinalModel(domain, "Fbe", "UInt64", "UInt64", "", "8", "0");
+
60 GenerateFBEFinalModel(domain, "Fbe", "Float", "Float", "", "4", "0.0");
+
61 GenerateFBEFinalModel(domain, "Fbe", "Double", "Double", "", "8", "0.0");
+
62 GenerateFBEFinalModel(domain, "Fbe", "UUID", "UUID", "", "16", "UUIDGenerator.nil()");
+
63 GenerateFBEFinalModelDecimal(domain, "Fbe");
+
64 GenerateFBEFinalModelTimestamp(domain, "Fbe");
+
65 GenerateFBEFinalModelBytes(domain, "Fbe");
+
66 GenerateFBEFinalModelString(domain, "Fbe");
+
67 }
+
68 if (Proto())
+
69 {
+
70 GenerateFBESender(domain, "Fbe");
+
71 GenerateFBEReceiver(domain, "Fbe");
+
72 GenerateFBEReceiverListener(domain, "Fbe");
+
73 GenerateFBEClient(domain, "Fbe");
+
74 }
+
75
+
76 GeneratePackage(package);
+
77}
+
+
78
+
79void GeneratorSwift::GenerateHeader(const std::string& source)
+
80{
+
81 std::string code = R"CODE(//------------------------------------------------------------------------------
+
82// Automatically generated by the Fast Binary Encoding compiler, do not modify!
+
83// https://github.com/chronoxor/FastBinaryEncoding
+
84// Source: _INPUT_
+
85// FBE version: _VERSION_
+
86//------------------------------------------------------------------------------
+
87
+
88)CODE";
+
89
+
90 // Prepare code template
+
91 code = std::regex_replace(code, std::regex("_INPUT_"), source);
+
92 code = std::regex_replace(code, std::regex("_VERSION_"), version);
+
93 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
94
+
95 Write(code);
+
96}
+
97
+
98void GeneratorSwift::GenerateFooter()
+
99{
+
100}
+
101
+
102void GeneratorSwift::GenerateImports(const std::string& domain, const std::string& package)
+
103{
+
104 if (!package.empty())
+
105 {
+
106 // Generate package name
+
107 WriteLineIndent("import " + domain + package);
+
108 }
+
109}
+
110
+
111void GeneratorSwift::GenerateImports(const std::shared_ptr<Package>& p)
+
112{
+
113 std::string domain = ConvertDomain(p);
+
114
+
115 if (p->import)
+
116 for (const auto& i : p->import->imports)
+
117 GenerateImports(domain, ConvertPackageName(*i));
+
118}
+
119
+
120void GeneratorSwift::GenerateFBEPackage(const std::string& domain, const std::string& package)
+
121{
+
122 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
123
+
124 // Create FBE package path
+
125 CppCommon::Directory::CreateTree(path);
+
126
+
127 CppCommon::Path packagePath = CppCommon::Path(_output) / package;
+
128
+
129 // Create FBE package path
+
130 CppCommon::Directory::CreateTree(packagePath);
+
131
+
132 // Generate the file
+
133 CppCommon::Path file = packagePath / "Package.swift";
+
134 WriteBegin();
+
135
+
136 std::string code = R"CODE(// swift-tools-version:5.1
+
137
+
138import PackageDescription
+
139
+
140let package = Package(
+
141 name: "_DOMAIN_",
+
142 products: [
+
143 // Products define the executables and libraries produced by a package, and make them visible to other packages.
+
144 .library(
+
145 name: "_DOMAIN_",
+
146 targets: ["_DOMAIN_"])
+
147 ],
+
148 dependencies: [
+
149 // Dependencies declare other packages that this package depends on.
+
150 ],
+
151 targets: [
+
152 // Targets are the basic building blocks of a package. A target can define a module or a test suite.
+
153 // Targets can depend on other targets in this package, and on products in packages which this package depends on.
+
154 .target(
+
155 name: "_DOMAIN_",
+
156 dependencies: [])
+
157 ]
+
158)
+
159)CODE";
+
160
+
161 code = std::regex_replace(code, std::regex("_DOMAIN_"), domain + "Fbe");
+
162
+
163 Write(code);
+
164
+
165 // Generate footer
+
166 GenerateFooter();
+
167
+
168 // Store the file
+
169 WriteEnd();
+
170 Store(file);
+
171}
+
172
+
173void GeneratorSwift::GenerateFBEUUIDGenerator(const std::string& domain, const std::string& package)
+
174{
+
175 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
176
+
177 // Generate the file
+
178 CppCommon::Path file = path / "UUIDGenerator.swift";
+
179 WriteBegin();
+
180
+
181 // Generate headers
+
182 GenerateHeader("FBE");
+
183 GenerateImports("", "Foundation");
+
184
+
185 std::string code = R"CODE(
+
186// Fast Binary Encoding UUID generator
+
187public struct UUIDGenerator {
+
188
+
189 // Generate nil UUID0 (all bits set to zero)
+
190 public static func `nil`() -> UUID {
+
191 return UUID(uuid: (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0))
+
192 }
+
193
+
194 // Generate sequential UUID1 (time based version)
+
195 public static func sequential() -> UUID {
+
196 var uuid: uuid_t = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
+
197 withUnsafeMutablePointer(to: &uuid) {
+
198 $0.withMemoryRebound(to: UInt8.self, capacity: 16) {
+
199 uuid_generate_time($0)
+
200 }
+
201 }
+
202
+
203 return UUID(uuid: uuid)
+
204 }
+
205
+
206 // Generate random UUID4 (randomly or pseudo-randomly generated version)
+
207 public static func random() -> UUID {
+
208 var uuid: uuid_t = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
+
209 withUnsafeMutablePointer(to: &uuid) {
+
210 $0.withMemoryRebound(to: UInt8.self, capacity: 16) {
+
211 uuid_generate_random($0)
+
212 }
+
213 }
+
214
+
215 return UUID(uuid: uuid)
+
216 }
+
217}
+
218
+
219extension UUID: Comparable {
+
220 public static func < (lhs: UUID, rhs: UUID) -> Bool {
+
221 return lhs.hashValue < rhs.hashValue
+
222 }
+
223}
+
224)CODE";
+
225
+
226 // Prepare code template
+
227 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
228
+
229 Write(code);
+
230
+
231 // Generate footer
+
232 GenerateFooter();
+
233
+
234 // Store the file
+
235 WriteEnd();
+
236 Store(file);
+
237}
+
238
+
239void GeneratorSwift::GenerateFBEBuffer(const std::string& domain, const std::string& package)
+
240{
+
241 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
242
+
243 // Generate the file
+
244 CppCommon::Path file = path / "Buffer.swift";
+
245 WriteBegin();
+
246
+
247 // Generate headers
+
248 GenerateHeader("FBE");
+
249 GenerateImports("", "Foundation");
+
250
+
251 std::string code = R"CODE(public class Buffer {
+
252
+
253 // Get bytes memory buffer
+
254 public internal(set) var data = Data()
+
255
+
256 // Get bytes memory buffer capacity
+
257 public var capacity: Int {
+
258 return data.count
+
259 }
+
260
+
261 // Is the buffer empty?
+
262 public var empty: Bool {
+
263 return size == 0
+
264 }
+
265
+
266 // Get bytes memory buffer size
+
267 public private(set) var size: Int = 0
+
268 // Get bytes memory buffer offset
+
269 public private(set) var offset: Int = 0
+
270
+
271 // Initialize a new expandable buffer with zero capacity
+
272 public init() {}
+
273 // Initialize a new expandable buffer with the given capacity
+
274 public init(capacity: Int) { attach(capacity: capacity) }
+
275 // Initialize a new buffer based on the specified byte array
+
276 public init(buffer: Data) { attach(buffer: buffer) }
+
277 // Initialize a new buffer based on the specified region (offset) of a byte array
+
278 public init(buffer: Data, offset: Int) { attach(buffer: buffer, offset: offset) }
+
279 // Initialize a new buffer based on the specified region (size and offset) of a byte array
+
280 public init(buffer: Data, size: Int, offset: Int) { attach(buffer: buffer, size: size, offset: offset) }
+
281
+
282 public func attach() {
+
283 data = Data(capacity: 0)
+
284 size = 0
+
285 offset = 0
+
286 }
+
287
+
288 // Attach memory buffer methods
+
289 public func attach(capacity: Int) {
+
290 data = Data(capacity: capacity)
+
291 size = 0
+
292 offset = 0
+
293 }
+
294
+
295 public func attach(buffer: Data) {
+
296 data = buffer
+
297 size = buffer.count
+
298 offset = 0
+
299 }
+
300
+
301 public func attach(buffer: Data, offset: Int) {
+
302 data = buffer
+
303 size = buffer.count
+
304 self.offset = offset
+
305 }
+
306
+
307 public func attach(buffer: Data, size: Int, offset: Int) {
+
308 data = buffer
+
309 self.size = size
+
310 self.offset = offset
+
311 }
+
312
+
313 // Allocate memory in the current buffer and return offset to the allocated memory block
+
314 public func allocate(size: Int) throws -> Int {
+
315
+
316 if size < 0 {
+
317 throw NSException(name: .invalidArgumentException, reason: "Invalid allocation size!") as! Error
+
318 }
+
319
+
320 let offset = self.size
+
321
+
322 // Calculate a new buffer size
+
323 let total = Int(self.size + size)
+
324
+
325 if total <= data.count {
+
326 self.size = total
+
327 return offset
+
328 }
+
329
+
330 var data = Data(count: max(total, 2 * self.size))
+
331 data.withUnsafeMutableBytes { (body: UnsafeMutableRawBufferPointer) in
+
332 if let baseAddress = body.baseAddress, body.count > 0 {
+
333 let pointer = baseAddress.assumingMemoryBound(to: UInt8.self)
+
334 self.data.copyBytes(to: pointer, count: self.data.count)
+
335 }
+
336 }
+
337 self.data = data
+
338 self.size += size
+
339
+
340 return offset
+
341 }
+
342
+
343 // Remove some memory of the given size from the current buffer
+
344 public func remove(offset: Int, size: Int) throws {
+
345 if offset + size > self.size {
+
346 throw NSException(name: .invalidArgumentException, reason: "Invalid offset & size!") as! Error
+
347 }
+
348 if size != 0 {
+
349 if self.size - size - offset != 0 {
+
350 data[offset...] = data[(offset + size)..<self.size]
+
351 } else {
+
352 data = data[0..<offset]
+
353 }
+
354 }
+
355 self.size -= size
+
356 if self.offset >= offset + size {
+
357 self.offset -= size
+
358 } else if self.offset >= offset {
+
359 self.offset -= self.offset - offset
+
360 if self.offset > self.size {
+
361 self.offset = self.size
+
362 }
+
363 }
+
364 }
+
365
+
366 // Reserve memory of the given capacity in the current buffer
+
367 public func reserve(capacity: Int) throws {
+
368 if capacity < 0 {
+
369 throw NSException(name: .invalidArgumentException, reason: "Invalid reserve capacity!") as! Error
+
370 }
+
371
+
372 if capacity > data.count {
+
373 var data = Data(capacity: max(capacity, 2 * self.data.count))
+
374 data[0...] = self.data[0...]
+
375 self.data = data
+
376 }
+
377 }
+
378
+
379 // Resize the current buffer
+
380 public func resize(size: Int) throws {
+
381 try reserve(capacity: size)
+
382
+
383 self.size = size
+
384
+
385 if offset > self.size {
+
386 offset = self.size
+
387 }
+
388 }
+
389
+
390 // Reset the current buffer and its offset
+
391 public func reset() {
+
392 size = 0
+
393 offset = 0
+
394 }
+
395
+
396 // Shift the current buffer offset
+
397 public func shift(offset: Int) { self.offset += offset }
+
398 // Unshift the current buffer offset
+
399 public func unshift(offset: Int) { self.offset -= offset }
+
400
+
401 func withDataMutablePointer(offset: Int = 0, block: (UnsafeMutablePointer<UInt8>) -> Void) {
+
402 self.data.withUnsafeMutableBytes { (body: UnsafeMutableRawBufferPointer) in
+
403 if let baseAddress = body.baseAddress, body.count > 0 {
+
404 block(baseAddress.assumingMemoryBound(to: UInt8.self).advanced(by: offset))
+
405 } else {
+
406 assertionFailure()
+
407 }
+
408 }
+
409 }
+
410
+
411 func withUnsafeBytes(block: (UnsafeRawPointer) -> Void) {
+
412 self.data.withUnsafeBytes { body in
+
413 if let baseAddress = body.baseAddress, body.count > 0 {
+
414 block(baseAddress)
+
415 } else {
+
416 assertionFailure()
+
417 }
+
418 }
+
419 }
+
420
+
421 private func decodeByteNumber<T>(value: inout T, offset: Int, count: Int) {
+
422 withUnsafeMutableBytes(of: &value) { dest -> Void in
+
423 withUnsafeBytes { p in
+
424 let src = p.advanced(by: offset)
+
425 dest.copyMemory(from: UnsafeRawBufferPointer(start: src, count: count))
+
426 }
+
427 }
+
428 }
+
429}
+
430)CODE";
+
431
+
432 Write(code);
+
433
+
434 code = R"CODE(// MARK: Buffer I/O methods
+
435public extension Buffer {
+
436 class func readBoolean(buffer: Data, offset: Int) -> Bool {
+
437 let index = offset
+
438 return buffer[index] != 0
+
439 }
+
440
+
441 class func readByte(buffer: Data, offset: Int) -> UInt8 {
+
442 let index = offset
+
443 return buffer[index]
+
444 }
+
445
+
446 class func readChar(buffer: Data, offset: Int) -> Character {
+
447 return Character(UnicodeScalar(Buffer.readUInt8(buffer: buffer, offset: offset)))
+
448 }
+
449
+
450 class func readWChar(buffer: Buffer, offset: Int) -> Character {
+
451 return Character(UnicodeScalar(Buffer.readUInt32(buffer: buffer, offset: offset))!)
+
452 }
+
453
+
454 class func readInt8(buffer: Buffer, offset: Int) -> Int8 {
+
455 var i: Int8 = 0
+
456 buffer.decodeByteNumber(value: &i, offset: offset, count: 1)
+
457 return Int8(littleEndian: i)
+
458 }
+
459
+
460 class func readUInt8(buffer: Data, offset: Int) -> UInt8 {
+
461 let index = offset
+
462 return buffer[index]
+
463 }
+
464
+
465 class func readInt16(buffer: Buffer, offset: Int) -> Int16 {
+
466 var i: Int16 = 0
+
467 buffer.decodeByteNumber(value: &i, offset: offset, count: 2)
+
468 return Int16(littleEndian: i)
+
469 }
+
470
+
471 class func readUInt16(buffer: Buffer, offset: Int) -> UInt16 {
+
472 var i: UInt16 = 0
+
473 buffer.decodeByteNumber(value: &i, offset: offset, count: 2)
+
474 return UInt16(littleEndian: i)
+
475 }
+
476
+
477 class func readInt32(buffer: Buffer, offset: Int) -> Int32 {
+
478 var i: Int32 = 0
+
479 buffer.decodeByteNumber(value: &i, offset: offset, count: 4)
+
480 return Int32(littleEndian: i)
+
481 }
+
482
+
483 class func readUInt32(buffer: Buffer, offset: Int) -> UInt32 {
+
484 var i: UInt32 = 0
+
485 buffer.decodeByteNumber(value: &i, offset: offset, count: 4)
+
486 return UInt32(littleEndian: i)
+
487 }
+
488
+
489 class func readInt64(buffer: Buffer, offset: Int) -> Int64 {
+
490 var i: Int64 = 0
+
491 buffer.decodeByteNumber(value: &i, offset: offset, count: 8)
+
492 return Int64(littleEndian: i)
+
493 }
+
494
+
495 class func readUInt64(buffer: Buffer, offset: Int) -> UInt64 {
+
496 var i: UInt64 = 0
+
497 buffer.decodeByteNumber(value: &i, offset: offset, count: 8)
+
498 return UInt64(littleEndian: i)
+
499 }
+
500
+
501 class func readFloat(buffer: Buffer, offset: Int) -> Float {
+
502 let bits = readUInt32(buffer: buffer, offset: offset)
+
503 return Float(bitPattern: bits)
+
504 }
+
505
+
506 class func readDouble(buffer: Buffer, offset: Int) -> Double {
+
507 let bitPattern = readUInt64(buffer: buffer, offset: offset)
+
508 return Double(bitPattern: bitPattern)
+
509 }
+
510
+
511 class func readBytes(buffer: Data, offset: Int, size: Int) -> Data {
+
512 var result = Data(capacity: size)
+
513 result[0...] = buffer[offset..<(offset + size)]
+
514 return result
+
515 }
+
516
+
517 class func readString(buffer: Buffer, offset: Int, size: Int) -> String {
+
518 var value = ""
+
519
+
520 buffer.withUnsafeBytes { p in
+
521 let src = p.advanced(by: offset).assumingMemoryBound(to: UInt8.self)
+
522 value = utf8ToString(bytes: src, count: size)
+
523 }
+
524 return value
+
525 }
+
526
+
527 class func utf8ToString(bytes: UnsafePointer<UInt8>, count: Int) -> String {
+
528 if count == 0 {
+
529 return String()
+
530 }
+
531 let codeUnits = UnsafeBufferPointer<UInt8>(start: bytes, count: count)
+
532 let sourceEncoding = Unicode.UTF8.self
+
533
+
534 // Verify that the UTF-8 is valid.
+
535 var p = sourceEncoding.ForwardParser()
+
536 var i = codeUnits.makeIterator()
+
537 Loop:
+
538 while true {
+
539 switch p.parseScalar(from: &i) {
+
540 case .valid(_):
+
541 break
+
542 case .error:
+
543 return ""
+
544 case .emptyInput:
+
545 break Loop
+
546 }
+
547 }
+
548
+
549 // This initializer is fast but does not reject broken
+
550 // UTF-8 (which is why we validate the UTF-8 above).
+
551 return String(decoding: codeUnits, as: sourceEncoding)
+
552 }
+
553
+
554 class func readUUID(buffer: Data, offset: Int) -> UUID {
+
555 let bytes = readBytes(buffer: buffer, offset: offset, size: 16)
+
556 let uuid: uuid_t = (
+
557 bytes[15],
+
558 bytes[14],
+
559 bytes[13],
+
560 bytes[12],
+
561 bytes[11],
+
562 bytes[10],
+
563 bytes[9],
+
564 bytes[8],
+
565 bytes[7],
+
566 bytes[6],
+
567 bytes[5],
+
568 bytes[4],
+
569 bytes[3],
+
570 bytes[2],
+
571 bytes[1],
+
572 bytes[0]
+
573 )
+
574
+
575 return UUID(uuid: uuid)
+
576 }
+
577
+
578 class func write(buffer: inout Buffer, offset: Int, value: Bool) {
+
579 buffer.data[offset] = value ? 1 : 0
+
580 }
+
581
+
582 class func write(buffer: inout Buffer, offset: Int, value: Int8) {
+
583 buffer.withDataMutablePointer(offset: offset) {
+
584 var v = value.littleEndian
+
585 let n = MemoryLayout<UInt8>.size
+
586 memcpy($0, &v, n)
+
587 }
+
588 }
+
589
+
590 class func write(buffer: inout Buffer, offset: Int, value: UInt8) {
+
591 buffer.withDataMutablePointer(offset: offset) {
+
592 var v = value.littleEndian
+
593 let n = MemoryLayout<UInt8>.size
+
594 memcpy($0, &v, n)
+
595 }
+
596 }
+
597
+
598 class func write(buffer: inout Buffer, offset: Int, value: Int16) {
+
599 buffer.withDataMutablePointer(offset: offset) {
+
600 var v = value.littleEndian
+
601 let n = MemoryLayout<Int16>.size
+
602 memcpy($0, &v, n)
+
603 }
+
604 }
+
605
+
606 class func write(buffer: inout Buffer, offset: Int, value: UInt16) {
+
607 buffer.withDataMutablePointer(offset: offset) {
+
608 var v = value.littleEndian
+
609 let n = MemoryLayout<UInt16>.size
+
610 memcpy($0, &v, n)
+
611 }
+
612 }
+
613
+
614 class func write(buffer: inout Buffer, offset: Int, value: Int32) {
+
615 buffer.withDataMutablePointer(offset: offset) {
+
616 var v = value.littleEndian
+
617 let n = MemoryLayout<Int32>.size
+
618 memcpy($0, &v, n)
+
619 }
+
620 }
+
621
+
622 class func write(buffer: inout Buffer, offset: Int, value: UInt32) {
+
623 buffer.withDataMutablePointer(offset: offset) {
+
624 var v = value.littleEndian
+
625 let n = MemoryLayout<UInt32>.size
+
626 memcpy($0, &v, n)
+
627 }
+
628 }
+
629
+
630 class func write(buffer: inout Buffer, offset: Int, value: Int64) {
+
631 buffer.withDataMutablePointer(offset: offset) {
+
632 var v = value.littleEndian
+
633 let n = MemoryLayout<Int64>.size
+
634 memcpy($0, &v, n)
+
635 }
+
636 }
+
637
+
638 class func write(buffer: inout Buffer, offset: Int, value: UInt64) {
+
639 buffer.withDataMutablePointer(offset: offset) {
+
640 var v = value.littleEndian
+
641 let n = MemoryLayout<UInt64>.size
+
642 memcpy($0, &v, n)
+
643 }
+
644 }
+
645
+
646 class func write(buffer: inout Buffer, offset: Int, value: String) {
+
647 buffer.withDataMutablePointer(offset: offset) {
+
648 var pointer = $0
+
649 var v = UInt32(value.count).littleEndian
+
650 let n = MemoryLayout<UInt32>.size
+
651 memcpy(pointer, &v, n)
+
652 pointer = pointer.advanced(by: n)
+
653
+
654 for b in value.utf8 {
+
655 pointer.pointee = b
+
656 pointer = pointer.successor()
+
657 }
+
658 }
+
659 }
+
660
+
661 class func write(buffer: inout Buffer, offset: Int, value: Float) {
+
662 let bits = value.bitPattern
+
663 Buffer.write(buffer: &buffer, offset: offset, value: bits)
+
664 }
+
665
+
666 class func write(buffer: inout Buffer, offset: Int, value: Double) {
+
667 let bits = value.bitPattern
+
668 Buffer.write(buffer: &buffer, offset: offset, value: bits)
+
669 }
+
670
+
671 class func write(buffer: inout Data, offset: Int, value: Data) {
+
672 if value.isEmpty {
+
673 return
+
674 }
+
675 buffer[offset...(offset + value.count - 1)] = value[0...value.count - 1]
+
676 }
+
677
+
678 class func write(buffer: inout Buffer, offset: Int, value: Data, valueOffset: Int, valueSize: Int) {
+
679 if valueSize == 0 {
+
680 return
+
681 }
+
682
+
683 let values = Array(value[valueOffset..<(valueOffset + valueSize)])
+
684 for i in 0..<values.count {
+
685 Buffer.write(buffer: &buffer, offset: offset + i, value: values[i])
+
686 }
+
687 }
+
688
+
689 class func write(buffer: inout Buffer, offset: Int, value: UInt8, valueCount: Int) {
+
690 buffer.withDataMutablePointer(offset: offset) {
+
691 var pointer = $0
+
692
+
693 var v = value.littleEndian
+
694 let n = MemoryLayout<UInt8>.size
+
695
+
696 for _ in 0..<valueCount {
+
697
+
698 memcpy(pointer, &v, n)
+
699 pointer = pointer.successor()
+
700 }
+
701 }
+
702 }
+
703
+
704 class func write(buffer: inout Data, offset: Int, value: UUID) {
+
705 Buffer.write(buffer: &buffer, offset: offset, value: Data(Swift.withUnsafeBytes(of: value.uuid, { Data($0) }).reversed()))
+
706 }
+
707}
+
708)CODE";
+
709
+
710 // Prepare code template
+
711 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
712
+
713 Write(code);
+
714
+
715 // Generate footer
+
716 GenerateFooter();
+
717
+
718 // Store the file
+
719 WriteEnd();
+
720 Store(file);
+
721}
+
722
+
723void GeneratorSwift::GenerateFBEModel(const std::string& domain, const std::string& package)
+
724{
+
725 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
726
+
727 // Generate the file
+
728 CppCommon::Path file = path / "Model.swift";
+
729 WriteBegin();
+
730
+
731 // Generate headers
+
732 GenerateHeader("FBE");
+
733 GenerateImports("", "Foundation");
+
734
+
735 std::string code = R"CODE(
+
736// Fast Binary Encoding base model
+
737open class Model {
+
738
+
739 // Get bytes buffer
+
740 public private(set) var buffer: Buffer
+
741
+
742 // Initialize a new model
+
743 public init(buffer: Buffer = Buffer()) {
+
744 self.buffer = buffer
+
745 }
+
746
+
747 // Attach memory buffer methods
+
748 public func attach() { buffer.attach() }
+
749 public func attach(capacity: Int) { buffer.attach(capacity: capacity) }
+
750 public func attach(buffer: Data) { self.buffer.attach(buffer: buffer) }
+
751 public func attach(buffer: Data, offset: Int) { self.buffer.attach(buffer: buffer, offset: offset) }
+
752 public func attach(buffer: Data, size: Int, offset: Int) { self.buffer.attach(buffer: buffer, size: size, offset: offset) }
+
753 public func attach(buffer: Buffer) { self.buffer.attach(buffer: buffer.data, size: buffer.size, offset: buffer.offset) }
+
754 public func attach(buxffer: Buffer, offset: Int) { self.buffer.attach(buffer: buffer.data, size: buffer.size, offset: offset) }
+
755
+
756 // Model buffer operations
+
757 public func allocate(size: Int) throws -> Int { return try buffer.allocate(size: size) }
+
758 public func remove(offset: Int, size: Int) throws { try buffer.remove(offset: offset, size: size) }
+
759 public func reserve(capacity: Int) throws { try buffer.reserve(capacity: capacity) }
+
760 public func resize(size: Int) throws { try buffer.resize(size: size) }
+
761 public func reset() { buffer.reset() }
+
762 public func shift(offset: Int) { buffer.shift(offset: offset) }
+
763 public func unshift(offset: Int) { buffer.unshift(offset: offset) }
+
764
+
765 // Buffer I/O methods
+
766 public func readUInt32(offset: Int) -> UInt { return UInt(Buffer.readUInt32(buffer: buffer, offset: buffer.offset + offset)) }
+
767 public func write(offset: Int, value: UInt32) { Buffer.write(buffer: &buffer, offset: buffer.offset + offset, value: value) }
+
768}
+
769)CODE";
+
770
+
771 // Prepare code template
+
772 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
773
+
774 Write(code);
+
775
+
776 // Generate footer
+
777 GenerateFooter();
+
778
+
779 // Store the file
+
780 WriteEnd();
+
781 Store(file);
+
782}
+
783
+
784void GeneratorSwift::GenerateFBEFieldModel(const std::string& domain, const std::string& package)
+
785{
+
786 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
787
+
788 // Generate the file
+
789 CppCommon::Path file = path / "FieldModel.swift";
+
790 WriteBegin();
+
791
+
792 // Generate headers
+
793 GenerateHeader("FBE");
+
794 GenerateImports("", "Foundation");
+
795
+
796 std::string code = R"CODE(
+
797// Fast Binary Encoding base field model
+
798public protocol FieldModel: class {
+
799 var _buffer: Buffer { get set }
+
800 var _offset: Int { get set }
+
801
+
802 init()
+
803 init(buffer: Buffer, offset: Int)
+
804
+
805 var fbeSize: Int { get }
+
806 var fbeExtra: Int { get }
+
807}
+
808
+
809public extension FieldModel {
+
810
+
811 init(buffer: Buffer, offset: Int) {
+
812 self.init()
+
813
+
814 _buffer = buffer
+
815 _offset = offset
+
816 }
+
817
+
818 // Field offset
+
819 var fbeOffset: Int {
+
820 get {
+
821 return _offset
+
822 }
+
823 set {
+
824 _offset = newValue
+
825 }
+
826 }
+
827
+
828 // Field size
+
829 var fbeSize: Int {
+
830 return 0
+
831 }
+
832
+
833 // Field extra size
+
834 var fbeExtra: Int {
+
835 return 0
+
836 }
+
837
+
838 // Shift the current field offset
+
839 func fbeShift(size: Int) { _offset += size }
+
840 // Unshift the current field offset
+
841 func fbeUnshift(size: Int) { _offset -= size }
+
842
+
843 // Check if the value is valid
+
844 func verify() -> Bool {
+
845 return true
+
846 }
+
847
+
848 // Buffer I/O methods
+
849 func readBoolean(offset: Int) -> Bool { return Buffer.readBoolean(buffer: _buffer.data, offset: _buffer.offset + offset) }
+
850 func readByte(offset: Int) -> Data.Element { return Buffer.readByte(buffer: _buffer.data, offset: _buffer.offset + offset) }
+
851 func readChar(offset: Int) -> Character { return Buffer.readChar(buffer: _buffer.data, offset: _buffer.offset + offset) }
+
852 func readWChar(offset: Int) -> Character { return Buffer.readWChar(buffer: _buffer, offset: _buffer.offset + offset) }
+
853 func readInt8(offset: Int) -> Int8 { return Buffer.readInt8(buffer: _buffer, offset: _buffer.offset + offset) }
+
854 func readUInt8(offset: Int) -> UInt8 { return Buffer.readUInt8(buffer: _buffer.data, offset: _buffer.offset + offset) }
+
855 func readInt16(offset: Int) -> Int16 { return Buffer.readInt16(buffer: _buffer, offset: _buffer.offset + offset) }
+
856 func readUInt16(offset: Int) -> UInt16 { return Buffer.readUInt16(buffer: _buffer, offset: _buffer.offset + offset) }
+
857 func readInt32(offset: Int) -> Int32 { return Buffer.readInt32(buffer: _buffer, offset: _buffer.offset + offset) }
+
858 func readUInt32(offset: Int) -> UInt32 { return Buffer.readUInt32(buffer: _buffer, offset: _buffer.offset + offset) }
+
859 func readInt64(offset: Int) -> Int64 { return Buffer.readInt64(buffer: _buffer, offset: _buffer.offset + offset) }
+
860 func readUInt64(offset: Int) -> UInt64 { return Buffer.readUInt64(buffer: _buffer, offset: _buffer.offset + offset) }
+
861 func readFloat(offset: Int) -> Float { return Buffer.readFloat(buffer: _buffer, offset: _buffer.offset + offset) }
+
862 func readDouble(offset: Int) -> Double { return Buffer.readDouble(buffer: _buffer, offset: _buffer.offset + offset) }
+
863 func readBytes(offset: Int, size: Int) -> Data { return Buffer.readBytes(buffer: _buffer.data, offset: _buffer.offset + offset, size: size) }
+
864 func readString(offset: Int, size: Int) -> String { return Buffer.readString(buffer: _buffer, offset: _buffer.offset + offset, size: size) }
+
865 func readUUID(offset: Int) -> UUID { return Buffer.readUUID(buffer: _buffer.data, offset: _buffer.offset + offset) }
+
866 func write(offset: Int, value: Bool) { Buffer.write(buffer: &_buffer, offset: _buffer.offset + offset, value: value) }
+
867 func write(offset: Int, value: Int8) { Buffer.write(buffer: &_buffer, offset: _buffer.offset + offset, value: value) }
+
868 func write(offset: Int, value: UInt8) { Buffer.write(buffer: &_buffer, offset: _buffer.offset + offset, value: value) }
+
869 func write(offset: Int, value: Int16) { Buffer.write(buffer: &_buffer, offset: _buffer.offset + offset, value: value) }
+
870 func write(offset: Int, value: UInt16) { Buffer.write(buffer: &_buffer, offset: _buffer.offset + offset, value: value) }
+
871 func write(offset: Int, value: Int32) { Buffer.write(buffer: &_buffer, offset: _buffer.offset + offset, value: value) }
+
872 func write(offset: Int, value: UInt32) { Buffer.write(buffer: &_buffer, offset: _buffer.offset + offset, value: value) }
+
873 func write(offset: Int, value: Int64) { Buffer.write(buffer: &_buffer, offset: _buffer.offset + offset, value: value) }
+
874 func write(offset: Int, value: UInt64) { Buffer.write(buffer: &_buffer, offset: _buffer.offset + offset, value: value) }
+
875 func write(offset: Int, value: String) { Buffer.write(buffer: &_buffer, offset: _buffer.offset + offset, value: value) }
+
876 func write(offset: Int, value: Float) { Buffer.write(buffer: &_buffer, offset: _buffer.offset + offset, value: value) }
+
877 func write(offset: Int, value: Double) { Buffer.write(buffer: &_buffer, offset: _buffer.offset + offset, value: value) }
+
878 func write(offset: Int, value: Data) { Buffer.write(buffer: &_buffer.data, offset: _buffer.offset + offset, value: value) }
+
879 func write(offset: Int, value: Data, valueOffset: Int, valueSize: Int) { Buffer.write(buffer: &_buffer, offset: _buffer.offset + offset, value: value, valueOffset: valueOffset, valueSize: valueSize) }
+
880 func write(offset: Int, value: Data.Element, valueCount: Int) { Buffer.write(buffer: &_buffer, offset: _buffer.offset + offset, value: value, valueCount: valueCount) }
+
881 func write(offset: Int, value: UUID) { Buffer.write(buffer: &_buffer.data, offset: _buffer.offset + offset, value: value) }
+
882}
+
883)CODE";
+
884
+
885 // Prepare code template
+
886 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
887
+
888 Write(code);
+
889
+
890 // Generate footer
+
891 GenerateFooter();
+
892
+
893 // Store the file
+
894 WriteEnd();
+
895 Store(file);
+
896}
+
897
+
898void GeneratorSwift::GenerateFBEFieldModel(const std::string& domain, const std::string& package, const std::string& name, const std::string& type, const std::string& base, const std::string& size, const std::string& defaults)
+
899{
+
900 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
901
+
902 // Generate the file
+
903 CppCommon::Path file = path / ("FieldModel" + name + ".swift");
+
904 WriteBegin();
+
905
+
906 // Generate headers
+
907 GenerateHeader("FBE");
+
908 GenerateImports("", "Foundation");
+
909
+
910 std::string code = R"CODE(
+
911// Fast Binary Encoding _TYPE_ field model
+
912public class FieldModel_NAME_: FieldModel {
+
913 public var _buffer = Buffer()
+
914 public var _offset: Int = 0
+
915
+
916 // Field size
+
917 public let fbeSize: Int = _SIZE_
+
918
+
919 public required init() {
+
920 _buffer = Buffer()
+
921 _offset = 0
+
922 }
+
923
+
924 public required init(buffer: Buffer, offset: Int) {
+
925 _buffer = buffer
+
926 _offset = offset
+
927 }
+
928
+
929 // Get the value
+
930 public func get(defaults: _TYPE_ = _DEFAULTS_) -> _TYPE_ {
+
931 if (_buffer.offset + fbeOffset + fbeSize) > _buffer.size {
+
932 return defaults
+
933 }
+
934
+
935 return read_NAME_(offset: fbeOffset)
+
936 }
+
937
+
938 // Set the value
+
939 public func set(value: _TYPE_) throws {
+
940 if (_buffer.offset + fbeOffset + fbeSize) > _buffer.size {
+
941 assertionFailure("Model is broken!")
+
942 return
+
943 }
+
944
+
945 write(offset: fbeOffset, value: value_BASE_)
+
946 }
+
947}
+
948)CODE";
+
949
+
950 // Prepare code template
+
951 code = std::regex_replace(code, std::regex("_NAME_"), name);
+
952 code = std::regex_replace(code, std::regex("_TYPE_"), type);
+
953 code = std::regex_replace(code, std::regex("_SIZE_"), size);
+
954 code = std::regex_replace(code, std::regex("_DEFAULTS_"), defaults);
+
955 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
956 code = std::regex_replace(code, std::regex("_BASE_"), base);
+
957
+
958 Write(code);
+
959
+
960 // Generate footer
+
961 GenerateFooter();
+
962
+
963 // Store the file
+
964 WriteEnd();
+
965 Store(file);
+
966}
+
967
+
968void GeneratorSwift::GenerateFBEFieldModelDecimal(const std::string& domain, const std::string& package)
+
969{
+
970 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
971
+
972 // Generate the file
+
973 CppCommon::Path file = path / "FieldModelDecimal.swift";
+
974 WriteBegin();
+
975
+
976 // Generate headers
+
977 GenerateHeader("FBE");
+
978 GenerateImports("", "Foundation");
+
979
+
980 std::string code = R"CODE(
+
981// Fast Binary Encoding decimal field model
+
982public class FieldModelDecimal: FieldModel {
+
983 public var _buffer = Buffer()
+
984 public var _offset: Int = 0
+
985
+
986 // Field size
+
987 public let fbeSize: Int = 16
+
988
+
989 public required init() {
+
990 _buffer = Buffer()
+
991 _offset = 0
+
992 }
+
993
+
994 // Get the value
+
995 public func get(defaults: Decimal = Decimal.zero) -> Decimal {
+
996 if (_buffer.offset + fbeOffset + fbeSize) > _buffer.size {
+
997 return defaults
+
998 }
+
999
+
1000 let lowScaleField = Decimal(string: "18446744073709551616")!
+
1001 let midScaleField = Decimal(string: "4294967296")!
+
1002
+
1003 let flags = readUInt32(offset: fbeOffset + 12)
+
1004 let negative = (flags & 0x80000000) != 0
+
1005 let scale = -Int((flags & 0x7FFFFFFF) >> 16)
+
1006 let sign: FloatingPointSign = negative ? .minus : .plus
+
1007
+
1008 var result = Decimal(readUInt32(offset: fbeOffset + 8)) * lowScaleField
+
1009 result += Decimal(readUInt32(offset: fbeOffset + 4)) * midScaleField
+
1010 result += Decimal(readUInt32(offset: fbeOffset + 0))
+
1011 result = Decimal(sign: sign, exponent: scale, significand: result)
+
1012
+
1013 if result.exponent != scale {
+
1014 var zero = Decimal(sign: sign, exponent: scale, significand: .zero)
+
1015 NSDecimalNormalize(&result, &zero, .up)
+
1016 }
+
1017
+
1018 return result
+
1019 }
+
1020
+
1021 // Set the value
+
1022 public func set(value: Decimal) throws {
+
1023 if (_buffer.offset + fbeOffset + fbeSize) > _buffer.size {
+
1024 assertionFailure("Model is broken!")
+
1025 return
+
1026 }
+
1027
+
1028 var valueRef = value
+
1029 if valueRef.exponent > 0 {
+
1030 // Try to normalize decimal number for .NET Decimal format
+
1031 var zero = Decimal.zero
+
1032 let error = NSDecimalNormalize(&valueRef, &zero, .up)
+
1033 if error != .noError {
+
1034 // Issue during normalize decimal number
+
1035 write(offset: fbeOffset, value: UInt8.zero, valueCount: fbeSize)
+
1036 return
+
1037 }
+
1038 }
+
1039
+
1040 // Get scale
+
1041 let scale = UInt8(abs(valueRef.exponent))
+
1042 if scale < 0 || scale > 28 {
+
1043 // Value scale exceeds .NET Decimal limit of [0, 28]
+
1044 write(offset: fbeOffset, value: UInt8.zero, valueCount: fbeSize)
+
1045 return
+
1046 }
+
1047
+
1048 // Get byte array
+
1049 let unscaledBytes = withUnsafeBytes(of: valueRef) {
+
1050 Array($0)
+
1051 }
+
1052
+
1053 // Write unscaled value to bytes 0-11
+
1054 var index = 0
+
1055 let straterIndex = unscaledBytes.count - min(unscaledBytes.count, 16)
+
1056 let bytes = Array(unscaledBytes[straterIndex..<min(unscaledBytes.count, 16)])
+
1057 while index < 12 {
+
1058 write(offset: fbeOffset + index, value: bytes[index])
+
1059 index += 1
+
1060 }
+
1061
+
1062 // Fill remaining bytes with zeros
+
1063 while index < 14 {
+
1064 write(offset: fbeOffset + index, value: Int8.zero)
+
1065 index += 1
+
1066 }
+
1067
+
1068 // Write scale at byte 14
+
1069 write(offset: fbeOffset + 14, value: scale)
+
1070
+
1071 // Write signum at byte 15
+
1072 write(offset: fbeOffset + 15, value: UInt8(value.isSignMinus ? 128: 0))
+
1073 }
+
1074}
+
1075)CODE";
+
1076
+
1077 // Prepare code template
+
1078 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
1079
+
1080 Write(code);
+
1081
+
1082 // Generate footer
+
1083 GenerateFooter();
+
1084
+
1085 // Store the file
+
1086 WriteEnd();
+
1087 Store(file);
+
1088}
+
1089
+
1090void GeneratorSwift::GenerateFBEFieldModelTimestamp(const std::string& domain, const std::string& package)
+
1091{
+
1092 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
1093
+
1094 // Generate the file
+
1095 CppCommon::Path file = path / "FieldModelTimestamp.swift";
+
1096 WriteBegin();
+
1097
+
1098 // Generate headers
+
1099 GenerateHeader("FBE");
+
1100 GenerateImports("", "Foundation");
+
1101
+
1102 std::string code = R"CODE(
+
1103// Fast Binary Encoding timestamp field model
+
1104public class FieldModelTimestamp: FieldModel {
+
1105 public var _buffer = Buffer()
+
1106 public var _offset: Int = 0
+
1107
+
1108 // Field size
+
1109 public let fbeSize: Int = 8
+
1110
+
1111 public required init() {
+
1112 _buffer = Buffer()
+
1113 _offset = 0
+
1114 }
+
1115
+
1116 public func get(defaults: Date = Date(timeIntervalSince1970: 0)) -> Date {
+
1117 if (_buffer.offset + fbeOffset + fbeSize) > _buffer.size {
+
1118 return defaults
+
1119 }
+
1120
+
1121 let nanoseconds = TimeInterval(readInt64(offset: fbeOffset))
+
1122 return Date(timeIntervalSince1970: nanoseconds / 1_000_000_000)
+
1123 }
+
1124
+
1125 public func set(value: Date) throws {
+
1126 if (_buffer.offset + fbeOffset + fbeSize) > _buffer.size {
+
1127 assertionFailure("Model is broken!")
+
1128 return
+
1129 }
+
1130
+
1131 let milliseconds = value.timeIntervalSince1970 * 1000
+
1132 write(offset: fbeOffset, value: UInt64(milliseconds) * 1_000_000)
+
1133 }
+
1134}
+
1135)CODE";
+
1136
+
1137 // Prepare code template
+
1138 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
1139
+
1140 Write(code);
+
1141
+
1142 // Generate footer
+
1143 GenerateFooter();
+
1144
+
1145 // Store the file
+
1146 WriteEnd();
+
1147 Store(file);
+
1148}
+
1149
+
1150void GeneratorSwift::GenerateFBEFieldModelBytes(const std::string& domain, const std::string& package)
+
1151{
+
1152 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
1153
+
1154 // Generate the file
+
1155 CppCommon::Path file = path / "FieldModelData.swift";
+
1156 WriteBegin();
+
1157
+
1158 // Generate headers
+
1159 GenerateHeader("FBE");
+
1160 GenerateImports("", "Foundation");
+
1161
+
1162 std::string code = R"CODE(
+
1163// Fast Binary Encoding bytes field model
+
1164public class FieldModelData: FieldModel {
+
1165 public var _buffer = Buffer()
+
1166 public var _offset: Int = 0
+
1167
+
1168 // Field size
+
1169 public let fbeSize: Int = 4
+
1170
+
1171 public required init() {
+
1172 _buffer = Buffer()
+
1173 _offset = 0
+
1174 }
+
1175
+
1176 // Field extra size
+
1177 public var fbeExtra: Int {
+
1178 if (_buffer.offset + fbeOffset + fbeSize) > _buffer.size {
+
1179 return 0
+
1180 }
+
1181
+
1182 let fbeBytesOffset = Int(readUInt32(offset: fbeOffset))
+
1183 if (fbeBytesOffset == 0) || ((_buffer.offset + fbeBytesOffset + 4) > _buffer.size) {
+
1184 return 0
+
1185 }
+
1186
+
1187 let fbeBytesSize = Int(readUInt32(offset: fbeBytesOffset))
+
1188 return 4 + fbeBytesSize
+
1189 }
+
1190
+
1191 public func verify() -> Bool {
+
1192 if (_buffer.offset + fbeOffset + fbeSize) > _buffer.size {
+
1193 return true
+
1194 }
+
1195
+
1196 let fbeBytesOffset = Int(readUInt32(offset: fbeOffset))
+
1197 if fbeBytesOffset == 0 {
+
1198 return true
+
1199 }
+
1200
+
1201 if (_buffer.offset + fbeBytesOffset + 4) > _buffer.size {
+
1202 return false
+
1203 }
+
1204
+
1205 let fbeBytesSize = Int(readUInt32(offset: fbeBytesOffset))
+
1206 if (_buffer.offset + fbeBytesOffset + 4 + fbeBytesSize) > _buffer.size {
+
1207 return false
+
1208 }
+
1209
+
1210 return true
+
1211 }
+
1212
+
1213 // Get the value
+
1214 public func get(defaults: Data = Data(count: 0)) -> Data {
+
1215 if (_buffer.offset + fbeOffset + fbeSize) > _buffer.size {
+
1216 return defaults
+
1217 }
+
1218
+
1219 let fbeBytesOffset = Int(readUInt32(offset: fbeOffset))
+
1220 if fbeBytesOffset == 0 {
+
1221 return defaults
+
1222 }
+
1223
+
1224 if _buffer.offset + fbeBytesOffset + 4 > _buffer.size {
+
1225 assertionFailure("Model is broken!")
+
1226 return defaults
+
1227 }
+
1228
+
1229 let fbeBytesSize = Int(readUInt32(offset: fbeBytesOffset))
+
1230 if _buffer.offset + fbeBytesOffset + 4 + fbeBytesSize > _buffer.size {
+
1231 assertionFailure("Model is broken!")
+
1232 return defaults
+
1233 }
+
1234
+
1235 return readBytes(offset: fbeBytesOffset + 4, size: fbeBytesSize)
+
1236 }
+
1237
+
1238 // Set the value
+
1239 public func set(value: Data) throws {
+
1240 if _buffer.offset + fbeOffset + fbeSize > _buffer.size {
+
1241 assertionFailure("Model is broken!")
+
1242 return
+
1243 }
+
1244
+
1245 let fbeBytesSize = value.count
+
1246 let fbeBytesOffset = try _buffer.allocate(size: 4 + fbeBytesSize) - _buffer.offset
+
1247 if fbeBytesOffset <= 0 || (_buffer.offset + fbeBytesOffset + 4 + fbeBytesSize) > _buffer.size {
+
1248 assertionFailure("Model is broken!")
+
1249 return
+
1250 }
+
1251
+
1252 write(offset: fbeOffset, value: UInt32(fbeBytesOffset))
+
1253 write(offset: fbeBytesOffset, value: UInt32(fbeBytesSize))
+
1254 write(offset: fbeBytesOffset + 4, value: value)
+
1255 }
+
1256}
+
1257)CODE";
+
1258
+
1259 // Prepare code template
+
1260 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
1261
+
1262 Write(code);
+
1263
+
1264 // Generate footer
+
1265 GenerateFooter();
+
1266
+
1267 // Store the file
+
1268 WriteEnd();
+
1269 Store(file);
+
1270}
+
1271
+
1272void GeneratorSwift::GenerateFBEFieldModelString(const std::string& domain, const std::string& package)
+
1273{
+
1274 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
1275
+
1276 // Generate the file
+
1277 CppCommon::Path file = path / "FieldModelString.swift";
+
1278 WriteBegin();
+
1279
+
1280 // Generate headers
+
1281 GenerateHeader("FBE");
+
1282
+
1283 std::string code = R"CODE(// Fast Binary Encoding string field model
+
1284public class FieldModelString: FieldModel {
+
1285 public var _buffer: Buffer
+
1286 public var _offset: Int
+
1287
+
1288 // Field size
+
1289 public let fbeSize: Int = 4
+
1290
+
1291 public required init() {
+
1292 _buffer = Buffer()
+
1293 _offset = 0
+
1294 }
+
1295
+
1296 public required init(buffer: Buffer, offset: Int) {
+
1297 _buffer = buffer
+
1298 _offset = offset
+
1299 }
+
1300
+
1301 public var fbeExtra: Int {
+
1302 if (_buffer.offset + fbeOffset + fbeSize) > _buffer.size {
+
1303 return 0
+
1304 }
+
1305
+
1306 let fbeStringOffset = Int(readUInt32(offset: fbeOffset))
+
1307 if (fbeStringOffset == 0) || ((_buffer.offset + fbeStringOffset + 4) > _buffer.size) {
+
1308 return 0
+
1309 }
+
1310
+
1311 let fbeStringSize = Int(readUInt32(offset: fbeStringOffset))
+
1312 return 4 + fbeStringSize
+
1313 }
+
1314
+
1315 // Check if the string value is valid
+
1316 public func verify() -> Bool {
+
1317 if (_buffer.offset + fbeOffset + fbeSize) > _buffer.size {
+
1318 return true
+
1319 }
+
1320
+
1321 let fbeStringOffset = Int(readUInt32(offset: fbeOffset))
+
1322 if fbeStringOffset == 0 {
+
1323 return true
+
1324 }
+
1325
+
1326 if _buffer.offset + fbeStringOffset + 4 > _buffer.size {
+
1327 return false
+
1328 }
+
1329
+
1330 let fbeStringSize = Int(readUInt32(offset: fbeStringOffset))
+
1331 if (_buffer.offset + fbeStringOffset + 4 + fbeStringSize) > _buffer.size {
+
1332 return false
+
1333 }
+
1334
+
1335 return true
+
1336 }
+
1337
+
1338 // Get the value
+
1339 public func get(defaults: String = "") -> String {
+
1340 if (_buffer.offset + fbeOffset + fbeSize) > _buffer.size {
+
1341 return defaults
+
1342 }
+
1343
+
1344 let fbeStringOffset = Int(readUInt32(offset: fbeOffset))
+
1345 if fbeStringOffset == 0 {
+
1346 return defaults
+
1347 }
+
1348
+
1349 if (_buffer.offset + fbeStringOffset + 4) > _buffer.size {
+
1350 return defaults
+
1351 }
+
1352
+
1353 let fbeStringSize = Int(readUInt32(offset: fbeStringOffset))
+
1354 if (_buffer.offset + fbeStringOffset + 4 + fbeStringSize) > _buffer.size {
+
1355 return defaults
+
1356 }
+
1357
+
1358 return readString(offset: fbeStringOffset + 4, size: fbeStringSize)
+
1359 }
+
1360
+
1361 // Set the value
+
1362 public func set(value: String) throws {
+
1363 if (_buffer.offset + fbeOffset + fbeSize) > _buffer.size {
+
1364 return
+
1365 }
+
1366
+
1367 let fbeStringSize = value.count
+
1368 let fbeStringOffset = try _buffer.allocate(size: 4 + fbeStringSize) - _buffer.offset
+
1369 if (fbeStringOffset <= 0) || ((_buffer.offset + fbeStringOffset + 4 + fbeStringSize) > _buffer.size) {
+
1370 return
+
1371 }
+
1372
+
1373 write(offset: fbeOffset, value: UInt32(fbeStringOffset))
+
1374 write(offset: fbeStringOffset, value: value)
+
1375 }
+
1376}
+
1377)CODE";
+
1378
+
1379 // Prepare code template
+
1380 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
1381
+
1382 Write(code);
+
1383
+
1384 // Generate footer
+
1385 GenerateFooter();
+
1386
+
1387 // Store the file
+
1388 WriteEnd();
+
1389 Store(file);
+
1390}
+
1391
+
1392void GeneratorSwift::GenerateFBEFieldModelOptional(const std::string& domain, const std::shared_ptr<Package>& p, const std::string& name, const std::string& type, const std::string& model)
+
1393{
+
1394 std::string package = ConvertPackage(p);
+
1395 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "Fbe";
+
1396
+
1397 // Create package path
+
1398 CppCommon::Directory::CreateTree(path);
+
1399
+
1400 // Generate the file
+
1401 CppCommon::Path file = path / ("FieldModelOptional" + name + ".swift");
+
1402 WriteBegin();
+
1403
+
1404 // Generate headers
+
1405 GenerateHeader(CppCommon::Path(_input).filename().string());
+
1406 GenerateImports("", "Foundation");
+
1407 GenerateImports(domain, "Fbe");
+
1408 GenerateImports(p);
+
1409
+
1410 std::string code = R"CODE(
+
1411// Fast Binary Encoding optional _NAME_ field model
+
1412public class FieldModelOptional_NAME_: FieldModel {
+
1413
+
1414 public var _buffer: Buffer
+
1415 public var _offset: Int
+
1416
+
1417 // Field size
+
1418 public let fbeSize: Int = 1 + 4
+
1419
+
1420 // Base field model value
+
1421 public let value: _MODEL_
+
1422
+
1423 public var fbeExtra: Int {
+
1424 if !hasValue() {
+
1425 return 0
+
1426 }
+
1427
+
1428 let fbeOptionalOffset = Int(readUInt32(offset: fbeOffset + 1))
+
1429 if (fbeOptionalOffset == 0) || ((_buffer.offset + fbeOptionalOffset + 4) > _buffer.size) {
+
1430 return 0
+
1431 }
+
1432
+
1433 _buffer.shift(offset: fbeOptionalOffset)
+
1434 let fbeResult = value.fbeSize + value.fbeExtra
+
1435 _buffer.unshift(offset: fbeOptionalOffset)
+
1436 return fbeResult
+
1437 }
+
1438
+
1439 public required init() {
+
1440 let buffer = Buffer()
+
1441 let offset = 0
+
1442
+
1443 _buffer = buffer
+
1444 _offset = offset
+
1445
+
1446 value = _MODEL_(buffer: buffer, offset: 0)
+
1447 }
+
1448
+
1449 public required init(buffer: Buffer, offset: Int) {
+
1450 _buffer = buffer
+
1451 _offset = offset
+
1452
+
1453 value = _MODEL_(buffer: buffer, offset: 0)
+
1454 }
+
1455
+
1456 public func hasValue() -> Bool {
+
1457 if (_buffer.offset + fbeOffset + fbeSize) > _buffer.size {
+
1458 return false
+
1459 }
+
1460
+
1461 let fbeHasValue = Int32(readInt8(offset: fbeOffset))
+
1462 return fbeHasValue != 0
+
1463 }
+
1464
+
1465 public func verify() -> Bool {
+
1466 if _buffer.offset + fbeOffset + fbeSize > _buffer.size {
+
1467 return true
+
1468 }
+
1469
+
1470 let fbeHasValue = Int(readInt8(offset: fbeOffset))
+
1471 if fbeHasValue == 0 {
+
1472 return true
+
1473 }
+
1474
+
1475 let fbeOptionalOffset = Int(readUInt32(offset: fbeOffset + 1))
+
1476 if fbeOptionalOffset == 0 {
+
1477 return false
+
1478 }
+
1479
+
1480 _buffer.shift(offset: fbeOptionalOffset)
+
1481 let fbeResult = value.verify()
+
1482 _buffer.unshift(offset: fbeOptionalOffset)
+
1483 return fbeResult
+
1484 }
+
1485
+
1486 // Get the optional value (being phase)
+
1487 func getBegin() -> Int {
+
1488 if !hasValue() {
+
1489 return 0
+
1490 }
+
1491
+
1492 let fbeOptionalOffset = Int(readUInt32(offset: fbeOffset + 1))
+
1493 if fbeOptionalOffset <= 0 {
+
1494 assertionFailure("Model is broken!")
+
1495 return 0
+
1496 }
+
1497
+
1498 _buffer.shift(offset: fbeOptionalOffset)
+
1499 return fbeOptionalOffset
+
1500 }
+
1501
+
1502 // Get the optional value (end phase)
+
1503 func getEnd(fbeBegin: Int) {
+
1504 _buffer.unshift(offset: fbeBegin)
+
1505 }
+
1506
+
1507 public func get(defaults: _TYPE_ = nil) -> _TYPE_ {
+
1508 let fbeBegin = getBegin()
+
1509 if fbeBegin == 0 {
+
1510 return defaults
+
1511 }
+
1512
+
1513 let optional = value.get()
+
1514 getEnd(fbeBegin: fbeBegin)
+
1515 return optional
+
1516 }
+
1517
+
1518 // Set the optional value (begin phase)
+
1519 func setBegin(hasValue: Bool) throws -> Int {
+
1520 if _buffer.offset + fbeOffset + fbeSize > _buffer.size {
+
1521 assertionFailure("Model is broken!")
+
1522 return 0
+
1523 }
+
1524
+
1525 let fbeHasValue = hasValue ? 1 : 0
+
1526 write(offset: fbeOffset, value: Int8(fbeHasValue))
+
1527 if fbeHasValue == 0 {
+
1528 return 0
+
1529 }
+
1530
+
1531 let fbeOptionalSize = value.fbeSize
+
1532 let fbeOptionalOffset = try _buffer.allocate(size: fbeOptionalSize) - _buffer.offset
+
1533 if (fbeOptionalOffset <= 0) || ((_buffer.offset + fbeOptionalOffset + fbeOptionalSize) > _buffer.size) {
+
1534 assertionFailure("Model is broken!")
+
1535 return 0
+
1536 }
+
1537
+
1538 write(offset: fbeOffset + 1, value: UInt32(fbeOptionalOffset))
+
1539
+
1540 _buffer.shift(offset: fbeOptionalOffset)
+
1541 return fbeOptionalOffset
+
1542 }
+
1543
+
1544 // Set the optional value (end phase)
+
1545 func setEnd(fbeBegin: Int) {
+
1546 _buffer.unshift(offset: fbeBegin)
+
1547 }
+
1548
+
1549 // Set the optional value
+
1550 public func set(value optional: _TYPE_) throws {
+
1551 let fbeBegin = try setBegin(hasValue: optional != nil)
+
1552 if fbeBegin == 0 {
+
1553 return
+
1554 }
+
1555
+
1556 try value.set(value: optional!)
+
1557 setEnd(fbeBegin: fbeBegin)
+
1558 }
+
1559}
+
1560)CODE";
+
1561
+
1562 std::string type_name = type;
+
1563
+
1564 // Prepare code template
+
1565 code = std::regex_replace(code, std::regex("_DOMAIN_"), domain);
+
1566 code = std::regex_replace(code, std::regex("_NAME_"), name);
+
1567 code = std::regex_replace(code, std::regex("_TYPE_"), type_name);
+
1568 code = std::regex_replace(code, std::regex("_MODEL_"), model);
+
1569 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
1570
+
1571 Write(code);
+
1572
+
1573 // Generate footer
+
1574 GenerateFooter();
+
1575
+
1576 // Store the file
+
1577 WriteEnd();
+
1578 Store(file);
+
1579}
+
1580
+
1581void GeneratorSwift::GenerateFBEFieldModelArray(const std::string& domain, const std::shared_ptr<Package>& p, const std::string& name, const std::string& type, const std::string& base, bool optional, const std::string& model)
+
1582{
+
1583 std::string package = ConvertPackage(p);
+
1584 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "Fbe";
+
1585
+
1586 // Create package path
+
1587 CppCommon::Directory::CreateTree(path);
+
1588
+
1589 // Generate the file
+
1590 CppCommon::Path file = path / ("FieldModelArray" + name + ".swift");
+
1591 WriteBegin();
+
1592
+
1593 // Generate headers
+
1594 GenerateHeader(CppCommon::Path(_input).filename().string());
+
1595 GenerateImports("", "Foundation");
+
1596 GenerateImports(domain, "Fbe");
+
1597 GenerateImports(p);
+
1598
+
1599 std::string code = R"CODE(
+
1600// Fast Binary Encoding _NAME_ array field model
+
1601class FieldModelArray_NAME_: FieldModel {
+
1602 private let _model: _MODEL_
+
1603
+
1604 var _buffer: Buffer
+
1605 var _offset: Int
+
1606 var size: Int
+
1607
+
1608 // Field size
+
1609 var fbeSize: Int {
+
1610 return size * _model.fbeSize
+
1611 }
+
1612
+
1613 // Field extra size
+
1614 var fbeExtra: Int = 0
+
1615
+
1616 // Get the vector offset
+
1617 var offset: Int = 0
+
1618
+
1619 required init() {
+
1620 let buffer = Buffer()
+
1621 let offset = 0
+
1622
+
1623 _buffer = buffer
+
1624 _offset = offset
+
1625 self.size = 0
+
1626
+
1627 _model = _MODEL_(buffer: buffer, offset: offset)
+
1628 }
+
1629
+
1630 required init(buffer: Buffer, offset: Int, size: Int) {
+
1631 _buffer = buffer
+
1632 _offset = offset
+
1633 self.size = size
+
1634
+
1635 _model = _MODEL_(buffer: buffer, offset: offset)
+
1636 }
+
1637
+
1638 // Vector index operator
+
1639 public func getItem(index: Int) -> _MODEL_ {
+
1640 assert(_buffer.offset + fbeOffset + fbeSize <= _buffer.size, "Model is broken!")
+
1641 assert(index < size, "Model is broken!")
+
1642
+
1643 _model.fbeOffset = fbeOffset
+
1644 _model.fbeShift(size: index * _model.fbeSize)
+
1645 return _model
+
1646 }
+
1647
+
1648 public func verify() -> Bool {
+
1649 if _buffer.offset + fbeOffset + fbeSize > _buffer.size {
+
1650 return false
+
1651 }
+
1652
+
1653 _model.fbeOffset = fbeOffset
+
1654 var i = size
+
1655 while i > 0 {
+
1656 if !_model.verify() { return false }
+
1657 _model.fbeShift(size: _model.fbeSize)
+
1658 i -= 1
+
1659 }
+
1660
+
1661 return true
+
1662 }
+
1663
+
1664 public func get() -> _ARRAY_ {
+
1665 var values = _ARRAY_()
+
1666 let fbeModel = getItem(index: 0)
+
1667 for _ in 0..<size {
+
1668 values.append(fbeModel.get())
+
1669 fbeModel.fbeShift(size: fbeModel.fbeSize)
+
1670 }
+
1671
+
1672 return values
+
1673 }
+
1674
+
1675 public func get(values: inout _ARRAY_) {
+
1676 values.removeAll()
+
1677
+
1678 let fbeVectorSize = size
+
1679 if fbeVectorSize == 0 {
+
1680 return
+
1681 }
+
1682
+
1683 values.reserveCapacity(fbeVectorSize)
+
1684
+
1685 let fbeModel = getItem(index: 0)
+
1686 var i = size
+
1687 while i > 0 {
+
1688 let value = fbeModel.get()
+
1689 values.append(value)
+
1690 fbeModel.fbeShift(size: fbeModel.fbeSize)
+
1691 i -= 1
+
1692 }
+
1693 }
+
1694
+
1695 public func set(value values: _ARRAY_) throws {
+
1696 if _buffer.offset + fbeOffset + fbeSize > _buffer.size {
+
1697 assertionFailure("Model is broken!")
+
1698 return
+
1699 }
+
1700
+
1701 let fbeModel = getItem(index: 0)
+
1702 for value in values {
+
1703 try fbeModel.set(value: value)
+
1704 fbeModel.fbeShift(size: fbeModel.fbeSize)
+
1705 }
+
1706 }
+
1707}
+
1708)CODE";
+
1709
+
1710 std::string type_name = IsPackageType(type) ? type : (domain + package + "." + type);
+
1711
+
1712 // Prepare code template
+
1713 code = std::regex_replace(code, std::regex("_DOMAIN_"), domain);
+
1714 code = std::regex_replace(code, std::regex("_NAME_"), name);
+
1715 code = std::regex_replace(code, std::regex("_TYPE_"), type_name);
+
1716 code = std::regex_replace(code, std::regex("_MODEL_"), model);
+
1717
+
1718 if (optional)
+
1719 code = std::regex_replace(code, std::regex("_ARRAY_"), "Array<" + type_name + ">");
+
1720 else
+
1721 code = std::regex_replace(code, std::regex("_ARRAY_"), "Array<" + type_name + ">");
+
1722 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
1723
+
1724 Write(code);
+
1725
+
1726 // Generate footer
+
1727 GenerateFooter();
+
1728
+
1729 // Store the file
+
1730 WriteEnd();
+
1731 Store(file);
+
1732}
+
1733
+
1734void GeneratorSwift::GenerateFBEFieldModelVector(const std::string& domain, const std::shared_ptr<Package>& p, const std::string& name, const std::string& type, const std::string& model)
+
1735{
+
1736 std::string package = ConvertPackage(p);
+
1737 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "Fbe";
+
1738
+
1739 // Create package path
+
1740 CppCommon::Directory::CreateTree(path);
+
1741
+
1742 // Generate the file
+
1743 CppCommon::Path file = path / ("FieldModelVector" + name + ".swift");
+
1744 WriteBegin();
+
1745
+
1746 // Generate headers
+
1747 GenerateHeader(CppCommon::Path(_input).filename().string());
+
1748 GenerateImports("", "Foundation");
+
1749 GenerateImports(domain, "Fbe");
+
1750 GenerateImports(p);
+
1751
+
1752 std::string code = R"CODE(
+
1753// Fast Binary Encoding _NAME_ vector field model
+
1754class FieldModelVector_NAME_: FieldModel {
+
1755 private let _model: _MODEL_
+
1756
+
1757 var _buffer: Buffer
+
1758 var _offset: Int
+
1759
+
1760 // Field size
+
1761 let fbeSize: Int = 4
+
1762
+
1763 var fbeExtra: Int {
+
1764 if _buffer.offset + fbeOffset + fbeSize > _buffer.size {
+
1765 return 0
+
1766 }
+
1767
+
1768 let fbeVectorOffset = Int(readUInt32(offset: fbeOffset))
+
1769 if (fbeVectorOffset == 0) || ((_buffer.offset + fbeVectorOffset + 4) > _buffer.size) {
+
1770 return 0
+
1771 }
+
1772
+
1773 let fbeVectorSize = Int(readUInt32(offset: fbeVectorOffset))
+
1774
+
1775 var fbeResult: Int = 4
+
1776 _model.fbeOffset = fbeVectorOffset + 4
+
1777 var i = fbeVectorSize
+
1778 while i > 0 {
+
1779 fbeResult += _model.fbeSize + _model.fbeExtra
+
1780 _model.fbeShift(size: _model.fbeSize)
+
1781 i -= 1
+
1782 }
+
1783 return fbeResult
+
1784 }
+
1785
+
1786 required init() {
+
1787 let buffer = Buffer()
+
1788 let offset = 0
+
1789
+
1790 _buffer = buffer
+
1791 _offset = offset
+
1792
+
1793 _model = _MODEL_(buffer: buffer, offset: offset)
+
1794 }
+
1795
+
1796 required init(buffer: Buffer, offset: Int) {
+
1797 _buffer = buffer
+
1798 _offset = offset
+
1799
+
1800 _model = _MODEL_(buffer: buffer, offset: offset)
+
1801 }
+
1802
+
1803 // Get the vector offset
+
1804 var offset: Int {
+
1805 if (_buffer.offset + fbeOffset + fbeSize) > _buffer.size {
+
1806 return 0
+
1807 }
+
1808
+
1809 return Int(readUInt32(offset: fbeOffset))
+
1810 }
+
1811
+
1812 // Get the vector offset
+
1813 var size: Int {
+
1814 if _buffer.offset + fbeOffset + fbeSize > _buffer.size {
+
1815 return 0
+
1816 }
+
1817
+
1818 let fbeVectorOffset = Int(readUInt32(offset: fbeOffset))
+
1819 if (fbeVectorOffset == 0) || ((_buffer.offset + fbeVectorOffset + 4) > _buffer.size) {
+
1820 return 0
+
1821 }
+
1822
+
1823 return Int(readUInt32(offset: fbeVectorOffset))
+
1824 }
+
1825
+
1826 // Vector index operator
+
1827 public func getItem(index: Int) -> _MODEL_ {
+
1828 assert(_buffer.offset + fbeOffset + fbeSize <= _buffer.size, "Model is broken!")
+
1829
+
1830 let fbeVectorOffset = Int(readUInt32(offset: fbeOffset))
+
1831 assert((fbeVectorOffset > 0) && ((_buffer.offset + fbeVectorOffset + 4) <= _buffer.size), "Model is broken!")
+
1832
+
1833 let fbeVectorSize = Int(readUInt32(offset: fbeVectorOffset))
+
1834 assert(index < fbeVectorSize, "Index is out of bounds!")
+
1835
+
1836 _model.fbeOffset = fbeVectorOffset + 4
+
1837 _model.fbeShift(size: index * _model.fbeSize)
+
1838 return _model
+
1839 }
+
1840
+
1841 func resize(size: Int) throws -> _MODEL_ {
+
1842 let fbeVectorSize = size * _model.fbeSize
+
1843 let fbeVectorOffset = try _buffer.allocate(size: 4 + fbeVectorSize) - _buffer.offset
+
1844 assert((fbeVectorOffset > 0) && ((_buffer.offset + fbeVectorOffset + 4) <= _buffer.size), "Model is broken!")
+
1845
+
1846 write(offset: fbeOffset, value: UInt32(fbeVectorOffset))
+
1847 write(offset: fbeVectorOffset, value: UInt32(size))
+
1848 write(offset: fbeVectorOffset + 4, value: UInt8.zero, valueCount: fbeVectorSize)
+
1849
+
1850 _model.fbeOffset = fbeVectorOffset + 4
+
1851 return _model
+
1852 }
+
1853
+
1854 public func verify() -> Bool {
+
1855 if _buffer.offset + fbeOffset + fbeSize > _buffer.size {
+
1856 return true
+
1857 }
+
1858
+
1859 let fbeVectorOffset = Int(readUInt32(offset: fbeOffset))
+
1860 if fbeVectorOffset == 0 {
+
1861 return true
+
1862 }
+
1863
+
1864 if _buffer.offset + fbeVectorOffset + 4 > _buffer.size {
+
1865 return false
+
1866 }
+
1867
+
1868 let fbeVectorSize = Int(readUInt32(offset: fbeVectorOffset))
+
1869 _model.fbeOffset = fbeVectorOffset + 4
+
1870 var i = fbeVectorSize
+
1871 while i > 0 {
+
1872 if !_model.verify() { return false }
+
1873 _model.fbeShift(size: _model.fbeSize)
+
1874 i -= 1
+
1875 }
+
1876
+
1877 return true
+
1878 }
+
1879
+
1880 public func get(values: inout Array<_TYPE_>) {
+
1881 values.removeAll()
+
1882
+
1883 let fbeVectorSize = size
+
1884 if fbeVectorSize == 0 {
+
1885 return
+
1886 }
+
1887
+
1888 values.reserveCapacity(fbeVectorSize)
+
1889
+
1890 let fbeModel = getItem(index: 0)
+
1891 var i = fbeVectorSize
+
1892 while i > 0 {
+
1893 let value = fbeModel.get()
+
1894 values.append(value)
+
1895 fbeModel.fbeShift(size: fbeModel.fbeSize)
+
1896 i -= 1
+
1897 }
+
1898 }
+
1899
+
1900 public func set(value values: Array<_TYPE_>) throws {
+
1901 if _buffer.offset + fbeOffset + fbeSize > _buffer.size {
+
1902 assertionFailure("Model is broken!")
+
1903 return
+
1904 }
+
1905
+
1906 let fbeModel = try resize(size: values.count)
+
1907 for i in 0..<values.count {
+
1908 try fbeModel.set(value: values[i])
+
1909 fbeModel.fbeShift(size: fbeModel.fbeSize)
+
1910 }
+
1911 }
+
1912}
+
1913)CODE";
+
1914
+
1915 std::string type_name = IsPackageType(type) ? type : (domain + package + "." + type);
+
1916
+
1917 // Prepare code template
+
1918 code = std::regex_replace(code, std::regex("_DOMAIN_"), domain);
+
1919 code = std::regex_replace(code, std::regex("_NAME_"), name);
+
1920 code = std::regex_replace(code, std::regex("_TYPE_"), type_name);
+
1921 code = std::regex_replace(code, std::regex("_MODEL_"), model);
+
1922 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
1923
+
1924 Write(code);
+
1925
+
1926 // Generate footer
+
1927 GenerateFooter();
+
1928
+
1929 // Store the file
+
1930 WriteEnd();
+
1931 Store(file);
+
1932}
+
1933
+
1934void GeneratorSwift::GenerateFBEFieldModelMap(const std::string& domain, const std::shared_ptr<Package>& p, const std::string& key_name, const std::string& key_type, const std::string& key_model, const std::string& value_name, const std::string& value_type, const std::string& value_model)
+
1935{
+
1936 std::string package = ConvertPackage(p);
+
1937 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "Fbe";
+
1938
+
1939 // Create package path
+
1940 CppCommon::Directory::CreateTree(path);
+
1941
+
1942 // Generate the file
+
1943 CppCommon::Path file = path / ("FieldModelMap" + key_name + value_name + ".swift");
+
1944 WriteBegin();
+
1945
+
1946 // Generate headers
+
1947 GenerateHeader(CppCommon::Path(_input).filename().string());
+
1948 GenerateImports("", "Foundation");
+
1949 GenerateImports(domain, "Fbe");
+
1950 GenerateImports(p);
+
1951
+
1952 std::string code = R"CODE(
+
1953// Fast Binary Encoding _KEY_NAME_->_VALUE_NAME_ map field model
+
1954class FieldModelMap_KEY_NAME__VALUE_NAME_: FieldModel {
+
1955 private let _modelKey: _KEY_MODEL_
+
1956 private let _modelValue: _VALUE_MODEL_
+
1957
+
1958 var _buffer: Buffer
+
1959 var _offset: Int
+
1960
+
1961 // Field size
+
1962 let fbeSize: Int = 4
+
1963
+
1964 var fbeExtra: Int {
+
1965 if _buffer.offset + fbeOffset + fbeSize > _buffer.size {
+
1966 return 0
+
1967 }
+
1968
+
1969 let fbeMapOffset = Int(readUInt32(offset: fbeOffset))
+
1970 if (fbeMapOffset == 0) || ((_buffer.offset + fbeMapOffset + 4) > _buffer.size) {
+
1971 return 0
+
1972 }
+
1973
+
1974 let fbeMapSize = Int(readUInt32(offset: fbeMapOffset))
+
1975
+
1976 var fbeResult: Int = 4
+
1977 _modelKey.fbeOffset = fbeMapOffset + 4
+
1978 _modelValue.fbeOffset = fbeMapOffset + 4 + _modelKey.fbeSize
+
1979 var i = fbeMapSize
+
1980 while i > 0 {
+
1981 fbeResult += _modelKey.fbeSize + _modelKey.fbeExtra
+
1982 _modelKey.fbeShift(size: _modelKey.fbeSize)
+
1983 fbeResult += _modelValue.fbeSize + _modelValue.fbeExtra
+
1984 _modelValue.fbeShift(size: _modelValue.fbeSize)
+
1985 i -= 1
+
1986 }
+
1987 return fbeResult
+
1988 }
+
1989
+
1990 required init() {
+
1991 let buffer = Buffer()
+
1992 let offset = 0
+
1993
+
1994 _buffer = buffer
+
1995 _offset = offset
+
1996
+
1997 _modelKey = _KEY_MODEL_(buffer: buffer, offset: offset)
+
1998 _modelValue = _VALUE_MODEL_(buffer: buffer, offset: offset)
+
1999 }
+
2000
+
2001 required init(buffer: Buffer, offset: Int) {
+
2002 _buffer = buffer
+
2003 _offset = offset
+
2004
+
2005 _modelKey = _KEY_MODEL_(buffer: buffer, offset: offset)
+
2006 _modelValue = _VALUE_MODEL_(buffer: buffer, offset: offset)
+
2007 }
+
2008
+
2009 // Get the vector offset
+
2010 var offset: Int {
+
2011 if (_buffer.offset + fbeOffset + fbeSize) > _buffer.size {
+
2012 return 0
+
2013 }
+
2014
+
2015 return Int(readUInt32(offset: fbeOffset))
+
2016 }
+
2017
+
2018 // Get the vector offset
+
2019 var size: Int {
+
2020 if _buffer.offset + fbeOffset + fbeSize > _buffer.size {
+
2021 return 0
+
2022 }
+
2023
+
2024 let fbeMapOffset = Int(readUInt32(offset: fbeOffset))
+
2025 if (fbeMapOffset == 0) || ((_buffer.offset + fbeMapOffset + 4) > _buffer.size) {
+
2026 return 0
+
2027 }
+
2028
+
2029 return Int(readUInt32(offset: fbeMapOffset))
+
2030 }
+
2031
+
2032 // Vector index operator
+
2033 public func getItem(index: Int) -> (_KEY_MODEL_, _VALUE_MODEL_) {
+
2034 assert(_buffer.offset + fbeOffset + fbeSize <= _buffer.size, "Model is broken!")
+
2035
+
2036 let fbeMapOffset = Int(readUInt32(offset: fbeOffset))
+
2037 assert((fbeMapOffset > 0) && ((_buffer.offset + fbeMapOffset + 4) <= _buffer.size), "Model is broken!")
+
2038
+
2039 let fbeMapSize = Int(readUInt32(offset: fbeMapOffset))
+
2040 assert(index < fbeMapSize, "Index is out of bounds!")
+
2041
+
2042 _modelKey.fbeOffset = fbeMapOffset + 4
+
2043 _modelValue.fbeOffset = fbeMapOffset + 4 + _modelKey.fbeSize
+
2044 _modelKey.fbeShift(size: index * (_modelKey.fbeSize + _modelValue.fbeSize))
+
2045 _modelValue.fbeShift(size: index * (_modelKey.fbeSize + _modelValue.fbeSize))
+
2046 return (_modelKey, _modelValue)
+
2047 }
+
2048
+
2049 func resize(size: Int) throws -> (_KEY_MODEL_, _VALUE_MODEL_) {
+
2050 let fbeMapSize = size * (_modelKey.fbeSize + _modelValue.fbeSize)
+
2051 let fbeMapOffset = try _buffer.allocate(size: 4 + fbeMapSize) - _buffer.offset
+
2052 assert((fbeMapOffset > 0) && ((_buffer.offset + fbeMapOffset + 4) <= _buffer.size), "Model is broken!")
+
2053
+
2054 write(offset: fbeOffset, value: UInt32(fbeMapOffset))
+
2055 write(offset: fbeMapOffset, value: UInt32(size))
+
2056 write(offset: fbeMapOffset + 4, value: UInt8.zero, valueCount: fbeMapSize)
+
2057
+
2058 _modelKey.fbeOffset = fbeMapOffset + 4
+
2059 _modelValue.fbeOffset = fbeMapOffset + 4 + _modelKey.fbeSize
+
2060 return (_modelKey, _modelValue)
+
2061 }
+
2062
+
2063 public func verify() -> Bool {
+
2064 if _buffer.offset + fbeOffset + fbeSize > _buffer.size {
+
2065 return true
+
2066 }
+
2067
+
2068 let fbeMapOffset = Int(readUInt32(offset: fbeOffset))
+
2069 if fbeMapOffset == 0 {
+
2070 return true
+
2071 }
+
2072
+
2073 if _buffer.offset + fbeMapOffset + 4 > _buffer.size {
+
2074 return false
+
2075 }
+
2076
+
2077 let fbeMapSize = Int(readUInt32(offset: fbeMapOffset))
+
2078 _modelKey.fbeOffset = fbeMapOffset + 4
+
2079 _modelValue.fbeOffset = fbeMapOffset + 4 + _modelKey.fbeSize
+
2080 var i = fbeMapSize
+
2081 while i > 0 {
+
2082 if !_modelKey.verify() { return false }
+
2083 _modelKey.fbeShift(size: _modelKey.fbeSize + _modelValue.fbeSize)
+
2084 if !_modelValue.verify() { return false }
+
2085 _modelValue.fbeShift(size: _modelKey.fbeSize + _modelValue.fbeSize)
+
2086 i -= 1
+
2087 }
+
2088
+
2089 return true
+
2090 }
+
2091
+
2092 public func get(values: inout Dictionary<_KEY_TYPE_, _VALUE_TYPE_>) {
+
2093 values.removeAll()
+
2094
+
2095 let fbeMapSize = size
+
2096 if fbeMapSize == 0 {
+
2097 return
+
2098 }
+
2099
+
2100 values.reserveCapacity(fbeMapSize)
+
2101
+
2102 let fbeModel = getItem(index: 0)
+
2103 var i = fbeMapSize
+
2104 while i > 0 {
+
2105 let key = fbeModel.0.get()
+
2106 let value = fbeModel.1.get()
+
2107 values[key] = value
+
2108 fbeModel.0.fbeShift(size: fbeModel.0.fbeSize + fbeModel.1.fbeSize)
+
2109 fbeModel.1.fbeShift(size: fbeModel.0.fbeSize + fbeModel.1.fbeSize)
+
2110 i -= 1
+
2111 }
+
2112 }
+
2113
+
2114 public func set(value values: Dictionary<_KEY_TYPE_, _VALUE_TYPE_>) throws {
+
2115 if _buffer.offset + fbeOffset + fbeSize > _buffer.size {
+
2116 assertionFailure("Model is broken!")
+
2117 return
+
2118 }
+
2119
+
2120 let fbeModel = try resize(size: values.count)
+
2121 for (key, value) in values {
+
2122 try fbeModel.0.set(value: key)
+
2123 fbeModel.0.fbeShift(size: fbeModel.0.fbeSize + fbeModel.1.fbeSize)
+
2124 try fbeModel.1.set(value: value)
+
2125 fbeModel.1.fbeShift(size: fbeModel.0.fbeSize + fbeModel.1.fbeSize)
+
2126 }
+
2127 }
+
2128}
+
2129)CODE";
+
2130
+
2131 std::string key_type_name = IsPackageType(key_type) ? key_type : (domain + package + "." + key_type);
+
2132 std::string value_type_name = IsPackageType(value_type) ? value_type : (domain + package + "." + value_type);
+
2133
+
2134 // Prepare code template
+
2135 code = std::regex_replace(code, std::regex("_DOMAIN_"), domain);
+
2136 code = std::regex_replace(code, std::regex("_KEY_NAME_"), key_name);
+
2137 code = std::regex_replace(code, std::regex("_KEY_TYPE_"), key_type_name);
+
2138 code = std::regex_replace(code, std::regex("_KEY_MODEL_"), key_model);
+
2139 code = std::regex_replace(code, std::regex("_VALUE_NAME_"), value_name);
+
2140 code = std::regex_replace(code, std::regex("_VALUE_TYPE_"), value_type_name);
+
2141 code = std::regex_replace(code, std::regex("_VALUE_MODEL_"), value_model);
+
2142 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2143
+
2144 Write(code);
+
2145
+
2146 // Generate footer
+
2147 GenerateFooter();
+
2148
+
2149 // Store the file
+
2150 WriteEnd();
+
2151 Store(file);
+
2152}
+
2153
+
2154void GeneratorSwift::GenerateFBEFieldModelEnumFlags(const std::string& domain, const std::string& package, const std::string& name, const std::string& type)
+
2155{
+
2156 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "Fbe";
+
2157
+
2158 // Create package path
+
2159 CppCommon::Directory::CreateTree(path);
+
2160
+
2161 // Generate the file
+
2162 CppCommon::Path file = path / ("FieldModel" + name + ".swift");
+
2163 WriteBegin();
+
2164
+
2165 // Generate headers
+
2166 GenerateHeader(CppCommon::Path(_input).filename().string());
+
2167 GenerateImports(domain, "Fbe");
+
2168
+
2169 std::string code = R"CODE(
+
2170// Fast Binary Encoding _NAME_ field model
+
2171public class FieldModel_NAME_: FieldModel {
+
2172
+
2173 public var _buffer: Buffer = Buffer()
+
2174 public var _offset: Int = 0
+
2175
+
2176 public var fbeSize: Int = _SIZE_
+
2177
+
2178 public required init() {
+
2179 _buffer = Buffer()
+
2180 _offset = 0
+
2181 }
+
2182
+
2183 // Get the value
+
2184 public func get(defaults: _NAME_ = _NAME_()) -> _NAME_ {
+
2185 if _buffer.offset + fbeOffset + fbeSize > _buffer.size {
+
2186 return defaults
+
2187 }
+
2188
+
2189 return _NAME_(value: _READ_(offset: fbeOffset))
+
2190 }
+
2191
+
2192 // Set the value
+
2193 public func set(value: _NAME_) throws {
+
2194 if (_buffer.offset + fbeOffset + fbeSize) > _buffer.size {
+
2195 assertionFailure("Model is broken!")
+
2196 return
+
2197 }
+
2198
+
2199 write(offset: fbeOffset, value: value.raw)
+
2200 }
+
2201}
+
2202)CODE";
+
2203
+
2204 // Prepare code template
+
2205 code = std::regex_replace(code, std::regex("_DOMAIN_"), domain);
+
2206 code = std::regex_replace(code, std::regex("_PACKAGE_"), package);
+
2207 code = std::regex_replace(code, std::regex("_NAME_"), name);
+
2208 code = std::regex_replace(code, std::regex("_SIZE_"), ConvertEnumSize(type));
+
2209 code = std::regex_replace(code, std::regex("_READ_"), ConvertEnumRead(type));
+
2210 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2211
+
2212 Write(code);
+
2213
+
2214 // Generate footer
+
2215 GenerateFooter();
+
2216
+
2217 // Store the file
+
2218 WriteEnd();
+
2219 Store(file);
+
2220}
+
2221
+
2222void GeneratorSwift::GenerateFBESize(const std::string& domain, const std::string& package)
+
2223{
+
2224 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
2225
+
2226 // Generate the file
+
2227 CppCommon::Path file = path / "Size.swift";
+
2228 WriteBegin();
+
2229
+
2230 // Generate headers
+
2231 GenerateHeader("FBE");
+
2232
+
2233 std::string code = R"CODE(
+
2234// Fast Binary Encoding size
+
2235public class Size {
+
2236 public var value: Int
+
2237
+
2238 public init(size: Int = 0) {
+
2239 value = size
+
2240 }
+
2241}
+
2242)CODE";
+
2243
+
2244 // Prepare code template
+
2245 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2246
+
2247 Write(code);
+
2248
+
2249 // Generate footer
+
2250 GenerateFooter();
+
2251
+
2252 // Store the file
+
2253 WriteEnd();
+
2254 Store(file);
+
2255}
+
2256
+
2257void GeneratorSwift::GenerateFBEFinalModel(const std::string& domain, const std::string& package)
+
2258{
+
2259 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
2260
+
2261 // Generate the file
+
2262 CppCommon::Path file = path / "FinalModel.swift";
+
2263 WriteBegin();
+
2264
+
2265 // Generate headers
+
2266 GenerateHeader("FBE");
+
2267 GenerateImports("", "Foundation");
+
2268
+
2269 std::string code = R"CODE(
+
2270// Fast Binary Encoding base final model
+
2271public protocol FinalModel: class {
+
2272 var _buffer: Buffer { get set }
+
2273 var _offset: Int { get set }
+
2274
+
2275 // Field size
+
2276 var fbeSize: Int { get }
+
2277 // Field extra size
+
2278 var fbeExtra: Int { get }
+
2279}
+
2280
+
2281public extension FinalModel {
+
2282
+
2283 // Field offset
+
2284 var fbeOffset: Int {
+
2285 get {
+
2286 return _offset
+
2287 }
+
2288 set {
+
2289 _offset = newValue
+
2290 }
+
2291 }
+
2292
+
2293 // Field size
+
2294 var fbeSize: Int {
+
2295 return 0
+
2296 }
+
2297
+
2298 // Field extra size
+
2299 var fbeExtra: Int {
+
2300 return 0
+
2301 }
+
2302
+
2303 // Shift the current field offset
+
2304 func fbeShift(size: Int) { _offset += size }
+
2305 // Unshift the current field offset
+
2306 func fbeUnshift(size: Int) { _offset -= size }
+
2307
+
2308 // Check if the value is valid
+
2309 func verify() -> Bool {
+
2310 return true
+
2311 }
+
2312
+
2313 // Buffer I/O methods
+
2314 func readBoolean(offset: Int) -> Bool { return Buffer.readBoolean(buffer: _buffer.data, offset: _buffer.offset + offset) }
+
2315 func readByte(offset: Int) -> Data.Element { return Buffer.readByte(buffer: _buffer.data, offset: _buffer.offset + offset) }
+
2316 func readChar(offset: Int) -> Character { return Buffer.readChar(buffer: _buffer.data, offset: _buffer.offset + offset) }
+
2317 func readWChar(offset: Int) -> Character { return Buffer.readWChar(buffer: _buffer, offset: _buffer.offset + offset) }
+
2318 func readInt8(offset: Int) -> Int8 { return Buffer.readInt8(buffer: _buffer, offset: _buffer.offset + offset) }
+
2319 func readUInt8(offset: Int) -> UInt8 { return Buffer.readUInt8(buffer: _buffer.data, offset: _buffer.offset + offset) }
+
2320 func readInt16(offset: Int) -> Int16 { return Buffer.readInt16(buffer: _buffer, offset: _buffer.offset + offset) }
+
2321 func readUInt16(offset: Int) -> UInt16 { return Buffer.readUInt16(buffer: _buffer, offset: _buffer.offset + offset) }
+
2322 func readInt32(offset: Int) -> Int32 { return Buffer.readInt32(buffer: _buffer, offset: _buffer.offset + offset) }
+
2323 func readUInt32(offset: Int) -> UInt32 { return Buffer.readUInt32(buffer: _buffer, offset: _buffer.offset + offset) }
+
2324 func readInt64(offset: Int) -> Int64 { return Buffer.readInt64(buffer: _buffer, offset: _buffer.offset + offset) }
+
2325 func readUInt64(offset: Int) -> UInt64 { return Buffer.readUInt64(buffer: _buffer, offset: _buffer.offset + offset) }
+
2326 func readFloat(offset: Int) -> Float { return Buffer.readFloat(buffer: _buffer, offset: _buffer.offset + offset) }
+
2327 func readDouble(offset: Int) -> Double { return Buffer.readDouble(buffer: _buffer, offset: _buffer.offset + offset) }
+
2328 func readBytes(offset: Int, size: Int) -> Data { return Buffer.readBytes(buffer: _buffer.data, offset: _buffer.offset + offset, size: size) }
+
2329 func readString(offset: Int, size: Int) -> String { return Buffer.readString(buffer: _buffer, offset: _buffer.offset + offset, size: size) }
+
2330 func readUUID(offset: Int) -> UUID { return Buffer.readUUID(buffer: _buffer.data, offset: _buffer.offset + offset) }
+
2331 func write(offset: Int, value: Bool) { Buffer.write(buffer: &_buffer, offset: _buffer.offset + offset, value: value) }
+
2332 func write(offset: Int, value: Int8) { Buffer.write(buffer: &_buffer, offset: _buffer.offset + offset, value: value) }
+
2333 func write(offset: Int, value: UInt8) { Buffer.write(buffer: &_buffer, offset: _buffer.offset + offset, value: value) }
+
2334 func write(offset: Int, value: Int16) { Buffer.write(buffer: &_buffer, offset: _buffer.offset + offset, value: value) }
+
2335 func write(offset: Int, value: UInt16) { Buffer.write(buffer: &_buffer, offset: _buffer.offset + offset, value: value) }
+
2336 func write(offset: Int, value: Int32) { Buffer.write(buffer: &_buffer, offset: _buffer.offset + offset, value: value) }
+
2337 func write(offset: Int, value: UInt32) { Buffer.write(buffer: &_buffer, offset: _buffer.offset + offset, value: value) }
+
2338 func write(offset: Int, value: Int64) { Buffer.write(buffer: &_buffer, offset: _buffer.offset + offset, value: value) }
+
2339 func write(offset: Int, value: UInt64) { Buffer.write(buffer: &_buffer, offset: _buffer.offset + offset, value: value) }
+
2340 func write(offset: Int, value: String) { Buffer.write(buffer: &_buffer, offset: _buffer.offset + offset, value: value) }
+
2341 func write(offset: Int, value: Float) { Buffer.write(buffer: &_buffer, offset: _buffer.offset + offset, value: value) }
+
2342 func write(offset: Int, value: Double) { Buffer.write(buffer: &_buffer, offset: _buffer.offset + offset, value: value) }
+
2343 func write(offset: Int, value: Data) { Buffer.write(buffer: &_buffer.data, offset: _buffer.offset + offset, value: value) }
+
2344 func write(offset: Int, value: Data, valueOffset: Int, valueSize: Int) { Buffer.write(buffer: &_buffer, offset: _buffer.offset + offset, value: value, valueOffset: valueOffset, valueSize: valueSize) }
+
2345 func write(offset: Int, value: Data.Element, valueCount: Int) { Buffer.write(buffer: &_buffer, offset: _buffer.offset + offset, value: value, valueCount: valueCount) }
+
2346 func write(offset: Int, value: UUID) { Buffer.write(buffer: &_buffer.data, offset: _buffer.offset + offset, value: value) }
+
2347}
+
2348)CODE";
+
2349
+
2350 // Prepare code template
+
2351 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2352
+
2353 Write(code);
+
2354
+
2355 // Generate footer
+
2356 GenerateFooter();
+
2357
+
2358 // Store the file
+
2359 WriteEnd();
+
2360 Store(file);
+
2361}
+
2362
+
2363void GeneratorSwift::GenerateFBEFinalModel(const std::string& domain, const std::string& package, const std::string& name, const std::string& type, const std::string& base, const std::string& size, const std::string& defaults)
+
2364{
+
2365 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
2366
+
2367 // Generate the file
+
2368 CppCommon::Path file = path / ("FinalModel" + name + ".swift");
+
2369 WriteBegin();
+
2370
+
2371 // Generate headers
+
2372 GenerateHeader("FBE");
+
2373 GenerateImports("", "Foundation");
+
2374
+
2375 std::string code = R"CODE(
+
2376// Fast Binary Encoding _TYPE_ final model
+
2377public class FinalModel_NAME_: FinalModel {
+
2378 public var _buffer = Buffer()
+
2379 public var _offset: Int = 0
+
2380
+
2381 public init(buffer: Buffer, offset: Int) {
+
2382 _buffer = buffer
+
2383 _offset = offset
+
2384 }
+
2385
+
2386 // Get the allocation size
+
2387 public func fbeAllocationSize(value: _TYPE_) -> Int {
+
2388 return fbeSize
+
2389 }
+
2390
+
2391 // Field size
+
2392 public let fbeSize: Int = _SIZE_
+
2393
+
2394 // Check if the value is valid
+
2395 public func verify() -> Int {
+
2396 if _buffer.offset + fbeOffset + fbeSize > _buffer.size {
+
2397 return Int.max
+
2398 }
+
2399
+
2400 return fbeSize
+
2401 }
+
2402
+
2403 // Get the value
+
2404 public func get(size: inout Size) -> _TYPE_ {
+
2405 if (_buffer.offset + fbeOffset + fbeSize) > _buffer.size {
+
2406 return _DEFAULTS_
+
2407 }
+
2408
+
2409 size.value = fbeSize
+
2410 return read_NAME_(offset: fbeOffset)
+
2411 }
+
2412
+
2413 // Set the value
+
2414 public func set(value: _TYPE_) throws -> Int {
+
2415 if (_buffer.offset + fbeOffset + fbeSize) > _buffer.size {
+
2416 assertionFailure("Model is broken!")
+
2417 return 0
+
2418 }
+
2419
+
2420 write(offset: fbeOffset, value: value_BASE_)
+
2421 return fbeSize
+
2422 }
+
2423}
+
2424)CODE";
+
2425
+
2426 // Prepare code template
+
2427 code = std::regex_replace(code, std::regex("_NAME_"), name);
+
2428 code = std::regex_replace(code, std::regex("_TYPE_"), type);
+
2429 code = std::regex_replace(code, std::regex("_BASE_"), base);
+
2430 code = std::regex_replace(code, std::regex("_SIZE_"), size);
+
2431 code = std::regex_replace(code, std::regex("_DEFAULTS_"), defaults);
+
2432 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2433
+
2434 Write(code);
+
2435
+
2436 // Generate footer
+
2437 GenerateFooter();
+
2438
+
2439 // Store the file
+
2440 WriteEnd();
+
2441 Store(file);
+
2442}
+
2443
+
2444void GeneratorSwift::GenerateFBEFinalModelDecimal(const std::string& domain, const std::string& package)
+
2445{
+
2446 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
2447
+
2448 // Generate the file
+
2449 CppCommon::Path file = path / "FinalModelDecimal.swift";
+
2450 WriteBegin();
+
2451
+
2452 // Generate headers
+
2453 GenerateHeader("FBE");
+
2454 GenerateImports("", "Foundation");
+
2455
+
2456 std::string code = R"CODE(
+
2457// Fast Binary Encoding decimal final model
+
2458public class FinalModelDecimal: FinalModel {
+
2459 public var _buffer = Buffer()
+
2460 public var _offset: Int = 0
+
2461
+
2462 // Field size
+
2463 public let fbeSize: Int = 16
+
2464
+
2465 public init(buffer: Buffer, offset: Int) {
+
2466 _buffer = buffer
+
2467 _offset = offset
+
2468 }
+
2469
+
2470 public func fbeAllocationSize(value: Decimal) -> Int {
+
2471 return fbeSize
+
2472 }
+
2473
+
2474 public func verify() -> Int {
+
2475 if (_buffer.offset + fbeOffset + fbeSize) > _buffer.size {
+
2476 return Int.max
+
2477 }
+
2478
+
2479 return fbeSize
+
2480 }
+
2481
+
2482 // Get the value
+
2483 public func get(size: inout Size) -> Decimal {
+
2484 if (_buffer.offset + fbeOffset + fbeSize) > _buffer.size {
+
2485 return Decimal.zero
+
2486 }
+
2487
+
2488 let lowScaleField = Decimal(string: "18446744073709551616")!
+
2489 let midScaleField = Decimal(string: "4294967296")!
+
2490
+
2491 let flags = readUInt32(offset: fbeOffset + 12)
+
2492 let negative = (flags & 0x80000000) != 0
+
2493 let scale = -Int((flags & 0x7FFFFFFF) >> 16)
+
2494 let sign: FloatingPointSign = negative ? .minus : .plus
+
2495
+
2496 var result = Decimal(readUInt32(offset: fbeOffset + 8)) * lowScaleField
+
2497 result += Decimal(readUInt32(offset: fbeOffset + 4)) * midScaleField
+
2498 result += Decimal(readUInt32(offset: fbeOffset + 0))
+
2499 result = Decimal(sign: sign, exponent: scale, significand: result)
+
2500
+
2501 if result.exponent != scale {
+
2502 var zero = Decimal(sign: sign, exponent: scale, significand: .zero)
+
2503 NSDecimalNormalize(&result, &zero, .up)
+
2504 }
+
2505
+
2506 size.value = fbeSize
+
2507 return result
+
2508 }
+
2509
+
2510 // Set the value
+
2511 public func set(value: Decimal) throws -> Int {
+
2512 if (_buffer.offset + fbeOffset + fbeSize) > _buffer.size {
+
2513 assertionFailure("Model is broken!")
+
2514 return 0
+
2515 }
+
2516
+
2517 var valueRef = value
+
2518 if valueRef.exponent > 0 {
+
2519 // Try to normalize decimal number for .NET Decimal format
+
2520 var zero = Decimal.zero
+
2521 let error = NSDecimalNormalize(&valueRef, &zero, .up)
+
2522 if error != .noError {
+
2523 // Issue during normalize decimal number
+
2524 write(offset: fbeOffset, value: UInt8.zero, valueCount: fbeSize)
+
2525 return 0
+
2526 }
+
2527 }
+
2528
+
2529 // Get scale
+
2530 let scale = UInt8(abs(valueRef.exponent))
+
2531 if scale < 0 || scale > 28 {
+
2532 // Value scale exceeds .NET Decimal limit of [0, 28]
+
2533 write(offset: fbeOffset, value: UInt8.zero, valueCount: fbeSize)
+
2534 return 0
+
2535 }
+
2536
+
2537 // Get byte array
+
2538 let unscaledBytes = withUnsafeBytes(of: valueRef) {
+
2539 Array($0)
+
2540 }
+
2541
+
2542 // Write unscaled value to bytes 0-11
+
2543 var index = 0
+
2544 let straterIndex = unscaledBytes.count - min(unscaledBytes.count, 16)
+
2545 let bytes = Array(unscaledBytes[straterIndex..<min(unscaledBytes.count, 16)])
+
2546 while index < 12 {
+
2547 write(offset: fbeOffset + index, value: bytes[index])
+
2548 index += 1
+
2549 }
+
2550
+
2551 // Fill remaining bytes with zeros
+
2552 while index < 14 {
+
2553 write(offset: fbeOffset + index, value: Int8.zero)
+
2554 index += 1
+
2555 }
+
2556
+
2557 // Write scale at byte 14
+
2558 write(offset: fbeOffset + 14, value: scale)
+
2559
+
2560 // Write signum at byte 15
+
2561 write(offset: fbeOffset + 15, value: UInt8(value.isSignMinus ? 128: 0))
+
2562 return fbeSize
+
2563 }
+
2564}
+
2565)CODE";
+
2566
+
2567 // Prepare code template
+
2568 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2569
+
2570 Write(code);
+
2571
+
2572 // Generate footer
+
2573 GenerateFooter();
+
2574
+
2575 // Store the file
+
2576 WriteEnd();
+
2577 Store(file);
+
2578}
+
2579
+
2580void GeneratorSwift::GenerateFBEFinalModelTimestamp(const std::string& domain, const std::string& package)
+
2581{
+
2582 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
2583
+
2584 // Generate the file
+
2585 CppCommon::Path file = path / "FinalModelTimestamp.swift";
+
2586 WriteBegin();
+
2587
+
2588 // Generate headers
+
2589 GenerateHeader("FBE");
+
2590 GenerateImports("", "Foundation");
+
2591
+
2592 std::string code = R"CODE(
+
2593// Fast Binary Encoding timestamp final model
+
2594public class FinalModelTimestamp: FinalModel {
+
2595 public var _buffer = Buffer()
+
2596 public var _offset: Int = 0
+
2597
+
2598 public init(buffer: Buffer, offset: Int) {
+
2599 _buffer = buffer
+
2600 _offset = offset
+
2601 }
+
2602
+
2603 // Get the allocation size
+
2604 public func fbeAllocationSize(value: Date) -> Int {
+
2605 return fbeSize
+
2606 }
+
2607
+
2608 // Field size
+
2609 public let fbeSize: Int = 8
+
2610
+
2611 // Check if the value is valid
+
2612 public func verify() -> Int {
+
2613 if _buffer.offset + fbeOffset + fbeSize > _buffer.size {
+
2614 return Int.max
+
2615 }
+
2616
+
2617 return fbeSize
+
2618 }
+
2619
+
2620 // Get the value
+
2621 public func get(size: inout Size) -> Date {
+
2622 if _buffer.offset + fbeOffset + fbeSize > _buffer.size {
+
2623 return Date(timeIntervalSince1970: 0)
+
2624 }
+
2625
+
2626 size.value = fbeSize
+
2627 let nanoseconds = TimeInterval(readInt64(offset: fbeOffset))
+
2628 return Date(timeIntervalSince1970: nanoseconds / 1_000_000_000)
+
2629 }
+
2630
+
2631 // Set the value
+
2632 public func set(value: Date) throws -> Int {
+
2633 if _buffer.offset + fbeOffset + fbeSize > _buffer.size {
+
2634 assertionFailure("Model is broken!")
+
2635 return 0
+
2636 }
+
2637
+
2638 let milliseconds = value.timeIntervalSince1970 * 1000
+
2639 write(offset: fbeOffset, value: UInt64(milliseconds) * 1_000_000)
+
2640 return fbeSize
+
2641 }
+
2642}
+
2643)CODE";
+
2644
+
2645 // Prepare code template
+
2646 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2647
+
2648 Write(code);
+
2649
+
2650 // Generate footer
+
2651 GenerateFooter();
+
2652
+
2653 // Store the file
+
2654 WriteEnd();
+
2655 Store(file);
+
2656}
+
2657
+
2658void GeneratorSwift::GenerateFBEFinalModelBytes(const std::string& domain, const std::string& package)
+
2659{
+
2660 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
2661
+
2662 // Generate the file
+
2663 CppCommon::Path file = path / "FinalModelData.swift";
+
2664 WriteBegin();
+
2665
+
2666 // Generate headers
+
2667 GenerateHeader("FBE");
+
2668 GenerateImports("", "Foundation");
+
2669
+
2670 std::string code = R"CODE(
+
2671// Fast Binary Encoding bytes final model
+
2672public class FinalModelData: FinalModel {
+
2673 public var _buffer = Buffer()
+
2674 public var _offset: Int = 0
+
2675
+
2676 public init(buffer: Buffer, offset: Int) {
+
2677 _buffer = buffer
+
2678 _offset = offset
+
2679 }
+
2680
+
2681 public func fbeAllocationSize(value: Data) -> Int {
+
2682 return 4 + value.count
+
2683 }
+
2684
+
2685 public func verify() -> Int {
+
2686 if (_buffer.offset + fbeOffset) + 4 > _buffer.size {
+
2687 return Int.max
+
2688 }
+
2689
+
2690 let fbeBytesSize = Int(readUInt32(offset: fbeOffset))
+
2691 if (_buffer.offset + fbeOffset + 4 + fbeBytesSize) > _buffer.size {
+
2692 return Int.max
+
2693 }
+
2694
+
2695 return 4 + fbeBytesSize
+
2696 }
+
2697
+
2698 // Get the value
+
2699 public func get(size: inout Size) -> Data {
+
2700 if (_buffer.offset + fbeOffset + fbeSize) > _buffer.size {
+
2701 size.value = 0
+
2702 return Data()
+
2703 }
+
2704
+
2705 let fbeBytesSize = Int(readUInt32(offset: fbeOffset))
+
2706 if _buffer.offset + fbeOffset + 4 + fbeBytesSize > _buffer.size {
+
2707 assertionFailure("Model is broken!")
+
2708 size.value = 4
+
2709 return Data()
+
2710 }
+
2711
+
2712 size.value = 4 + fbeBytesSize
+
2713 return readBytes(offset: fbeOffset + 4, size: fbeBytesSize)
+
2714 }
+
2715
+
2716 // Set the value
+
2717 public func set(value: Data) throws -> Int {
+
2718 if (_buffer.offset + fbeOffset + 4) > _buffer.size {
+
2719 assertionFailure("Model is broken!")
+
2720 return 0
+
2721 }
+
2722
+
2723 let fbeBytesSize = value.count
+
2724 if _buffer.offset + fbeOffset + 4 + fbeBytesSize > _buffer.size {
+
2725 assertionFailure("Model is broken!")
+
2726 return 4
+
2727 }
+
2728
+
2729 write(offset: fbeOffset, value: UInt32(fbeBytesSize))
+
2730 write(offset: fbeOffset + 4, value: value)
+
2731 return 4 + fbeBytesSize
+
2732 }
+
2733}
+
2734)CODE";
+
2735
+
2736 // Prepare code template
+
2737 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2738
+
2739 Write(code);
+
2740
+
2741 // Generate footer
+
2742 GenerateFooter();
+
2743
+
2744 // Store the file
+
2745 WriteEnd();
+
2746 Store(file);
+
2747}
+
2748
+
2749void GeneratorSwift::GenerateFBEFinalModelString(const std::string& domain, const std::string& package)
+
2750{
+
2751 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
2752
+
2753 // Generate the file
+
2754 CppCommon::Path file = path / "FinalModelString.swift";
+
2755 WriteBegin();
+
2756
+
2757 // Generate headers
+
2758 GenerateHeader("FBE");
+
2759
+
2760 std::string code = R"CODE(
+
2761// Fast Binary Encoding string final model
+
2762public class FinalModelString: FinalModel {
+
2763 public var _buffer = Buffer()
+
2764 public var _offset: Int = 0
+
2765
+
2766 public init(buffer: Buffer, offset: Int) {
+
2767 _buffer = buffer
+
2768 _offset = offset
+
2769 }
+
2770
+
2771 public func fbeAllocationSize(value: String) -> Int {
+
2772 return 4 + 3 * (value.count + 1)
+
2773 }
+
2774
+
2775 // Check if the value is valid
+
2776 public func verify() -> Int {
+
2777 if _buffer.offset + fbeOffset + 4 > _buffer.size {
+
2778 return Int.max
+
2779 }
+
2780
+
2781 let fbeStringSize = Int(readUInt32(offset: fbeOffset))
+
2782 if _buffer.offset + fbeOffset + 4 + fbeStringSize > _buffer.size {
+
2783 return Int.max
+
2784 }
+
2785
+
2786 return 4 + fbeStringSize
+
2787 }
+
2788
+
2789 // Get the value
+
2790 public func get(size: inout Size) -> String {
+
2791 if _buffer.offset + fbeOffset + 4 > _buffer.size {
+
2792 size.value = 0
+
2793 return ""
+
2794 }
+
2795
+
2796 let fbeStringSize = Int(readUInt32(offset: fbeOffset))
+
2797 if _buffer.offset + fbeOffset + 4 + fbeStringSize > _buffer.size {
+
2798 size.value = 4
+
2799 return ""
+
2800 }
+
2801
+
2802 size.value = 4 + fbeStringSize
+
2803 return readString(offset: fbeOffset + 4, size: fbeStringSize)
+
2804 }
+
2805
+
2806 // Set the value
+
2807 public func set(value: String) throws -> Int {
+
2808 if _buffer.offset + fbeOffset + 4 > _buffer.size {
+
2809 return 0
+
2810 }
+
2811
+
2812 let fbeStringSize = value.count
+
2813 if _buffer.offset + fbeOffset + 4 + fbeStringSize > _buffer.size {
+
2814 return 4
+
2815 }
+
2816
+
2817 write(offset: fbeOffset, value: value)
+
2818 return 4 + fbeStringSize
+
2819 }
+
2820}
+
2821)CODE";
+
2822
+
2823 // Prepare code template
+
2824 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2825
+
2826 Write(code);
+
2827
+
2828 // Generate footer
+
2829 GenerateFooter();
+
2830
+
2831 // Store the file
+
2832 WriteEnd();
+
2833 Store(file);
+
2834}
+
2835
+
2836void GeneratorSwift::GenerateFBEFinalModelOptional(const std::string& domain, const std::shared_ptr<Package>& p, const std::string& name, const std::string& type, const std::string& model)
+
2837{
+
2838 std::string package = ConvertPackage(p);
+
2839 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "Fbe";
+
2840
+
2841 // Create package path
+
2842 CppCommon::Directory::CreateTree(path);
+
2843
+
2844 // Generate the file
+
2845 CppCommon::Path file = path / ("FinalModelOptional" + name + ".swift");
+
2846 WriteBegin();
+
2847
+
2848 // Generate headers
+
2849 GenerateHeader(CppCommon::Path(_input).filename().string());
+
2850 GenerateImports("", "Foundation");
+
2851 GenerateImports(domain, "Fbe");
+
2852 GenerateImports(p);
+
2853
+
2854 std::string code = R"CODE(
+
2855// Fast Binary Encoding optional _NAME_ final model
+
2856class FinalModelOptional_NAME_: FinalModel {
+
2857
+
2858 var _buffer: Buffer
+
2859 var _offset: Int
+
2860
+
2861 // Base field model value
+
2862 let value: _MODEL_
+
2863
+
2864 required init() {
+
2865 let buffer = Buffer()
+
2866 let offset = 0
+
2867
+
2868 _buffer = buffer
+
2869 _offset = offset
+
2870
+
2871 value = _MODEL_(buffer: buffer, offset: offset)
+
2872 }
+
2873
+
2874 required init(buffer: Buffer, offset: Int) {
+
2875 _buffer = buffer
+
2876 _offset = offset
+
2877
+
2878 value = _MODEL_(buffer: buffer, offset: offset)
+
2879 }
+
2880
+
2881 func fbeAllocationSize(value optional: _TYPE_) -> Int {
+
2882 return 1 + (optional != nil ? value.fbeAllocationSize(value: optional!) : 0)
+
2883 }
+
2884
+
2885 func hasValue() -> Bool {
+
2886 if _buffer.offset + fbeOffset + 1 > _buffer.size {
+
2887 return false
+
2888 }
+
2889
+
2890 let fbeHasValue = Int32(readInt8(offset: fbeOffset))
+
2891 return fbeHasValue != 0
+
2892 }
+
2893
+
2894 public func verify() -> Int {
+
2895 if _buffer.offset + fbeOffset + 1 > _buffer.size {
+
2896 return Int.max
+
2897 }
+
2898
+
2899 let fbeHasValue = Int(readInt8(offset: fbeOffset))
+
2900 if fbeHasValue == 0 {
+
2901 return 1
+
2902 }
+
2903
+
2904 _buffer.shift(offset: fbeOffset + 1)
+
2905 let fbeResult = value.verify()
+
2906 _buffer.unshift(offset: fbeOffset + 1)
+
2907 return 1 + fbeResult
+
2908 }
+
2909
+
2910 public func get(size: inout Size) -> _TYPE_ {
+
2911 if _buffer.offset + fbeOffset + 1 > _buffer.size {
+
2912 assertionFailure("Model is broken!")
+
2913 size.value = 0
+
2914 return nil
+
2915 }
+
2916
+
2917 if !hasValue() {
+
2918 size.value = 1
+
2919 return nil
+
2920 }
+
2921
+
2922 _buffer.shift(offset: fbeOffset + 1)
+
2923 let optional = value.get(size: &size)
+
2924 _buffer.unshift(offset: fbeOffset + 1)
+
2925 size.value += 1
+
2926 return optional
+
2927 }
+
2928
+
2929 // Set the optional value
+
2930 public func set(value optional: _TYPE_) throws -> Int {
+
2931 if _buffer.offset + fbeOffset + 1 > _buffer.size {
+
2932 assertionFailure("Model is broken!")
+
2933 return 0
+
2934 }
+
2935
+
2936 let fbeHasValue = optional != nil ? 1 : 0
+
2937 write(offset: fbeOffset, value: Int8(fbeHasValue))
+
2938 if fbeHasValue == 0 {
+
2939 return 1
+
2940 }
+
2941
+
2942 _buffer.shift(offset: fbeOffset + 1)
+
2943 let size = try value.set(value: optional!)
+
2944 _buffer.unshift(offset: fbeOffset + 1)
+
2945 return 1 + size
+
2946 }
+
2947}
+
2948)CODE";
+
2949
+
2950 std::string type_name = type;
+
2951
+
2952 // Prepare code template
+
2953 code = std::regex_replace(code, std::regex("_DOMAIN_"), domain);
+
2954 code = std::regex_replace(code, std::regex("_NAME_"), name);
+
2955 code = std::regex_replace(code, std::regex("_TYPE_"), type_name);
+
2956 code = std::regex_replace(code, std::regex("_MODEL_"), model);
+
2957 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
2958
+
2959 Write(code);
+
2960
+
2961 // Generate footer
+
2962 GenerateFooter();
+
2963
+
2964 // Store the file
+
2965 WriteEnd();
+
2966 Store(file);
+
2967}
+
2968
+
2969void GeneratorSwift::GenerateFBEFinalModelArray(const std::string& domain, const std::shared_ptr<Package>& p, const std::string& name, const std::string& type, const std::string& base, bool optional, const std::string& model)
+
2970{
+
2971 std::string package = ConvertPackage(p);
+
2972 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "Fbe";
+
2973
+
2974 // Create package path
+
2975 CppCommon::Directory::CreateTree(path);
+
2976
+
2977 // Generate the file
+
2978 CppCommon::Path file = path / ("FinalModelArray" + name + ".swift");
+
2979 WriteBegin();
+
2980
+
2981 // Generate headers
+
2982 GenerateHeader(CppCommon::Path(_input).filename().string());
+
2983 GenerateImports("", "Foundation");
+
2984 GenerateImports(domain, "Fbe");
+
2985 GenerateImports(p);
+
2986
+
2987 std::string code = R"CODE(
+
2988// Fast Binary Encoding _NAME_ array final model
+
2989class FinalModelArray_NAME_: FinalModel {
+
2990 var _buffer: Buffer = Buffer()
+
2991 var _offset: Int = 0
+
2992 var _size: Int = 0
+
2993
+
2994 private var _model: _MODEL_
+
2995
+
2996 init(buffer: Buffer, offset: Int, size: Int) {
+
2997 _buffer = buffer
+
2998 _offset = offset
+
2999 _size = size
+
3000
+
3001 _model = _MODEL_(buffer: buffer, offset: offset)
+
3002 }
+
3003
+
3004 // Get the allocation size
+
3005 func fbeAllocationSize(value values: _ARRAY_) -> Int {
+
3006 var size: Int = 0
+
3007 for value in values {
+
3008 size += _model.fbeAllocationSize(value: value)
+
3009 }
+
3010
+
3011 return size
+
3012 }
+
3013
+
3014 // Check if the vector is valid
+
3015 public func verify() -> Int {
+
3016 if _buffer.offset + fbeOffset > _buffer.size {
+
3017 return Int.max
+
3018 }
+
3019
+
3020 var size: Int = 0
+
3021 _model.fbeOffset = fbeOffset
+
3022 var i = _size
+
3023 while i > 0 {
+
3024 let offset = _model.verify()
+
3025 if offset == Int.max { return Int.max }
+
3026 _model.fbeShift(size: offset)
+
3027 size += offset
+
3028 i -= 1
+
3029 }
+
3030 return size
+
3031 }
+
3032
+
3033 public func get(size: inout Size) -> _ARRAY_ {
+
3034 var values = _ARRAY_()
+
3035
+
3036 if _buffer.offset + fbeOffset > _buffer.size {
+
3037 assertionFailure("Model is broken!")
+
3038 size.value = 0
+
3039 return values
+
3040 }
+
3041
+
3042 size.value = 0
+
3043 var offset = Size()
+
3044 _model.fbeOffset = fbeOffset
+
3045 for _ in 0..._size {
+
3046 offset.value = 0
+
3047 let value = _model.get(size: &offset)
+
3048 values.append(value)
+
3049 _model.fbeShift(size: offset.value)
+
3050 size.value += offset.value
+
3051 }
+
3052 return values
+
3053 }
+
3054
+
3055 public func get(values: inout _ARRAY_) -> Int {
+
3056 values.removeAll()
+
3057
+
3058 if _buffer.offset + fbeOffset > _buffer.size {
+
3059 assertionFailure("Model is broken!")
+
3060 return 0
+
3061 }
+
3062
+
3063 var size: Int = 0
+
3064 var offset = Size()
+
3065 _model.fbeOffset = fbeOffset
+
3066 for _ in 1..._size {
+
3067 offset.value = 0
+
3068 let value = _model.get(size: &offset)
+
3069 values.append(value)
+
3070 _model.fbeShift(size: offset.value)
+
3071 size += offset.value
+
3072 }
+
3073 return size
+
3074 }
+
3075
+
3076 public func set(value values: _ARRAY_) throws -> Int {
+
3077 if _buffer.offset + fbeOffset > _buffer.size {
+
3078 assertionFailure("Model is broken!")
+
3079 return 0
+
3080 }
+
3081
+
3082 var size: Int = 0
+
3083 _model.fbeOffset = fbeOffset
+
3084 for value in values {
+
3085 let offset = try _model.set(value: value)
+
3086 _model.fbeShift(size: offset)
+
3087 size += offset
+
3088 }
+
3089 return size
+
3090 }
+
3091}
+
3092)CODE";
+
3093
+
3094 std::string type_name = type;
+
3095
+
3096 // Prepare code template
+
3097 code = std::regex_replace(code, std::regex("_DOMAIN_"), domain);
+
3098 code = std::regex_replace(code, std::regex("_NAME_"), name);
+
3099 code = std::regex_replace(code, std::regex("_TYPE_"), type_name);
+
3100 code = std::regex_replace(code, std::regex("_MODEL_"), model);
+
3101 if (optional)
+
3102 code = std::regex_replace(code, std::regex("_ARRAY_"), "Array<" + type_name + ">");
+
3103 else
+
3104 code = std::regex_replace(code, std::regex("_ARRAY_"), "Array<" + type_name + ">");
+
3105 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
3106
+
3107 Write(code);
+
3108
+
3109 // Generate footer
+
3110 GenerateFooter();
+
3111
+
3112 // Store the file
+
3113 WriteEnd();
+
3114 Store(file);
+
3115}
+
3116
+
3117void GeneratorSwift::GenerateFBEFinalModelVector(const std::string& domain, const std::shared_ptr<Package>& p, const std::string& name, const std::string& type, const std::string& model)
+
3118{
+
3119 std::string package = ConvertPackage(p);
+
3120 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "Fbe";
+
3121
+
3122 // Create package path
+
3123 CppCommon::Directory::CreateTree(path);
+
3124
+
3125 // Generate the file
+
3126 CppCommon::Path file = path / ("FinalModelVector" + name + ".swift");
+
3127 WriteBegin();
+
3128
+
3129 // Generate headers
+
3130 GenerateHeader(CppCommon::Path(_input).filename().string());
+
3131 GenerateImports("", "Foundation");
+
3132 GenerateImports(domain, "Fbe");
+
3133 GenerateImports(p);
+
3134
+
3135 std::string code = R"CODE(
+
3136// Fast Binary Encoding _NAME_ vector final model
+
3137class FinalModelVector_NAME_: FinalModel {
+
3138 var _buffer: Buffer = Buffer()
+
3139 var _offset: Int = 0
+
3140
+
3141 private var _model: _MODEL_
+
3142
+
3143 init(buffer: Buffer, offset: Int) {
+
3144 _buffer = buffer
+
3145 _offset = offset
+
3146
+
3147 _model = _MODEL_(buffer: buffer, offset: offset)
+
3148 }
+
3149
+
3150 // Get the allocation size
+
3151 func fbeAllocationSize(value values: Array<_TYPE_>) -> Int {
+
3152 var size: Int = 4
+
3153 for i in 0..<values.count {
+
3154 size += _model.fbeAllocationSize(value: values[i])
+
3155 }
+
3156
+
3157 return size
+
3158 }
+
3159
+
3160 // Check if the vector is valid
+
3161 public func verify() -> Int {
+
3162 if _buffer.offset + fbeOffset + 4 > _buffer.size {
+
3163 return Int.max
+
3164 }
+
3165
+
3166 let fbeVectorSize = Int(readUInt32(offset: fbeOffset))
+
3167
+
3168 var size: Int = 4
+
3169 _model.fbeOffset = fbeOffset + 4
+
3170 var i = fbeVectorSize
+
3171 while i > 0 {
+
3172 let offset = _model.verify()
+
3173 if offset == Int.max { return Int.max }
+
3174 _model.fbeShift(size: offset)
+
3175 size += offset
+
3176 i -= 1
+
3177 }
+
3178 return size
+
3179 }
+
3180
+
3181 public func get(values: inout Array<_TYPE_>) -> Int {
+
3182 values.removeAll()
+
3183
+
3184 if _buffer.offset + fbeOffset + 4 > _buffer.size {
+
3185 assertionFailure("Model is broken!")
+
3186 return 0
+
3187 }
+
3188
+
3189 let fbeVectorSize = Int(readUInt32(offset: fbeOffset))
+
3190 if fbeVectorSize == 0 {
+
3191 return 4
+
3192 }
+
3193
+
3194 values.reserveCapacity(fbeVectorSize)
+
3195
+
3196 var size: Int = 4
+
3197 var offset = Size()
+
3198 _model.fbeOffset = fbeOffset + 4
+
3199 for _ in 1...fbeVectorSize {
+
3200 offset.value = 0
+
3201 let value = _model.get(size: &offset)
+
3202 values.append(value)
+
3203 _model.fbeShift(size: offset.value)
+
3204 size += offset.value
+
3205 }
+
3206 return size
+
3207 }
+
3208
+
3209 public func set(value values: Array<_TYPE_>) throws -> Int {
+
3210 if _buffer.offset + fbeOffset + 4 > _buffer.size {
+
3211 assertionFailure("Model is broken!")
+
3212 return 0
+
3213 }
+
3214
+
3215 write(offset: fbeOffset, value: UInt32(values.count))
+
3216
+
3217 var size: Int = 4
+
3218 _model.fbeOffset = fbeOffset + 4
+
3219 for i in 0..<values.count {
+
3220 let offset = try _model.set(value: values[i])
+
3221 _model.fbeShift(size: offset)
+
3222 size += offset
+
3223 }
+
3224 return size
+
3225 }
+
3226}
+
3227)CODE";
+
3228
+
3229 std::string type_name = IsPackageType(type) ? type : (domain + package + "." + type);
+
3230
+
3231 // Prepare code template
+
3232 code = std::regex_replace(code, std::regex("_DOMAIN_"), domain);
+
3233 code = std::regex_replace(code, std::regex("_NAME_"), name);
+
3234 code = std::regex_replace(code, std::regex("_TYPE_"), type_name);
+
3235 code = std::regex_replace(code, std::regex("_MODEL_"), model);
+
3236 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
3237
+
3238 Write(code);
+
3239
+
3240 // Generate footer
+
3241 GenerateFooter();
+
3242
+
3243 // Store the file
+
3244 WriteEnd();
+
3245 Store(file);
+
3246}
+
3247
+
3248void GeneratorSwift::GenerateFBEFinalModelMap(const std::string& domain, const std::shared_ptr<Package>& p, const std::string& key_name, const std::string& key_type, const std::string& key_model, const std::string& value_name, const std::string& value_type, const std::string& value_model)
+
3249{
+
3250 std::string package = ConvertPackage(p);
+
3251 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "Fbe";
+
3252
+
3253 // Create package path
+
3254 CppCommon::Directory::CreateTree(path);
+
3255
+
3256 // Generate the file
+
3257 CppCommon::Path file = path / ("FinalModelMap" + key_name + value_name + ".swift");
+
3258 WriteBegin();
+
3259
+
3260 // Generate headers
+
3261 GenerateHeader(CppCommon::Path(_input).filename().string());
+
3262 GenerateImports("", "Foundation");
+
3263 GenerateImports(domain, "Fbe");
+
3264 GenerateImports(p);
+
3265
+
3266 std::string code = R"CODE(
+
3267// Fast Binary Encoding _KEY_NAME_->_VALUE_NAME_ map final model
+
3268class FinalModelMap_KEY_NAME__VALUE_NAME_: FinalModel {
+
3269 var _buffer: Buffer = Buffer()
+
3270 var _offset: Int = 0
+
3271
+
3272 private var _modelKey: _KEY_MODEL_
+
3273 private var _modelValue: _VALUE_MODEL_
+
3274
+
3275 init(buffer: Buffer, offset: Int) {
+
3276 _buffer = buffer
+
3277 _offset = offset
+
3278
+
3279 _modelKey = _KEY_MODEL_(buffer: buffer, offset: offset)
+
3280 _modelValue = _VALUE_MODEL_(buffer: buffer, offset: offset)
+
3281 }
+
3282
+
3283 // Get the allocation size
+
3284 func fbeAllocationSize(value values: Dictionary<_KEY_TYPE_, _VALUE_TYPE_>) -> Int {
+
3285 var size: Int = 4
+
3286 for (key, value) in values {
+
3287 size += _modelKey.fbeAllocationSize(value: key)
+
3288 size += _modelValue.fbeAllocationSize(value: value)
+
3289 }
+
3290
+
3291 return size
+
3292 }
+
3293
+
3294 // Check if the vector is valid
+
3295 public func verify() -> Int {
+
3296 if _buffer.offset + fbeOffset + 4 > _buffer.size {
+
3297 return Int.max
+
3298 }
+
3299
+
3300 let fbeMapSize = Int(readUInt32(offset: fbeOffset))
+
3301
+
3302 var size: Int = 4
+
3303 _modelKey.fbeOffset = fbeOffset + 4
+
3304 _modelValue.fbeOffset = fbeOffset + 4
+
3305 var i = fbeMapSize
+
3306 while i > 0 {
+
3307 let offsetKey = _modelKey.verify()
+
3308 if offsetKey == Int.max { return Int.max }
+
3309 _modelKey.fbeShift(size: offsetKey)
+
3310 _modelValue.fbeShift(size: offsetKey)
+
3311 size += offsetKey
+
3312 let offsetValue = _modelValue.verify()
+
3313 if offsetValue == Int.max { return Int.max }
+
3314 _modelKey.fbeShift(size: offsetValue)
+
3315 _modelValue.fbeShift(size: offsetValue)
+
3316 size += offsetValue
+
3317 i -= 1
+
3318 }
+
3319 return size
+
3320 }
+
3321
+
3322 public func get(values: inout Dictionary<_KEY_TYPE_, _VALUE_TYPE_>) -> Int {
+
3323 values.removeAll()
+
3324
+
3325 if _buffer.offset + fbeOffset + 4 > _buffer.size {
+
3326 assertionFailure("Model is broken!")
+
3327 return 0
+
3328 }
+
3329
+
3330 let fbeMapSize = Int(readUInt32(offset: fbeOffset))
+
3331 if fbeMapSize == 0 {
+
3332 return 4
+
3333 }
+
3334
+
3335 var size: Int = 4
+
3336 var offset = Size()
+
3337 _modelKey.fbeOffset = fbeOffset + 4
+
3338 _modelValue.fbeOffset = fbeOffset + 4
+
3339 for _ in 1...fbeMapSize {
+
3340 offset.value = 0
+
3341 let key = _modelKey.get(size: &offset)
+
3342 _modelKey.fbeShift(size: offset.value)
+
3343 _modelValue.fbeShift(size: offset.value)
+
3344 size += offset.value
+
3345 offset.value = 0
+
3346 let value = _modelValue.get(size: &offset)
+
3347 _modelKey.fbeShift(size: offset.value)
+
3348 _modelValue.fbeShift(size: offset.value)
+
3349 size += offset.value
+
3350 values[key] = value
+
3351 }
+
3352 return size
+
3353 }
+
3354
+
3355 public func set(value values: Dictionary<_KEY_TYPE_, _VALUE_TYPE_>) throws -> Int {
+
3356 if _buffer.offset + fbeOffset + 4 > _buffer.size {
+
3357 assertionFailure("Model is broken!")
+
3358 return 0
+
3359 }
+
3360
+
3361 write(offset: fbeOffset, value: UInt32(values.count))
+
3362
+
3363 var size: Int = 4
+
3364 _modelKey.fbeOffset = fbeOffset + 4
+
3365 _modelValue.fbeOffset = fbeOffset + 4
+
3366 for (key, value) in values {
+
3367 let offsetKey = try _modelKey.set(value: key)
+
3368 _modelKey.fbeShift(size: offsetKey)
+
3369 _modelValue.fbeShift(size: offsetKey)
+
3370 let offsetValue = try _modelValue.set(value: value)
+
3371 _modelKey.fbeShift(size: offsetValue)
+
3372 _modelValue.fbeShift(size: offsetValue)
+
3373 size += offsetKey + offsetValue
+
3374 }
+
3375 return size
+
3376 }
+
3377}
+
3378)CODE";
+
3379
+
3380 std::string key_type_name = IsPackageType(key_type) ? key_type : (domain + package + "." + key_type);
+
3381 std::string value_type_name = IsPackageType(value_type) ? value_type : (domain + package + "." + value_type);
+
3382
+
3383 // Prepare code template
+
3384 code = std::regex_replace(code, std::regex("_DOMAIN_"), domain);
+
3385 code = std::regex_replace(code, std::regex("_KEY_NAME_"), key_name);
+
3386 code = std::regex_replace(code, std::regex("_KEY_TYPE_"), key_type_name);
+
3387 code = std::regex_replace(code, std::regex("_KEY_MODEL_"), key_model);
+
3388 code = std::regex_replace(code, std::regex("_VALUE_NAME_"), value_name);
+
3389 code = std::regex_replace(code, std::regex("_VALUE_TYPE_"), value_type_name);
+
3390 code = std::regex_replace(code, std::regex("_VALUE_MODEL_"), value_model);
+
3391 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
3392
+
3393 Write(code);
+
3394
+
3395 // Generate footer
+
3396 GenerateFooter();
+
3397
+
3398 // Store the file
+
3399 WriteEnd();
+
3400 Store(file);
+
3401}
+
3402
+
3403void GeneratorSwift::GenerateFBEFinalModelEnumFlags(const std::string& domain, const std::string& package, const std::string& name, const std::string& type)
+
3404{
+
3405 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "Fbe";
+
3406
+
3407 // Create package path
+
3408 CppCommon::Directory::CreateTree(path);
+
3409
+
3410 // Generate the file
+
3411 CppCommon::Path file = path / ("FinalModel" + name + ".swift");
+
3412 WriteBegin();
+
3413
+
3414 // Generate headers
+
3415 GenerateHeader(CppCommon::Path(_input).filename().string());
+
3416 GenerateImports(domain, "Fbe");
+
3417
+
3418 std::string code = R"CODE(
+
3419// Fast Binary Encoding _NAME_ final model
+
3420public class FinalModel_NAME_: FinalModel {
+
3421
+
3422 public var _buffer: Buffer
+
3423 public var _offset: Int
+
3424
+
3425 // Final size
+
3426 public let fbeSize: Int = _SIZE_
+
3427
+
3428 public init(buffer: Buffer = Buffer(), offset: Int = 0) {
+
3429 _buffer = buffer
+
3430 _offset = offset
+
3431 }
+
3432
+
3433 // Get the allocation size
+
3434 public func fbeAllocationSize(value: _NAME_) -> Int { fbeSize }
+
3435
+
3436 public func verify() -> Int {
+
3437 if _buffer.offset + fbeOffset + fbeSize > _buffer.size {
+
3438 return Int.max
+
3439 }
+
3440
+
3441 return fbeSize
+
3442 }
+
3443
+
3444 // Get the value
+
3445 public func get(size: inout Size) -> _NAME_ {
+
3446 if _buffer.offset + fbeOffset + fbeSize > _buffer.size {
+
3447 return _NAME_()
+
3448 }
+
3449
+
3450 size.value = fbeSize
+
3451 return _NAME_(value: _READ_(offset: fbeOffset))
+
3452 }
+
3453
+
3454 // Set the value
+
3455 public func set(value: _NAME_) throws -> Int {
+
3456 if _buffer.offset + fbeOffset + fbeSize > _buffer.size {
+
3457 assertionFailure("Model is broken!")
+
3458 return 0
+
3459 }
+
3460
+
3461 write(offset: fbeOffset, value: value.raw)
+
3462 return fbeSize
+
3463 }
+
3464}
+
3465)CODE";
+
3466
+
3467 // Prepare code template
+
3468 code = std::regex_replace(code, std::regex("_DOMAIN_"), domain);
+
3469 code = std::regex_replace(code, std::regex("_PACKAGE_"), package);
+
3470 code = std::regex_replace(code, std::regex("_NAME_"), name);
+
3471 code = std::regex_replace(code, std::regex("_SIZE_"), ConvertEnumSize(type));
+
3472 code = std::regex_replace(code, std::regex("_READ_"), ConvertEnumRead(type));
+
3473 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
3474
+
3475 Write(code);
+
3476
+
3477 // Generate footer
+
3478 GenerateFooter();
+
3479
+
3480 // Store the file
+
3481 WriteEnd();
+
3482 Store(file);
+
3483}
+
3484
+
3485void GeneratorSwift::GenerateFBESender(const std::string& domain, const std::string& package)
+
3486{
+
3487 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
3488
+
3489 // Generate the file
+
3490 CppCommon::Path file = path / "SenderProtocol.swift";
+
3491 WriteBegin();
+
3492
+
3493 // Generate headers
+
3494 GenerateHeader("FBE");
+
3495 GenerateImports("", "Foundation");
+
3496
+
3497 std::string code = R"CODE(
+
3498// Fast Binary Encoding base sender
+
3499public protocol SenderProtocol: class {
+
3500
+
3501 // Get the bytes buffer
+
3502 var buffer: Buffer { get set }
+
3503
+
3504 // Get the final protocol flag
+
3505 var final: Bool { get set }
+
3506}
+
3507
+
3508public extension SenderProtocol {
+
3509
+
3510 func build(with final: Bool) {
+
3511 self.final = final
+
3512 }
+
3513
+
3514 func build(with buffer: Buffer, final: Bool) {
+
3515 self.buffer = buffer
+
3516 self.final = final
+
3517 }
+
3518
+
3519 // Reset the sender buffer
+
3520 func reset() { buffer.reset() }
+
3521
+
3522 // Send serialized buffer.
+
3523 // Direct call of the method requires knowledge about internals of FBE models serialization.
+
3524 // Use it with care!
+
3525 func sendSerialized(listener: SenderListener, serialized: Int) throws -> Int {
+
3526 if serialized <= 0 {
+
3527 assertionFailure("Invalid size of the serialized buffer!")
+
3528 return 0
+
3529 }
+
3530
+
3531 // Shift the send buffer
+
3532 buffer.shift(offset: serialized)
+
3533
+
3534 // Send the value
+
3535 let sent = try listener.onSend(buffer: buffer.data, offset: 0, size: buffer.size)
+
3536 try _ = buffer.remove(offset: 0, size: sent)
+
3537 return sent
+
3538 }
+
3539}
+
3540)CODE";
+
3541
+
3542 // Prepare code template
+
3543 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
3544
+
3545 Write(code);
+
3546
+
3547 // Generate footer
+
3548 GenerateFooter();
+
3549
+
3550 // Store the file
+
3551 WriteEnd();
+
3552 Store(file);
+
3553}
+
3554
+
3555void GeneratorSwift::GenerateFBEReceiver(const std::string& domain, const std::string& package)
+
3556{
+
3557 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
3558
+
3559 // Generate the file
+
3560 CppCommon::Path file = path / "ReceiverProtocol.swift";
+
3561 WriteBegin();
+
3562
+
3563 // Generate headers
+
3564 GenerateHeader("FBE");
+
3565 GenerateImports("", "Foundation");
+
3566
+
3567 std::string code = R"CODE(
+
3568// Fast Binary Encoding base receiver
+
3569public protocol ReceiverProtocol: class {
+
3570
+
3571 // Get the bytes buffer
+
3572 var buffer: Buffer { get set }
+
3573
+
3574 // Get the final protocol flag
+
3575 var final: Bool { get set }
+
3576
+
3577 // Receive message handler
+
3578 func onReceive(type: Int, buffer: Data, offset: Int, size: Int) -> Bool
+
3579}
+
3580
+
3581public extension ReceiverProtocol {
+
3582
+
3583 func build(final: Bool) {
+
3584 self.final = final
+
3585 }
+
3586
+
3587 func build(with buffer: Buffer, final: Bool) {
+
3588 self.buffer = buffer
+
3589 self.final = final
+
3590 }
+
3591
+
3592 // Reset the receiver buffer
+
3593 func reset() { buffer.reset() }
+
3594
+
3595 // Receive data
+
3596 func receive(buffer: Buffer) throws { try receive(buffer: buffer, offset: 0, size: buffer.size) }
+
3597
+
3598 func receive(buffer: Buffer, offset: Int, size: Int) throws {
+
3599 // print("receive start: \‍(self.buffer.data.count)")
+
3600 defer {
+
3601 // print("receive end: \‍(self.buffer.data.count)")
+
3602 }
+
3603 assert((offset + size) <= buffer.data.count, "Invalid offset & size!")
+
3604 if (offset + size) > buffer.data.count {
+
3605 throw NSError()
+
3606 }
+
3607
+
3608 if size == 0 {
+
3609 return
+
3610 }
+
3611
+
3612 // Storage buffer
+
3613 var offset0 = self.buffer.offset
+
3614 var offset1 = self.buffer.size
+
3615 var size1 = self.buffer.size
+
3616
+
3617 // Receive buffer
+
3618 var offset2: Int = 0
+
3619
+
3620 // While receive buffer is available to handle...
+
3621 while offset2 < size {
+
3622 var messageBuffer: Buffer? = nil
+
3623 var messageOffset: Int = 0
+
3624 var messageSize: Int = 0
+
3625
+
3626 // Try to receive message size
+
3627 var messageSizeCopied = false
+
3628 var messageSizeFound = false
+
3629 while !messageSizeFound {
+
3630 // Look into the storage buffer
+
3631 if offset0 < size1 {
+
3632 var count = min(size1 - offset0, 4)
+
3633 if count == 4 {
+
3634 messageSizeCopied = true
+
3635 messageSizeFound = true
+
3636 messageSize = Int(Buffer.readUInt32(buffer: self.buffer, offset: offset0))
+
3637 offset0 += 4
+
3638 break
+
3639 } else {
+
3640 // Fill remaining data from the receive buffer
+
3641 if offset2 < size {
+
3642 count = min(size - offset2, 4 - count)
+
3643
+
3644 // Allocate and refresh the storage buffer
+
3645 try _ = self.buffer.allocate(size: count)
+
3646 size1 += count
+
3647
+
3648 self.buffer.data[offset1..<offset1 + count] = buffer.data[(offset + offset2)..<(offset + offset2) + count]
+
3649 offset1 += count
+
3650 offset2 += count
+
3651 continue
+
3652 } else {
+
3653 break
+
3654 }
+
3655 }
+
3656 }
+
3657
+
3658 // Look into the receive buffer
+
3659 if offset2 < size {
+
3660 let count = min(size - offset2, 4)
+
3661 if count == 4 {
+
3662 messageSizeFound = true
+
3663 messageSize = Int(Buffer.readUInt32(buffer: buffer, offset: offset + offset2))
+
3664 offset2 += 4
+
3665 break
+
3666 } else {
+
3667 // Allocate and refresh the storage buffer
+
3668 try _ = self.buffer.allocate(size: count)
+
3669 size1 += count
+
3670
+
3671 self.buffer.data[offset1..<offset1 + count] = buffer.data[(offset + offset2)..<(offset + offset2) + count]
+
3672 offset1 += count
+
3673 offset2 += count
+
3674 continue
+
3675 }
+
3676 } else {
+
3677 break
+
3678 }
+
3679 }
+
3680
+
3681 if !messageSizeFound {
+
3682 return
+
3683 }
+
3684
+
3685 // Check the message full size
+
3686 let minSize = {
+
3687 return final ? 4 + 4 : 4 + 4 + 4 + 4
+
3688 }()
+
3689 assert(messageSize >= minSize, "Invalid receive data!")
+
3690 if messageSize < minSize {
+
3691 return
+
3692 }
+
3693
+
3694 // Try to receive message body
+
3695 var messageFound = false
+
3696 while !messageFound {
+
3697 // Look into the storage buffer
+
3698 if offset0 < size1 {
+
3699 var count = min(size1 - offset0, messageSize - 4)
+
3700 if count == (messageSize - 4) {
+
3701 messageFound = true
+
3702 messageBuffer = self.buffer
+
3703 messageOffset = offset0 - 4
+
3704 offset0 += messageSize - 4
+
3705 break
+
3706 } else {
+
3707 // Fill remaining data from the receive buffer
+
3708 if offset2 < size {
+
3709 // Copy message size into the storage buffer
+
3710 if !messageSizeCopied {
+
3711 // Allocate and refresh the storage buffer
+
3712 try _ = self.buffer.allocate(size: 4)
+
3713 size1 += 4
+
3714
+
3715 Buffer.write(buffer: &self.buffer, offset: offset0, value: UInt32(messageSize))
+
3716 offset0 += 4
+
3717 offset1 += 4
+
3718
+
3719 messageSizeCopied = true
+
3720 }
+
3721
+
3722 count = min(size - offset2, messageSize - 4 - count)
+
3723
+
3724 // Allocate and refresh the storage buffer
+
3725 try _ = self.buffer.allocate(size: count)
+
3726 size1 += count
+
3727
+
3728 self.buffer.data[offset1..<offset1 + count] = buffer.data[(offset + offset2)..<(offset + offset2) + count]
+
3729 offset1 += count
+
3730 offset2 += count
+
3731 continue
+
3732 } else {
+
3733 break
+
3734 }
+
3735
+
3736 }
+
3737 }
+
3738
+
3739 // Look into the receive buffer
+
3740 if offset2 < size {
+
3741 let count = min(size - offset2, messageSize - 4)
+
3742 if !messageSizeCopied && (count == (messageSize - 4)) {
+
3743 messageFound = true
+
3744 messageBuffer = buffer
+
3745 messageOffset = offset + offset2 - 4
+
3746 offset2 += messageSize - 4
+
3747 break
+
3748 } else {
+
3749 // Copy message size into the storage buffer
+
3750 if !messageSizeCopied {
+
3751 // Allocate and refresh the storage buffer
+
3752 try _ = self.buffer.allocate(size: 4)
+
3753 size1 += 4
+
3754
+
3755 Buffer.write(buffer: &self.buffer, offset: offset0, value: UInt32(messageSize))
+
3756 offset0 += 4
+
3757 offset1 += 4
+
3758
+
3759 messageSizeCopied = true
+
3760 }
+
3761
+
3762 // Allocate and refresh the storage buffer
+
3763 try _ = self.buffer.allocate(size: count)
+
3764 size1 += count
+
3765 self.buffer.data[offset1..<offset1 + count] = buffer.data[(offset + offset2)..<(offset + offset2) + count]
+
3766 offset1 += count
+
3767 offset2 += count
+
3768 continue
+
3769 }
+
3770 } else {
+
3771 break
+
3772 }
+
3773 }
+
3774
+
3775 if !messageFound {
+
3776 // Copy message size into the storage buffer
+
3777 if !messageSizeCopied {
+
3778 // Allocate and refresh the storage buffer
+
3779 try _ = self.buffer.allocate(size: 4)
+
3780 size1 += 4
+
3781
+
3782 Buffer.write(buffer: &self.buffer, offset: offset0, value: UInt32(messageSize))
+
3783 offset0 += 4
+
3784 offset1 += 4
+
3785
+
3786 //@Suppress("UNUSED_VALUE")
+
3787 messageSizeCopied = true
+
3788 }
+
3789 return
+
3790 }
+
3791
+
3792 if let messageBuffer = messageBuffer {
+
3793 let fbeStructSize: Int
+
3794 let fbeStructType: Int
+
3795
+
3796 // Read the message parameters
+
3797 if final {
+
3798 fbeStructSize = Int(Buffer.readUInt32(buffer: messageBuffer, offset: messageOffset))
+
3799 fbeStructType = Int(Buffer.readUInt32(buffer: messageBuffer, offset: messageOffset + 4))
+
3800 } else {
+
3801 let fbeStructOffset = Int(Buffer.readUInt32(buffer: messageBuffer, offset: messageOffset + 4))
+
3802 fbeStructSize = Int(Buffer.readUInt32(buffer: messageBuffer, offset: messageOffset + fbeStructOffset))
+
3803 fbeStructType = Int(Buffer.readUInt32(buffer: messageBuffer, offset: messageOffset + fbeStructOffset + 4))
+
3804 }
+
3805
+
3806 // Handle the message
+
3807 _ = onReceive(type: fbeStructType, buffer: messageBuffer.data, offset: messageOffset, size: messageSize)
+
3808 }
+
3809
+
3810 // Reset the storage buffer
+
3811 self.buffer.reset()
+
3812
+
3813 // Refresh the storage buffer
+
3814 offset0 = self.buffer.offset
+
3815 offset1 = self.buffer.size
+
3816 size1 = self.buffer.size
+
3817 }
+
3818 }
+
3819}
+
3820)CODE";
+
3821
+
3822 // Prepare code template
+
3823 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
3824
+
3825 Write(code);
+
3826
+
3827 // Generate footer
+
3828 GenerateFooter();
+
3829
+
3830 // Store the file
+
3831 WriteEnd();
+
3832 Store(file);
+
3833}
+
3834
+
3835void GeneratorSwift::GenerateFBEReceiverListener(const std::string& domain, const std::string& package)
+
3836{
+
3837 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
3838
+
3839 // Generate the file
+
3840 CppCommon::Path file = path / "Listeners.swift";
+
3841 WriteBegin();
+
3842
+
3843 // Generate headers
+
3844 GenerateHeader("FBE");
+
3845 GenerateImports("", "Foundation");
+
3846
+
3847 std::string code = R"CODE(
+
3848public protocol LogListener {
+
3849 // Enable/Disable logging
+
3850 var logging: Bool { get set }
+
3851}
+
3852
+
3853// Fast Binary Encoding log listener
+
3854public protocol ReceiveLogListener: LogListener {
+
3855
+
3856 // Receive log message handler
+
3857 func onReceiveLog(message: String)
+
3858}
+
3859
+
3860public extension ReceiveLogListener {
+
3861 func onReceiveLog(message: String) {}
+
3862}
+
3863
+
3864public protocol SenderListener: LogListener {
+
3865 // Send message handler
+
3866 func onSend(buffer: Data, offset: Int, size: Int) throws -> Int
+
3867
+
3868 // Send log message handler
+
3869 func onSendLog(message: String)
+
3870}
+
3871
+
3872public extension SenderListener {
+
3873 func onSend(buffer: Data, offset: Int, size: Int) throws -> Int { return 0 }
+
3874 func onSendLog(message: String) {}
+
3875}
+
3876)CODE";
+
3877
+
3878 // Prepare code template
+
3879 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
3880
+
3881 Write(code);
+
3882
+
3883 // Generate footer
+
3884 GenerateFooter();
+
3885
+
3886 // Store the file
+
3887 WriteEnd();
+
3888 Store(file);
+
3889}
+
3890
+
3891void GeneratorSwift::GenerateFBEClient(const std::string& domain, const std::string& package)
+
3892{
+
3893 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
3894
+
3895 // Generate the file
+
3896 CppCommon::Path file = path / "ClientProtocol.swift";
+
3897 WriteBegin();
+
3898
+
3899 // Generate headers
+
3900 GenerateHeader("FBE");
+
3901 GenerateImports("", "Foundation");
+
3902
+
3903 std::string code = R"CODE(
+
3904// Fast Binary Encoding base client
+
3905public protocol ClientProtocol: class {
+
3906
+
3907 // Get the send bytes buffer
+
3908 var sendBuffer: Buffer { get set }
+
3909
+
3910 // Get the receive bytes buffer
+
3911 var receiveBuffer: Buffer { get set }
+
3912
+
3913 // Get the final protocol flag
+
3914 var final: Bool { get set }
+
3915
+
3916 // Receive message handler
+
3917 func onReceive(type: Int, buffer: Data, offset: Int, size: Int) -> Bool
+
3918}
+
3919
+
3920public extension ClientProtocol {
+
3921
+
3922 func build(with final: Bool) {
+
3923 self.final = final
+
3924 }
+
3925
+
3926 func build(with sendBuffer: Buffer, receiveBuffer: Buffer, final: Bool) {
+
3927 self.sendBuffer = sendBuffer
+
3928 self.receiveBuffer = receiveBuffer
+
3929 self.final = final
+
3930 }
+
3931
+
3932 func reset() {
+
3933 sendBuffer.reset()
+
3934 receiveBuffer.reset()
+
3935 }
+
3936
+
3937 // Send serialized buffer.
+
3938 // Direct call of the method requires knowledge about internals of FBE models serialization.
+
3939 // Use it with care!
+
3940 func sendSerialized(listener: SenderListener, serialized: Int) throws -> Int {
+
3941 assert(serialized > 0, "Invalid size of the serialized buffer!")
+
3942
+
3943 if serialized <= 0 {
+
3944 return 0
+
3945 }
+
3946
+
3947 // Shift the send buffer
+
3948 sendBuffer.shift(offset: serialized)
+
3949
+
3950 // Send the value
+
3951 let sent = try listener.onSend(buffer: sendBuffer.data, offset: 0, size: sendBuffer.size)
+
3952 try sendBuffer.remove(offset: 0, size: sent)
+
3953 return sent
+
3954 }
+
3955
+
3956 // Receive data
+
3957 func receive(buffer: Data) throws {
+
3958 let buffer = Buffer(buffer: buffer)
+
3959 try receive(buffer: buffer, offset: 0, size: buffer.data.count)
+
3960 }
+
3961
+
3962 func receive(buffer: Buffer, offset: Int, size: Int) throws {
+
3963 assert((offset + size) <= buffer.data.count, "Invalid offset & size!")
+
3964
+
3965 if (offset + size) > buffer.data.count {
+
3966 throw NSException(name: .invalidArgumentException, reason: "Invalid allocation size!") as! Error
+
3967 }
+
3968
+
3969 if size == 0 {
+
3970 return
+
3971 }
+
3972
+
3973 // Storage buffer
+
3974 var offset0 = self.receiveBuffer.offset
+
3975 var offset1 = self.receiveBuffer.size
+
3976 var size1 = self.receiveBuffer.size
+
3977
+
3978 // Receive buffer
+
3979 var offset2: Int = 0
+
3980
+
3981 // While receive buffer is available to handle...
+
3982 while offset2 < size {
+
3983 var messageBuffer: Buffer?
+
3984 var messageOffset: Int = 0
+
3985 var messageSize: Int = 0
+
3986
+
3987 // Try to receive message size
+
3988 var messageSizeCopied = false
+
3989 var messageSizeFound = false
+
3990 while !messageSizeFound {
+
3991 // Look into the storage buffer
+
3992 if offset0 < size1 {
+
3993 var count = min(size1 - offset0, 4)
+
3994 if count == 4 {
+
3995 messageSizeCopied = true
+
3996 messageSizeFound = true
+
3997 messageSize = Int(Buffer.readUInt32(buffer: self.receiveBuffer, offset: offset0))
+
3998 offset0 += 4
+
3999 break
+
4000 } else {
+
4001 // Fill remaining data from the receive buffer
+
4002 if offset2 < size {
+
4003 count = min(size - offset2, 4 - count)
+
4004
+
4005 // Allocate and refresh the storage buffer
+
4006 try _ = self.receiveBuffer.allocate(size: count)
+
4007 size1 += count
+
4008
+
4009 self.receiveBuffer.data[offset1..<offset1 + count] = buffer.data[(offset + offset2)..<(offset + offset2) + count]
+
4010 offset1 += count
+
4011 offset2 += count
+
4012 continue
+
4013 } else {
+
4014 break
+
4015 }
+
4016 }
+
4017 }
+
4018
+
4019 // Look into the receive buffer
+
4020 if offset2 < size {
+
4021 let count = min(size - offset2, 4)
+
4022 if count == 4 {
+
4023 messageSizeFound = true
+
4024 messageSize = Int(Buffer.readUInt32(buffer: buffer, offset: offset + offset2))
+
4025 offset2 += 4
+
4026 break
+
4027 } else {
+
4028 // Allocate and refresh the storage buffer
+
4029 try _ = self.receiveBuffer.allocate(size: count)
+
4030 size1 += count
+
4031
+
4032 self.receiveBuffer.data[offset1..<offset1 + count] = buffer.data[(offset + offset2)..<(offset + offset2) + count]
+
4033 offset1 += count
+
4034 offset2 += count
+
4035 continue
+
4036 }
+
4037 } else {
+
4038 break
+
4039 }
+
4040
+
4041 }
+
4042
+
4043 if !messageSizeFound {
+
4044 return
+
4045 }
+
4046
+
4047 // Check the message full size
+
4048 let minSize: Int = {
+
4049 return final ? 4 + 4 : 4 + 4 + 4 + 4
+
4050 }()
+
4051
+
4052 assert(messageSize >= minSize, "Invalid receive data!")
+
4053 if messageSize < minSize {
+
4054 return
+
4055 }
+
4056
+
4057 // Try to receive message body
+
4058 var messageFound = false
+
4059 while !messageFound {
+
4060 // Look into the storage buffer
+
4061 if offset0 < size1 {
+
4062 var count = min(size1 - offset0, messageSize - 4)
+
4063 if count == (messageSize - 4) {
+
4064 messageFound = true
+
4065 messageBuffer = self.receiveBuffer
+
4066 messageOffset = offset0 - 4
+
4067 offset0 += messageSize - 4
+
4068 break
+
4069 } else {
+
4070 // Fill remaining data from the receive buffer
+
4071 if offset2 < size {
+
4072 // Copy message size into the storage buffer
+
4073 if !messageSizeCopied {
+
4074 // Allocate and refresh the storage buffer
+
4075 try _ = self.receiveBuffer.allocate(size: 4)
+
4076 size1 += 4
+
4077 Buffer.write(buffer: &self.receiveBuffer, offset: offset0, value: UInt32(messageSize))
+
4078 offset0 += 4
+
4079 offset1 += 4
+
4080
+
4081 messageSizeCopied = true
+
4082 }
+
4083
+
4084 count = min(size - offset2, messageSize - 4 - count)
+
4085
+
4086 // Allocate and refresh the storage buffer
+
4087 try _ = self.receiveBuffer.allocate(size: count)
+
4088 size1 += count
+
4089
+
4090 self.receiveBuffer.data[offset1..<offset1 + count] = buffer.data[(offset + offset2)..<(offset + offset2) + count]
+
4091 offset1 += count
+
4092 offset2 += count
+
4093 continue
+
4094 } else {
+
4095 break
+
4096 }
+
4097 }
+
4098 }
+
4099
+
4100 // Look into the receive buffer
+
4101 if offset2 < size {
+
4102 let count = min(size - offset2, messageSize - 4)
+
4103 if !messageSizeCopied && (count == (messageSize - 4)) {
+
4104 messageFound = true
+
4105 messageBuffer = buffer
+
4106 messageOffset = offset + offset2 - 4
+
4107 offset2 += messageSize - 4
+
4108 break
+
4109 } else {
+
4110 // Copy message size into the storage buffer
+
4111 if !messageSizeCopied {
+
4112 // Allocate and refresh the storage buffer
+
4113 try _ = self.receiveBuffer.allocate(size: 4)
+
4114 size1 += 4
+
4115
+
4116 Buffer.write(buffer: &self.receiveBuffer, offset: offset0, value: UInt32(messageSize))
+
4117 offset0 += 4
+
4118 offset1 += 4
+
4119
+
4120 messageSizeCopied = true
+
4121 }
+
4122
+
4123 // Allocate and refresh the storage buffer
+
4124 try _ = self.receiveBuffer.allocate(size: count)
+
4125 size1 += count
+
4126
+
4127 self.receiveBuffer.data[offset1..<offset1 + count] = buffer.data[(offset + offset2)..<(offset + offset2) + count]
+
4128 offset1 += count
+
4129 offset2 += count
+
4130 continue
+
4131 }
+
4132 } else {
+
4133 break
+
4134 }
+
4135 }
+
4136
+
4137 if !messageFound {
+
4138 // Copy message size into the storage buffer
+
4139 if !messageSizeCopied {
+
4140 // Allocate and refresh the storage buffer
+
4141 try _ = self.receiveBuffer.allocate(size: 4)
+
4142 size1 += 4
+
4143
+
4144 Buffer.write(buffer: &self.receiveBuffer, offset: offset0, value: UInt32(messageSize))
+
4145 offset0 += 4
+
4146 offset1 += 4
+
4147
+
4148 messageSizeCopied = true
+
4149 }
+
4150 return
+
4151 }
+
4152
+
4153 if let messageBuffer = messageBuffer {
+
4154 let fbeStructSize: Int
+
4155 let fbeStructType: Int
+
4156
+
4157 // Read the message parameters
+
4158 if final {
+
4159 fbeStructSize = Int(Buffer.readUInt32(buffer: messageBuffer, offset: messageOffset))
+
4160 fbeStructType = Int(Buffer.readUInt32(buffer: messageBuffer, offset: messageOffset + 4))
+
4161 } else {
+
4162 let fbeStructOffset = Int(Buffer.readUInt32(buffer: messageBuffer, offset: messageOffset + 4))
+
4163 fbeStructSize = Int(Buffer.readUInt32(buffer: messageBuffer, offset: messageOffset + fbeStructOffset))
+
4164 fbeStructType = Int(Buffer.readUInt32(buffer: messageBuffer, offset: messageOffset + fbeStructOffset + 4))
+
4165 }
+
4166
+
4167 // Handle the message
+
4168 _ = onReceive(type: fbeStructType, buffer: messageBuffer.data, offset: messageOffset, size: messageSize)
+
4169 }
+
4170
+
4171 // Reset the storage buffer
+
4172 self.receiveBuffer.reset()
+
4173
+
4174 // Refresh the storage buffer
+
4175 offset0 = self.receiveBuffer.offset
+
4176 offset1 = self.receiveBuffer.size
+
4177 size1 = self.receiveBuffer.size
+
4178 }
+
4179 }
+
4180}
+
4181)CODE";
+
4182
+
4183 // Prepare code template
+
4184 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
4185
+
4186 Write(code);
+
4187
+
4188 // Generate footer
+
4189 GenerateFooter();
+
4190
+
4191 // Store the file
+
4192 WriteEnd();
+
4193 Store(file);
+
4194}
+
4195
+
4196void GeneratorSwift::GenerateContainers(const std::shared_ptr<Package>& p, bool final)
+
4197{
+
4198 std::string domain = ConvertDomain(p);
+
4199 std::string package = ConvertPackage(p);
+
4200 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
4201
+
4202 // Create package path
+
4203 CppCommon::Directory::CreateTree(path);
+
4204
+
4205 if (p->body)
+
4206 {
+
4207 // Check all structs in the package
+
4208 for (const auto& s : p->body->structs)
+
4209 {
+
4210 if (s->body)
+
4211 {
+
4212 // Check all fields in the struct
+
4213 for (const auto& field : s->body->fields)
+
4214 {
+
4215 if (field->array)
+
4216 {
+
4217 if (final)
+
4218 GenerateFBEFinalModelArray(domain, p, (field->optional ? "Optional" : "") + ConvertTypeFieldName(*field->type), ConvertTypeFieldType(domain, *field->type, field->optional), *field->type, field->optional, ConvertTypeFieldDeclaration(domain, *field->type, field->optional, final));
+
4219 else
+
4220 GenerateFBEFieldModelArray(domain, p, (field->optional ? "Optional" : "") + ConvertTypeFieldName(*field->type), ConvertTypeFieldType(domain, *field->type, field->optional), *field->type, field->optional, ConvertTypeFieldDeclaration(domain, *field->type, field->optional, final));
+
4221 }
+
4222 if (field->vector || field->list || field->set)
+
4223 {
+
4224 if (final)
+
4225 GenerateFBEFinalModelVector(domain, p, (field->optional ? "Optional" : "") + ConvertTypeFieldName(*field->type), ConvertTypeFieldType(domain, *field->type, field->optional), ConvertTypeFieldDeclaration(domain, *field->type, field->optional, final));
+
4226 else {
+
4227 GenerateFBEFieldModelVector(domain, p, (field->optional ? "Optional" : "") + ConvertTypeFieldName(*field->type), ConvertTypeFieldType(domain, *field->type, field->optional), ConvertTypeFieldDeclaration(domain, *field->type, field->optional, final));
+
4228 }
+
4229 }
+
4230 if (field->map || field->hash)
+
4231 {
+
4232 if (final)
+
4233 GenerateFBEFinalModelMap(domain, p, ConvertTypeFieldName(*field->key), ConvertTypeFieldType(domain, *field->key, false), ConvertTypeFieldDeclaration(domain, *field->key, false, final), (field->optional ? "Optional" : "") + ConvertTypeFieldName(*field->type), ConvertTypeFieldType(domain, *field->type, field->optional), ConvertTypeFieldDeclaration(domain, *field->type, field->optional, final));
+
4234 else
+
4235 GenerateFBEFieldModelMap(domain, p, ConvertTypeFieldName(*field->key), ConvertTypeFieldType(domain, *field->key, false), ConvertTypeFieldDeclaration(domain, *field->key, false, final), (field->optional ? "Optional" : "") + ConvertTypeFieldName(*field->type), ConvertTypeFieldType(domain, *field->type, field->optional), ConvertTypeFieldDeclaration(domain, *field->type, field->optional, final));
+
4236 }
+
4237 if (field->optional)
+
4238 {
+
4239 if (final)
+
4240 GenerateFBEFinalModelOptional(domain, p, ConvertTypeFieldName(*field->type), ConvertTypeFieldType(domain, *field->type, field->optional), ConvertTypeFieldDeclaration(domain, *field->type, false, final));
+
4241 else
+
4242 GenerateFBEFieldModelOptional(domain, p, ConvertTypeFieldName(*field->type), ConvertTypeFieldType(domain, *field->type, field->optional), ConvertTypeFieldDeclaration(domain, *field->type, false, final));
+
4243 }
+
4244 }
+
4245 }
+
4246 }
+
4247 }
+
4248}
+
4249
+
4250void GeneratorSwift::GeneratePackage(const std::shared_ptr<Package>& p)
+
4251{
+
4252 std::string domain = ConvertDomain(p);
+
4253 std::string package = ConvertPackage(p);
+
4254 CppCommon::Path path = CppCommon::Path(_output) / CreatePackagePath(domain, package);
+
4255
+
4256 // Create package path
+
4257 CppCommon::Directory::CreateTree(path);
+
4258
+
4259 CppCommon::Path packagePath = CppCommon::Path(_output) / package;
+
4260
+
4261 // Create FBE package path
+
4262 CppCommon::Directory::CreateTree(packagePath);
+
4263
+
4264 // Generate the file
+
4265 CppCommon::Path file = packagePath / "Package.swift";
+
4266 WriteBegin();
+
4267
+
4268 std::string code = R"CODE(// swift-tools-version:5.1
+
4269// The swift-tools-version declares the minimum version of Swift required to build this package.
+
4270
+
4271import PackageDescription
+
4272
+
4273let package = Package(
+
4274 name: "_NAME_",
+
4275 products: [
+
4276 // Products define the executables and libraries produced by a package, and make them visible to other packages.
+
4277 .library(
+
4278 name: "_NAME_",
+
4279 targets: ["_NAME_"])
+
4280 ],
+
4281 dependencies: [
+
4282 // Dependencies declare other packages that this package depends on.
+
4283 _DEPENDENCIES_RES_
+
4284 ],
+
4285 targets: [
+
4286 // Targets are the basic building blocks of a package. A target can define a module or a test suite.
+
4287 // Targets can depend on other targets in this package, and on products in packages which this package depends on.
+
4288 .target(
+
4289 name: "_NAME_",
+
4290 dependencies: [_DEPENDENCIES_]),
+
4291 ]
+
4292)
+
4293)CODE";
+
4294
+
4295 std::string dependenciesRes = std::string(".package(path: \"../") + "Fbe" + std::string("\")");
+
4296 if (p->import)
+
4297 for (const auto& import : p->import->imports)
+
4298 dependenciesRes = dependenciesRes + std::string(",\n .package(path: \"../") + ConvertPackageName(*import) + std::string("\")");
+
4299
+
4300 std::string dependencies = std::string("\"") + domain + "Fbe" + std::string("\"");
+
4301 if (p->import)
+
4302 for (const auto& import : p->import->imports)
+
4303 dependencies = dependencies + std::string(", \"") + domain + ConvertPackageName(*import) + std::string("\"");
+
4304
+
4305 // Prepare code template
+
4306 code = std::regex_replace(code, std::regex("_NAME_"), domain + package);
+
4307 code = std::regex_replace(code, std::regex("_DEPENDENCIES_RES_"), dependenciesRes);
+
4308 code = std::regex_replace(code, std::regex("_DEPENDENCIES_"), dependencies);
+
4309 code = std::regex_replace(code, std::regex("\n"), EndLine());
+
4310 Write(code);
+
4311
+
4312 // Generate footer
+
4313 GenerateFooter();
+
4314
+
4315 // Store the file
+
4316 WriteEnd();
+
4317 Store(file);
+
4318
+
4319 // Generate namespace
+
4320 if (p->body)
+
4321 {
+
4322 // Generate child enums
+
4323 for (const auto& child_e : p->body->enums)
+
4324 GenerateEnum(p, child_e, path);
+
4325
+
4326 // Generate child flags
+
4327 for (const auto& child_f : p->body->flags)
+
4328 GenerateFlags(p, child_f, path);
+
4329
+
4330 // Generate child structs
+
4331 for (const auto& child_s : p->body->structs)
+
4332 GenerateStruct(p, child_s, path);
+
4333 }
+
4334
+
4335 // Generate containers
+
4336 GenerateContainers(p, false);
+
4337 if (Final())
+
4338 GenerateContainers(p, true);
+
4339
+
4340 // Generate protocol
+
4341 if (Proto())
+
4342 {
+
4343 // Generate protocol version
+
4344 GenerateProtocolVersion(p);
+
4345
+
4346 // Generate sender & receiver
+
4347 GenerateSender(p, false);
+
4348 GenerateReceiver(p, false);
+
4349 GenerateReceiverListener(p, false);
+
4350 GenerateProxy(p, false);
+
4351 GenerateProxyListener(p, false);
+
4352 GenerateClient(p, false);
+
4353 if (Final())
+
4354 {
+
4355 GenerateSender(p, true);
+
4356 GenerateReceiver(p, true);
+
4357 GenerateReceiverListener(p, true);
+
4358 GenerateClient(p, true);
+
4359 }
+
4360 }
+
4361}
+
4362
+
4363void GeneratorSwift::GenerateEnum(const std::shared_ptr<Package>& p, const std::shared_ptr<EnumType>& e, const CppCommon::Path& path)
+
4364{
+
4365 std::string enum_name = *e->name + "Enum";
+
4366
+
4367 // Generate the output file
+
4368 CppCommon::Path output = path / (enum_name + ".swift");
+
4369 WriteBegin();
+
4370
+
4371 // Generate enum header
+
4372 GenerateHeader(CppCommon::Path(_input).filename().string());
+
4373 GenerateImports("", "Foundation");
+
4374
+
4375 std::string enum_type = (e->base && !e->base->empty()) ? *e->base : "int32";
+
4376 std::string enum_base_type = ConvertEnumType(enum_type);
+
4377 std::string enum_mapping_type = ConvertEnumBase(enum_type);
+
4378 std::string enum_to = ConvertEnumTo(enum_type);
+
4379
+
4380 // Generate enum body
+
4381 WriteLine();
+
4382 WriteLineIndent("public enum " + enum_name + " {");
+
4383 Indent(1);
+
4384 WriteLineIndent("typealias RawValue = " + enum_mapping_type);
+
4385 if (e->body)
+
4386 {
+
4387 for (const auto& value : e->body->values)
+
4388 {
+
4389 WriteIndent("case " + *value->name);
+
4390 WriteLine();
+
4391 }
+
4392 WriteLine();
+
4393 }
+
4394
+
4395 if (e->body)
+
4396 {
+
4397 int index = 0;
+
4398 std::string last = ConvertEnumConstant(enum_type, enum_type, (enum_type == "char" ? "\"0\"" : "0"), false);
+
4399 WriteLineIndent("var rawValue: RawValue {");
+
4400 Indent(1);
+
4401 WriteLineIndent("switch self {");
+
4402 for (const auto& value : e->body->values)
+
4403 {
+
4404 WriteIndent("case ." + *value->name + ": return ");
+
4405 if (value->value)
+
4406 {
+
4407 if (value->value->constant && !value->value->constant->empty())
+
4408 {
+
4409 index = 0;
+
4410 last = ConvertEnumConstant(enum_type, enum_type, *value->value->constant, false);
+
4411 Write(last + " + " + std::to_string(index++));
+
4412 }
+
4413 else if (value->value->reference && !value->value->reference->empty())
+
4414 {
+
4415 index = 0;
+
4416 last = ConvertEnumConstant(enum_type, "", *value->value->reference, false);
+
4417 Write(last);
+
4418 }
+
4419 }
+
4420 else
+
4421 Write(last + " + " + std::to_string(index++));
+
4422 WriteLine();
+
4423 }
+
4424 WriteLineIndent("}");
+
4425 Indent(-1);
+
4426 WriteLineIndent("}");
+
4427 WriteLine();
+
4428 }
+
4429
+
4430 // Generate enum constructors
+
4431 if ((enum_type == "char") || (enum_type == "wchar"))
+
4432 WriteLineIndent("init(value: Character) { self = " + enum_name + "(rawValue: NSNumber(value: Int(String(value))!)" + enum_to + " ) }");
+
4433 if (IsUnsignedType(enum_type))
+
4434 {
+
4435 WriteLineIndent("init(value: UInt8) { self = " + enum_name + "(rawValue: NSNumber(value: value)" + enum_to + ") }");
+
4436 WriteLineIndent("init(value: UInt16) { self = " + enum_name + "(rawValue: NSNumber(value: value)" + enum_to + ") }");
+
4437 WriteLineIndent("init(value: UInt32) { self = " + enum_name + "(rawValue: NSNumber(value: value)" + enum_to + ") }");
+
4438 WriteLineIndent("init(value: UInt64) { self = " + enum_name + "(rawValue: NSNumber(value: value)" + enum_to + ") }");
+
4439 }
+
4440 else
+
4441 {
+
4442 WriteLineIndent("init(value: Int8) { self = " + enum_name + "(rawValue: NSNumber(value: value)" + enum_to + ") }");
+
4443 WriteLineIndent("init(value: Int16) { self = " + enum_name + "(rawValue: NSNumber(value: value)" + enum_to + ") }");
+
4444 WriteLineIndent("init(value: Int32) { self = " + enum_name + "(rawValue: NSNumber(value: value)" + enum_to + ") }");
+
4445 WriteLineIndent("init(value: Int64) { self = " + enum_name + "(rawValue: NSNumber(value: value)" + enum_to + ") }");
+
4446 }
+
4447 WriteLineIndent("init(value: " + enum_name + ") { self = " + enum_name + "(rawValue: value.rawValue) }");
+
4448 WriteLineIndent("init(rawValue: " + enum_mapping_type + ") { self = Self.mapValue(value: rawValue)! }");
+
4449
+
4450 // Generate enum description method
+
4451 WriteLine();
+
4452 WriteLineIndent("var description: String {");
+
4453 Indent(1);
+
4454 if (e->body && !e->body->values.empty())
+
4455 {
+
4456 WriteLineIndent("switch self {");
+
4457 for (const auto& value : e->body->values)
+
4458 WriteLineIndent("case ." + *value->name + ":" + " return \"" + *value->name + "\"");
+
4459 WriteLineIndent("}");
+
4460 }
+
4461 else
+
4462 WriteLineIndent("return \"<empty>\"");
+
4463 Indent(-1);
+
4464 WriteLineIndent("}");
+
4465
+
4466 WriteLine();
+
4467 WriteLineIndent("static let rawValuesMap: [RawValue: " + enum_name + "] = {");
+
4468 Indent(1);
+
4469 WriteLineIndent("var value = [RawValue: " + enum_name + "]()");
+
4470 for (const auto& value : e->body->values)
+
4471 WriteLineIndent("value[" + enum_name + "." + *value->name + ".rawValue] = ." + *value->name);
+
4472 WriteLineIndent("return value");
+
4473 Indent(-1);
+
4474 WriteLineIndent("}()");
+
4475
+
4476 // Generate enum mapping
+
4477 WriteLine();
+
4478 WriteLineIndent("static func mapValue(value: " + enum_mapping_type + ") -> " + enum_name + "? {");
+
4479 Indent(1);
+
4480 WriteLineIndent("return rawValuesMap[value]");
+
4481 Indent(-1);
+
4482 WriteLineIndent("}");
+
4483
+
4484 Indent(-1);
+
4485 WriteLineIndent("}");
+
4486
+
4487 // Generate enum footer
+
4488 GenerateFooter();
+
4489
+
4490 // Store the output file
+
4491 WriteEnd();
+
4492 Store(output);
+
4493
+
4494 // Generate enum wrapper class
+
4495 GenerateEnumClass(p, e, path);
+
4496
+
4497 std::string domain = ConvertDomain(p);
+
4498 std::string package = ConvertPackage(p);
+
4499
+
4500 // Generate enum field model
+
4501 GenerateFBEFieldModelEnumFlags(domain, package, *e->name, enum_type);
+
4502
+
4503 // Generate enum final model
+
4504 if (Final())
+
4505 GenerateFBEFinalModelEnumFlags(domain, package, *e->name, enum_type);
+
4506}
+
4507
+
4508void GeneratorSwift::GenerateEnumClass(const std::shared_ptr<Package>& p, const std::shared_ptr<EnumType>& e, const CppCommon::Path& path)
+
4509{
+
4510 std::string enum_name = *e->name;
+
4511 std::string enum_type_name = *e->name + "Enum";
+
4512
+
4513 // Generate the output file
+
4514 CppCommon::Path output = path / (enum_name + ".swift");
+
4515 WriteBegin();
+
4516
+
4517 // Generate enum class header
+
4518 GenerateHeader(CppCommon::Path(_input).filename().string());
+
4519 GenerateImports("", "Foundation");
+
4520
+
4521 std::string enum_type = (e->base && !e->base->empty()) ? *e->base : "int32";
+
4522 std::string enum_base_type = ConvertEnumType(enum_type);
+
4523 std::string enum_to = ConvertEnumTo(enum_type);
+
4524
+
4525 // Generate enum class body
+
4526 WriteLine();
+
4527 if (JSON())
+
4528 WriteLineIndent("public struct " + enum_name + ": Comparable, Hashable, Codable {");
+
4529 else
+
4530 WriteLineIndent("public struct " + enum_name + ": Comparable, Hashable {");
+
4531 Indent(1);
+
4532 WriteLineIndent("typealias RawValue = " + enum_base_type);
+
4533
+
4534 if (e->body)
+
4535 {
+
4536 for (const auto& value : e->body->values)
+
4537 WriteLineIndent("public static let " + *value->name + " = " + enum_name + "(value: " + enum_type_name + "." + *value->name + ")");
+
4538 WriteLine();
+
4539 }
+
4540
+
4541 // Generate enum class value
+
4542 WriteLineIndent("var value: " + enum_type_name + "?");
+
4543 WriteLine();
+
4544
+
4545 // Generate enum raw value
+
4546 WriteLineIndent("public var raw: " + enum_base_type + " { return value!.rawValue }");
+
4547 WriteLine();
+
4548
+
4549 // Generate enum class constructors
+
4550 WriteLineIndent("public init() { setDefault() }");
+
4551 WriteLineIndent("public init(value: " + enum_base_type + ") { setEnum(value: value) }");
+
4552 WriteLineIndent("public init(value: " + enum_type_name + ") { setEnum(value: value) }");
+
4553 WriteLineIndent("public init(value: " + enum_name + ") { setEnum(value: value) }");
+
4554 WriteLine();
+
4555
+
4556 if (JSON())
+
4557 {
+
4558 WriteLineIndent("public init(from decoder: Decoder) throws {");
+
4559 Indent(1);
+
4560 WriteLineIndent("let container = try decoder.singleValueContainer()");
+
4561 WriteLineIndent("setEnum(value: try container.decode(RawValue.self))");
+
4562 Indent(-1);
+
4563 WriteLineIndent("}");
+
4564 }
+
4565
+
4566 // Generate enum class setDefault() method
+
4567 WriteLineIndent("public mutating func setDefault() { setEnum(value: NSNumber(value: 0)" + enum_to + ") }");
+
4568 WriteLine();
+
4569
+
4570 // Generate enum class setEnum() methods
+
4571 WriteLineIndent("public mutating func setEnum(value: " + enum_base_type + ") { self.value = " + enum_type_name + ".mapValue(value: value) }");
+
4572 WriteLineIndent("public mutating func setEnum(value: " + enum_type_name + ") { self.value = value }");
+
4573 WriteLineIndent("public mutating func setEnum(value: " + enum_name + ") { self.value = value.value }");
+
4574
+
4575 // Generate enum class compareTo() method
+
4576 WriteLine();
+
4577 WriteLineIndent("public static func < (lhs: " + enum_name + ", rhs: " + enum_name + ") -> Bool {");
+
4578 Indent(1);
+
4579 WriteLineIndent("guard let lhsValue = lhs.value, let rhsValue = rhs.value else {");
+
4580 Indent(1);
+
4581 WriteLineIndent("return false");
+
4582 WriteLineIndent("}");
+
4583 Indent(-1);
+
4584 WriteLineIndent("return lhsValue.rawValue < rhsValue.rawValue");
+
4585 Indent(-1);
+
4586 WriteLineIndent("}");
+
4587
+
4588 // Generate enum class equals() method
+
4589 // Generate enum class compareTo() method
+
4590 WriteLine();
+
4591 WriteLineIndent("public static func == (lhs: " + enum_name + ", rhs: " + enum_name + ") -> Bool {");
+
4592 Indent(1);
+
4593 WriteLineIndent("guard let lhsValue = lhs.value, let rhsValue = rhs.value else {");
+
4594 Indent(1);
+
4595 WriteLineIndent("return false");
+
4596 WriteLineIndent("}");
+
4597 Indent(-1);
+
4598 WriteLineIndent("return lhsValue.rawValue == rhsValue.rawValue");
+
4599 Indent(-1);
+
4600 WriteLineIndent("}");
+
4601
+
4602 // Generate enum class hashCode() method
+
4603 WriteLine();
+
4604 WriteLineIndent("public func hash(into hasher: inout Hasher) {");
+
4605 Indent(1);
+
4606 WriteLineIndent("hasher.combine(value?.rawValue ?? 0)");
+
4607 Indent(-1);
+
4608 WriteLineIndent("}");
+
4609
+
4610 // Generate enum class description method
+
4611 WriteLine();
+
4612 WriteLineIndent("public var description: String {");
+
4613 Indent(1);
+
4614 WriteLineIndent("return value?.description ?? \"<unknown>\"");
+
4615 Indent(-1);
+
4616 WriteLineIndent("}");
+
4617
+
4618 if (JSON())
+
4619 {
+
4620 WriteLineIndent("public func encode(to encoder: Encoder) throws {");
+
4621 Indent(1);
+
4622 WriteLineIndent("var container = encoder.singleValueContainer()");
+
4623 WriteLineIndent("try container.encode(raw)");
+
4624 Indent(-1);
+
4625 WriteLineIndent("}");
+
4626
+
4627 WriteLine();
+
4628 WriteLineIndent("public func toJson() throws -> String {");
+
4629 Indent(1);
+
4630 WriteLineIndent("return String(data: try JSONEncoder().encode(self), encoding: .utf8)!");
+
4631 Indent(-1);
+
4632 WriteLineIndent("}");
+
4633
+
4634 WriteLine();
+
4635 WriteLineIndent("public static func fromJson(_ json: String) throws -> " + enum_name + " {");
+
4636 Indent(1);
+
4637 WriteLineIndent("return try JSONDecoder().decode(" + enum_name + ".self, from: json.data(using: .utf8)!)");
+
4638 Indent(-1);
+
4639 WriteLineIndent("}");
+
4640 }
+
4641
+
4642 Indent(-1);
+
4643 WriteLineIndent("}");
+
4644
+
4645 // Generate enum class footer
+
4646 GenerateFooter();
+
4647
+
4648 // Store the output file
+
4649 WriteEnd();
+
4650 Store(output);
+
4651}
+
4652
+
4653void GeneratorSwift::GenerateFlags(const std::shared_ptr<Package>& p, const std::shared_ptr<FlagsType>& f, const CppCommon::Path& path)
+
4654{
+
4655 std::string flags_name = *f->name + "Enum";
+
4656
+
4657 // Generate the output file
+
4658 CppCommon::Path output = path / (flags_name + ".swift");
+
4659 WriteBegin();
+
4660
+
4661 // Generate flags header
+
4662 GenerateHeader(CppCommon::Path(_input).filename().string());
+
4663 GenerateImports("", "Foundation");
+
4664
+
4665 std::string flags_type = (f->base && !f->base->empty()) ? *f->base : "int32";
+
4666 std::string flags_base_type = ConvertEnumType(flags_type);
+
4667 std::string flags_mapping_type = ConvertEnumBase(flags_type);
+
4668 std::string flags_int = ConvertEnumFlags(flags_type);
+
4669 std::string flags_to = ConvertEnumTo(flags_type);
+
4670
+
4671 // Generate flags body
+
4672 WriteLine();
+
4673 WriteLineIndent("public struct " + flags_name + ": OptionSet {");
+
4674 Indent(1);
+
4675 if (f->body)
+
4676 {
+
4677 for (const auto& value : f->body->values)
+
4678 {
+
4679 WriteIndent("public static let " + *value->name + " = " + flags_name + "(rawValue: ");
+
4680 if (value->value)
+
4681 {
+
4682 if (value->value->constant && !value->value->constant->empty())
+
4683 Write(ConvertEnumConstant(flags_type, flags_type, *value->value->constant, true));
+
4684 else if (value->value->reference && !value->value->reference->empty())
+
4685 Write(ConvertEnumConstant(flags_type, "", *value->value->reference, true));
+
4686 }
+
4687 Write(")");
+
4688 WriteLine();
+
4689 }
+
4690 WriteLine();
+
4691 }
+
4692 else
+
4693 WriteIndent("public static let unknown = " + flags_name + "(rawValue: 0");
+
4694
+
4695 // Generate flags class value
+
4696 WriteLineIndent("public var rawValue: " + flags_mapping_type);
+
4697
+
4698 // Generate flags class constructors
+
4699 WriteLine();
+
4700 WriteLineIndent("public init(rawValue: " + flags_mapping_type + ") { self.rawValue = rawValue }");
+
4701 if ((flags_type == "char") || (flags_type == "wchar"))
+
4702 WriteLineIndent("public init(value: Char) { self.rawValue = value" + flags_to + " }");
+
4703 if (IsUnsignedType(flags_type))
+
4704 {
+
4705 WriteLineIndent("public init(value: UInt8) { self.rawValue = NSNumber(value: value)" + flags_to + " }");
+
4706 WriteLineIndent("public init(value: UInt16) { self.rawValue = NSNumber(value: value)" + flags_to + " }");
+
4707 WriteLineIndent("public init(value: UInt32) { self.rawValue = NSNumber(value: value)" + flags_to + " }");
+
4708 WriteLineIndent("public init(value: UInt64) { self.rawValue = NSNumber(value: value)" + flags_to + " }");
+
4709 }
+
4710 else
+
4711 {
+
4712 WriteLineIndent("public init(value: Int8) { self.rawValue = NSNumber(value: value)" + flags_to + " }");
+
4713 WriteLineIndent("public init(value: Int16) { self.rawValue = NSNumber(value: value)" + flags_to + " }");
+
4714 WriteLineIndent("public init(value: Int32) { self.rawValue = NSNumber(value: value)" + flags_to + " }");
+
4715 WriteLineIndent("public init(value: Int64) { self.rawValue = NSNumber(value: value)" + flags_to + " }");
+
4716 }
+
4717 WriteLineIndent("public init(value: " + flags_name + ") { self.rawValue = value.rawValue }");
+
4718
+
4719 // Generate flags hasFlags() methods
+
4720 WriteLine();
+
4721 WriteLineIndent("public func hasFlags(flags: " + flags_base_type + ") -> Bool { return ((NSNumber(value: rawValue)" + flags_int + " & NSNumber(value: flags)" + flags_int + ") != " + ConvertEnumConstant(flags_type, flags_type, "0", false) + ") && (NSNumber(value: rawValue)" + flags_int + " & NSNumber(value: flags)" + flags_int + " == NSNumber(value: flags)" + flags_int + ") }");
+
4722 WriteLineIndent("public func hasFlags(flags: " + flags_name + ") -> Bool { return hasFlags(flags: flags.rawValue) }");
+
4723
+
4724 // Generate flags getAllSet(), getNoneSet(), getCurrentSet() methods
+
4725 WriteLine();
+
4726 WriteLineIndent("public static let allSet: " + flags_name + " = [");
+
4727 Indent(1);
+
4728 if (f->body)
+
4729 {
+
4730 for (const auto& value : f->body->values)
+
4731 {
+
4732 WriteIndent("." + *value->name + ",");
+
4733 WriteLine();
+
4734 }
+
4735 }
+
4736 else
+
4737 WriteIndent(".unknown");
+
4738 Indent(-1);
+
4739 WriteLineIndent("]");
+
4740 WriteLineIndent("public static let noneSet: " + flags_name + " = []");
+
4741 WriteLineIndent("public var currentSet: " + flags_name + " {");
+
4742 Indent(1);
+
4743 WriteLineIndent("var result = " + flags_name + ".noneSet");
+
4744 if (f->body)
+
4745 {
+
4746 for (const auto& value : f->body->values)
+
4747 {
+
4748 WriteLineIndent("if (NSNumber(value: rawValue)" + flags_int + " & NSNumber(value: " + flags_name + "." + *value->name + ".rawValue)" + flags_int + ") != " + ConvertEnumConstant(flags_type, flags_type, "0", false) + " {");
+
4749 Indent(1);
+
4750 WriteLineIndent("result = result.union(." + *value->name + ")");
+
4751 Indent(-1);
+
4752 WriteLineIndent("}");
+
4753 }
+
4754 }
+
4755 WriteLineIndent("return result");
+
4756 Indent(-1);
+
4757 WriteLineIndent("}");
+
4758
+
4759 // Generate enum description method
+
4760 WriteLine();
+
4761 WriteLineIndent("public var description: String {");
+
4762 Indent(1);
+
4763 WriteLineIndent("var sb = String()");
+
4764 if (f->body && !f->body->values.empty())
+
4765 {
+
4766 WriteLineIndent("var first = true");
+
4767 for (const auto& value : f->body->values)
+
4768 {
+
4769 WriteLineIndent("if hasFlags(flags: ." + *value->name + ") {");
+
4770 Indent(1);
+
4771 WriteLineIndent("sb.append(first ? \"\" : \"|\"); sb.append(\"" + *value->name + "\")");
+
4772 WriteLineIndent("first = false");
+
4773 Indent(-1);
+
4774 WriteLineIndent("}");
+
4775 }
+
4776 }
+
4777 WriteLineIndent("return sb");
+
4778 Indent(-1);
+
4779 WriteLineIndent("}");
+
4780
+
4781 // Generate flags values() method
+
4782 WriteLine();
+
4783 WriteLineIndent("static let rawValuesMap: [RawValue: " + flags_name + "] = {");
+
4784 Indent(1);
+
4785 WriteLineIndent("var value = [RawValue: " + flags_name + "]()");
+
4786 if (f->body)
+
4787 {
+
4788 for (const auto& value : f->body->values)
+
4789 {
+
4790 WriteIndent("value[" + flags_name + "." + *value->name + ".rawValue] = ." + *value->name);
+
4791 WriteLine();
+
4792 }
+
4793 }
+
4794 else
+
4795 WriteIndent("value[" +flags_name + ".unknown.rawValue] = .unknown");
+
4796 WriteLineIndent("return value");
+
4797 Indent(-1);
+
4798 WriteLineIndent("}()");
+
4799
+
4800 // Generate flags mapValue() method
+
4801 WriteLine();
+
4802 WriteLineIndent("public static func mapValue(value: RawValue) -> " + flags_name + "? {");
+
4803 Indent(1);
+
4804 WriteLineIndent("return rawValuesMap[value]");
+
4805 Indent(-1);
+
4806 WriteLineIndent("}");
+
4807
+
4808 Indent(-1);
+
4809 WriteLineIndent("}");
+
4810
+
4811 // Generate flags footer
+
4812 GenerateFooter();
+
4813
+
4814 // Store the output file
+
4815 WriteEnd();
+
4816 Store(output);
+
4817
+
4818 // Generate flags wrapper class
+
4819 GenerateFlagsClass(p, f, path);
+
4820
+
4821 std::string domain = ConvertDomain(p);
+
4822 std::string package = ConvertPackage(p);
+
4823
+
4824 // Generate flags field model
+
4825 GenerateFBEFieldModelEnumFlags(domain, package, *f->name, flags_type);
+
4826
+
4827 // Generate flags final model
+
4828 if (Final())
+
4829 GenerateFBEFinalModelEnumFlags(domain, package, *f->name, flags_type);
+
4830}
+
4831
+
4832void GeneratorSwift::GenerateFlagsClass(const std::shared_ptr<Package>& p, const std::shared_ptr<FlagsType>& f, const CppCommon::Path& path)
+
4833{
+
4834 std::string flags_name = *f->name;
+
4835 std::string flags_type_name = *f->name + "Enum";
+
4836
+
4837 // Generate the output file
+
4838 CppCommon::Path output = path / (flags_name + ".swift");
+
4839 WriteBegin();
+
4840
+
4841 // Generate flags class header
+
4842 GenerateHeader(CppCommon::Path(_input).filename().string());
+
4843 GenerateImports("", "Foundation");
+
4844
+
4845 std::string flags_type = (f->base && !f->base->empty()) ? *f->base : "int32";
+
4846 std::string flags_base_type = ConvertEnumType(flags_type);
+
4847 std::string flags_int = ConvertEnumFlags(flags_type);
+
4848 std::string flags_to = ConvertEnumTo(flags_type);
+
4849
+
4850 // Generate flags class body
+
4851 WriteLine();
+
4852 if (JSON())
+
4853 WriteLineIndent("public struct " + flags_name + ": Comparable, Hashable, Codable {");
+
4854 else
+
4855 WriteLineIndent("public struct " + flags_name + ": Comparable, Hashable {");
+
4856 Indent(1);
+
4857 WriteLineIndent("typealias RawValue = " + flags_base_type);
+
4858 if (f->body)
+
4859 {
+
4860 if (!f->body->values.empty())
+
4861 {
+
4862 for (const auto& value : f->body->values)
+
4863 WriteLineIndent("public static let " + *value->name + " = " + flags_name + "(value: ." + *value->name + ")");
+
4864 WriteLine();
+
4865 }
+
4866
+
4867 // Generate flags class fromSet() method
+
4868 WriteLineIndent("public static func fromSet(set: " + flags_type_name + ") -> " + flags_name + " {");
+
4869 Indent(1);
+
4870 WriteLineIndent("var result = NSNumber(value: " + ConvertEnumConstant(flags_type, flags_type, "0", false) + ")" + flags_int);
+
4871 if (f->body)
+
4872 {
+
4873 for (const auto& value : f->body->values)
+
4874 {
+
4875 WriteLineIndent("if set.contains(" + flags_name + "." + *value->name + ".value!) {");
+
4876 Indent(1);
+
4877 WriteLineIndent("result = NSNumber(value: result)" + flags_int + " | NSNumber(value: " +flags_name + "." + *value->name + ".raw)" + flags_int);
+
4878 Indent(-1);
+
4879 WriteLineIndent("}");
+
4880 }
+
4881 }
+
4882 WriteLineIndent("return " + flags_name + "(value: NSNumber(value: result)" + flags_to + ")");
+
4883 Indent(-1);
+
4884 WriteLineIndent("}");
+
4885
+
4886 WriteLine();
+
4887 }
+
4888
+
4889 // Generate flags class value
+
4890 WriteLineIndent("public private(set) var value: " + flags_type_name + "?");
+
4891 WriteLine();
+
4892
+
4893 // Generate flags raw value
+
4894 WriteLineIndent("public private(set) var raw: " + flags_base_type + " = 0");
+
4895 WriteLine();
+
4896
+
4897 // Generate flags class constructors
+
4898 WriteLineIndent("public init() { setDefaults() }");
+
4899 WriteLineIndent("public init(value: " + flags_base_type + ") { setEnum(value: value) }");
+
4900 WriteLineIndent("public init(value: " + flags_type_name + ") { setEnum(value: value) }");
+
4901 WriteLineIndent("public init(value: " + flags_name + ") { setEnum(value: value) }");
+
4902
+
4903 if (JSON())
+
4904 {
+
4905 WriteLine();
+
4906 WriteLineIndent("public init(from decoder: Decoder) throws {");
+
4907 Indent(1);
+
4908 WriteLineIndent("let container = try decoder.singleValueContainer()");
+
4909 WriteLineIndent("setEnum(value: try container.decode(RawValue.self))");
+
4910 Indent(-1);
+
4911 WriteLineIndent("}");
+
4912 }
+
4913
+
4914 // Generate flags class setDefault() method
+
4915 WriteLine();
+
4916 WriteLineIndent("public mutating func setDefaults() { setEnum(value: 0) }");
+
4917 WriteLine();
+
4918
+
4919 // Generate flags class setEnum() methods
+
4920 WriteLineIndent("public mutating func setEnum(value: " + flags_base_type + ") { self.raw = value; self.value = " + flags_type_name + ".mapValue(value: value) }");
+
4921 WriteLineIndent("public mutating func setEnum(value: " + flags_type_name + ") { self.raw = value.rawValue; self.value = value }");
+
4922 WriteLineIndent("public mutating func setEnum(value: " + flags_name + ") { self.raw = value.raw; self.value = value.value }");
+
4923
+
4924 // Generate flags class hasFlags() methods
+
4925 WriteLine();
+
4926 WriteLineIndent("public func hasFlags(flags: " + flags_base_type + ") -> Bool { return (NSNumber(value: raw)" + flags_int + " & NSNumber(value: flags)" + flags_int + " != " + ConvertEnumConstant(flags_type, flags_type, "0", false) + ") && ((NSNumber(value: raw)" + flags_int + " & NSNumber(value: flags)" + flags_int + ") == NSNumber(value: flags)" + flags_int + ") }");
+
4927 WriteLineIndent("public func hasFlags(flags: " + flags_type_name + ") -> Bool { return hasFlags(flags: flags.rawValue) }");
+
4928 WriteLineIndent("public func hasFlags(flags: " + flags_name + ") -> Bool { return hasFlags(flags: flags.raw) }");
+
4929
+
4930 // Generate flags class setFlags() methods
+
4931 WriteLine();
+
4932 WriteLineIndent("public mutating func setFlags(flags: " + flags_base_type + ") -> " + flags_name + " { setEnum(value: NSNumber(value: NSNumber(value: raw)" + flags_int + " | NSNumber(value: flags)" + flags_int + ")" + flags_to + "); return self }");
+
4933 WriteLineIndent("public mutating func setFlags(flags: " + flags_type_name + ") -> " + flags_name + " { _ = setFlags(flags: flags.rawValue); return self }");
+
4934 WriteLineIndent("public mutating func setFlags(flags: " + flags_name + ") -> " + flags_name + " { _ = setFlags(flags: flags.raw); return self }");
+
4935
+
4936 // Generate flags class removeFlags() methods
+
4937 WriteLine();
+
4938 WriteLineIndent("public mutating func removeFlags(flags: " + flags_base_type + ") -> " + flags_name + " { setEnum(value: NSNumber(value: NSNumber(value: raw)" + flags_int + " | NSNumber(value: flags)" + flags_int + ".byteSwapped)" + flags_to + "); return self }");
+
4939 WriteLineIndent("public mutating func removeFlags(flags: " + flags_type_name + ") -> " + flags_name + " { _ = removeFlags(flags: flags.rawValue); return self }");
+
4940 WriteLineIndent("public mutating func removeFlags(flags: " + flags_name + ") -> " + flags_name + " { _ = removeFlags(flags: flags.raw); return self }");
+
4941
+
4942 // Generate flags class getAllSet(), getNoneSet() and getCurrentSet() methods
+
4943 WriteLine();
+
4944 WriteLineIndent("public var allSet: " + flags_type_name + " { return .allSet }");
+
4945 WriteLineIndent("public var noneSet: " + flags_type_name + " { return .noneSet }");
+
4946 WriteLineIndent("public var currentSet: " + flags_type_name + " { return value!.currentSet }");
+
4947
+
4948 // Generate flags class < method
+
4949 WriteLine();
+
4950 WriteLineIndent("public static func < (lhs: " + flags_name + ", rhs: " + flags_name + ") -> Bool {");
+
4951 Indent(1);
+
4952 WriteLineIndent("return lhs.raw < rhs.raw");
+
4953 Indent(-1);
+
4954 WriteLineIndent("}");
+
4955
+
4956 // Generate flags class == method
+
4957 WriteLine();
+
4958 WriteLineIndent("public static func == (lhs: " + flags_name + ", rhs: " + flags_name + ") -> Bool {");
+
4959 Indent(1);
+
4960 WriteLineIndent("return lhs.raw == rhs.raw");
+
4961 Indent(-1);
+
4962 WriteLineIndent("}");
+
4963
+
4964 // Generate flags class hashCode() method
+
4965 WriteLine();
+
4966 WriteLineIndent("public func hash(into hasher: inout Hasher) {");
+
4967 Indent(1);
+
4968 WriteLineIndent("hasher.combine(raw)");
+
4969 Indent(-1);
+
4970 WriteLineIndent("}");
+
4971
+
4972 // Generate flags class description method
+
4973 WriteLine();
+
4974 WriteLineIndent("public var description: String {");
+
4975 Indent(1);
+
4976 WriteLineIndent("var sb = String()");
+
4977 if (f->body && !f->body->values.empty())
+
4978 {
+
4979 WriteLineIndent("var first = true");
+
4980 for (const auto& value : f->body->values)
+
4981 {
+
4982 WriteLineIndent("if hasFlags(flags: " + flags_name + "." + *value->name + ".raw) {");
+
4983 Indent(1);
+
4984 WriteLineIndent("sb.append(first ? \"\" : \"|\"); sb.append(\"" + *value->name + "\")");
+
4985 WriteLineIndent("first = false");
+
4986 Indent(-1);
+
4987 WriteLineIndent("}");
+
4988 }
+
4989 }
+
4990 WriteLineIndent("return sb");
+
4991 Indent(-1);
+
4992 WriteLineIndent("}");
+
4993
+
4994 if (JSON())
+
4995 {
+
4996 WriteLineIndent("public func encode(to encoder: Encoder) throws {");
+
4997 Indent(1);
+
4998 WriteLineIndent("var container = encoder.singleValueContainer()");
+
4999 WriteLineIndent("try container.encode(raw)");
+
5000 Indent(-1);
+
5001 WriteLineIndent("}");
+
5002
+
5003 WriteLine();
+
5004 WriteLineIndent("public func toJson() throws -> String {");
+
5005 Indent(1);
+
5006 WriteLineIndent("return String(data: try JSONEncoder().encode(self), encoding: .utf8)!");
+
5007 Indent(-1);
+
5008 WriteLineIndent("}");
+
5009
+
5010 WriteLine();
+
5011 WriteLineIndent("public static func fromJson(_ json: String) throws -> " + flags_name + " {");
+
5012 Indent(1);
+
5013 WriteLineIndent("return try JSONDecoder().decode(" + flags_name + ".self, from: json.data(using: .utf8)!)");
+
5014 Indent(-1);
+
5015 WriteLineIndent("}");
+
5016 }
+
5017
+
5018 Indent(-1);
+
5019 WriteLineIndent("}");
+
5020
+
5021 // Generate flags class footer
+
5022 GenerateFooter();
+
5023
+
5024 // Store the output file
+
5025 WriteEnd();
+
5026 Store(output);
+
5027}
+
5028
+
5029void GeneratorSwift::GenerateStruct(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s, const CppCommon::Path& path)
+
5030{
+
5031 std::string domain = ConvertDomain(p);
+
5032 std::string package = ConvertPackage(p);
+
5033 bool first;
+
5034
+
5035 // Generate the output file
+
5036 CppCommon::Path output = path / (*s->name + ".swift");
+
5037 WriteBegin();
+
5038
+
5039 // Generate struct header
+
5040 GenerateHeader(CppCommon::Path(_input).filename().string());
+
5041 GenerateImports("", "Foundation");
+
5042 GenerateImports(domain, "Fbe");
+
5043 GenerateImports(p);
+
5044
+
5045 // Generate based protocol
+
5046
+
5047 WriteLine();
+
5048 WriteIndent("public protocol " + *s->name + "Base");
+
5049 if (s->base && !s->base->empty())
+
5050 Write(": " + ConvertTypeName(domain, "", ConvertPackageName(*s->base), false) + "Base");
+
5051 WriteLineIndent(" {");
+
5052 Indent(1);
+
5053 if (s->body && !s->body->fields.empty())
+
5054 {
+
5055 for (const auto& field : s->body->fields)
+
5056 {
+
5057 std::string fieldName = (*field->name == "Type") ? ("`Type`") : *field->name;
+
5058 WriteLineIndent("var " + fieldName + ": " + ConvertTypeName(domain, "", *field, false) + " { get set }");
+
5059 }
+
5060 }
+
5061 Indent(-1);
+
5062 WriteLineIndent("}");
+
5063
+
5064 WriteLine();
+
5065 WriteIndent("public protocol " + *s->name + "Inheritance");
+
5066 if (s->base && !s->base->empty())
+
5067 Write(": " + ConvertTypeName(domain, "", ConvertPackageName(*s->base), false) + "Inheritance");
+
5068 WriteLineIndent(" {");
+
5069 Indent(1);
+
5070 WriteLineIndent("var parent: " + *s->name + " { get set }");
+
5071 Indent(-1);
+
5072 WriteLineIndent("}");
+
5073
+
5074
+
5075 WriteLine();
+
5076 WriteLineIndent("extension " + *s->name + "Inheritance {");
+
5077 Indent(1);
+
5078 // Generate struct body
+
5079
+
5080 if (s->base && !s->base->empty())
+
5081 {
+
5082 WriteLineIndent("public var parent: " + ConvertTypeName(domain, "", ConvertPackageName(*s->base), false) + " {");
+
5083 Indent(1);
+
5084 WriteLineIndent("get { return parent.parent }");
+
5085 WriteLineIndent("set { parent.parent = newValue }");
+
5086 Indent(-1);
+
5087 WriteLineIndent("}");
+
5088 }
+
5089 if (s->body && !s->body->fields.empty())
+
5090 {
+
5091 for (const auto& field : s->body->fields)
+
5092 {
+
5093 std::string fieldName = (*field->name == "Type") ? ("`Type`") : *field->name;
+
5094 WriteLineIndent("public var " + fieldName + ": " + ConvertTypeName(domain, "", *field, false) + " {");
+
5095 Indent(1);
+
5096 WriteLineIndent("get { return parent." + fieldName + " }");
+
5097 WriteLineIndent("set { parent." + fieldName + " = newValue }");
+
5098 Indent(-1);
+
5099 WriteLineIndent("}");
+
5100 }
+
5101 }
+
5102 Indent(-1);
+
5103 WriteLineIndent("}");
+
5104
+
5105
+
5106 // Generate struct begin
+
5107 WriteLine();
+
5108 WriteIndent("public struct " + *s->name + ": " + *s->name + "Base");
+
5109 if (s->base && !s->base->empty())
+
5110 Write(", " + ConvertTypeName(domain, "", ConvertPackageName(*s->base), false) + "Inheritance");
+
5111 if (JSON())
+
5112 Write(", Comparable, Hashable, Codable");
+
5113 else
+
5114 Write(", Comparable, Hashable");
+
5115 WriteLineIndent(" {");
+
5116 Indent(1);
+
5117
+
5118 // Generate parent struct
+
5119 if (s->base && !s->base->empty())
+
5120 WriteLineIndent("public var parent: " + ConvertTypeName(domain, "", ConvertPackageName(*s->base), false));
+
5121
+
5122 // Generate struct body
+
5123 if (s->body && !s->body->fields.empty())
+
5124 {
+
5125 for (const auto& field : s->body->fields)
+
5126 {
+
5127 std::string fieldName = (*field->name == "Type") ? ("`Type`") : *field->name;
+
5128 WriteLineIndent("public var " + fieldName + ": " + ConvertTypeName(domain, "", *field, false) + " = " + ConvertDefault(domain, package, *field));
+
5129 }
+
5130 }
+
5131
+
5132 WriteLine();
+
5133 // Generate struct default constructor
+
5134 if (s->base && !s->base->empty())
+
5135 WriteLineIndent("public init() { parent = " + ConvertTypeName(domain, "", ConvertPackageName(*s->base), false) + "() }");
+
5136 else
+
5137 WriteLineIndent("public init() { }");
+
5138
+
5139 // Generate struct initialization constructor
+
5140 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
5141 {
+
5142 first = true;
+
5143 WriteIndent("public init(");
+
5144 if (s->base && !s->base->empty())
+
5145 {
+
5146 Write("parent: " + ConvertTypeName(domain, "", ConvertPackageName(*s->base), false));
+
5147 first = false;
+
5148 }
+
5149 if (s->body)
+
5150 {
+
5151 for (const auto& field : s->body->fields)
+
5152 {
+
5153 Write(std::string(first ? "" : ", ") + *field->name + ": " + ConvertTypeName(domain, "", *field, false));
+
5154 first = false;
+
5155 }
+
5156 }
+
5157 Write(") {");
+
5158 WriteLine();
+
5159 Indent(1);
+
5160 if (s->base && !s->base->empty())
+
5161 WriteLineIndent("self.parent = parent");
+
5162 WriteLine();
+
5163 if (s->body)
+
5164 for (const auto& field : s->body->fields)
+
5165 WriteLineIndent("self." + *field->name + " = " + *field->name);
+
5166 Indent(-1);
+
5167 WriteLineIndent("}");
+
5168 }
+
5169
+
5170 // Generate struct copy constructor
+
5171 WriteLine();
+
5172 WriteLineIndent("public init(other: " + *s->name + ") {");
+
5173 Indent(1);
+
5174 if (s->base && !s->base->empty())
+
5175 WriteLineIndent("parent = other.parent");
+
5176 if (s->body)
+
5177 for (const auto& field : s->body->fields)
+
5178 WriteLineIndent("self." + *field->name + " = other." + *field->name);
+
5179 Indent(-1);
+
5180 WriteLineIndent("}");
+
5181
+
5182 // Generate struct json constructor
+
5183 if (JSON())
+
5184 {
+
5185 WriteLine();
+
5186 WriteLineIndent("public init(from decoder: Decoder) throws {");
+
5187 Indent(1);
+
5188 if (s->base && !s->base->empty())
+
5189 WriteLineIndent("parent = try " + ConvertTypeName(domain, "", ConvertPackageName(*s->base), false) + "(from: decoder)");
+
5190
+
5191 WriteLineIndent("let container = try decoder.container(keyedBy: CodingKeys.self)");
+
5192 if (s->body)
+
5193 {
+
5194 for (const auto& field : s->body->fields)
+
5195 {
+
5196 if ((field->vector || field->list || field->set || field->map || field->hash) && *field->type == "timestamp")
+
5197 {
+
5198 WriteLineIndent(*field->name + " = Dictionary(uniqueKeysWithValues: (try container.decode(Dictionary<String, " + ConvertTypeName(domain, "", "TimeInterval", field->optional) + ">.self, forKey: ." + *field->name + ")).map { (" + ConvertTypeName(domain, "", *field->key, false) + "($0) ?? 0, Date(timeIntervalSince1970: $1 / 1_000_000_000)) })");
+
5199 }
+
5200 else if (field->map && *field->key != "string")
+
5201 {
+
5202 WriteLineIndent(*field->name + " = Dictionary(uniqueKeysWithValues: (try container.decode(Dictionary<String, " + ConvertTypeName(domain, "", *field->type, field->optional) + ">.self, forKey: ." + *field->name + ")).map { (" + ConvertTypeName(domain, "", *field->key, false) + "($0) ?? 0, $1) })");
+
5203 }
+
5204 else if (*field->type == "decimal")
+
5205 {
+
5206 if (field->optional)
+
5207 {
+
5208 WriteLineIndent("let " + *field->name + "RawValue = try container.decode(String?.self, forKey: ." + *field->name + ")");
+
5209 WriteLineIndent(*field->name + " = " + *field->name + "RawValue != nil ? Decimal(string: " + *field->name + "RawValue!) ?? .nan : nil");
+
5210 } else
+
5211 WriteLineIndent(*field->name + " = Decimal(string: try container.decode(String.self, forKey: ." + *field->name + ")) ?? .nan");
+
5212 }
+
5213 else if (*field->type == "timestamp")
+
5214 {
+
5215 if (field->optional)
+
5216 {
+
5217 WriteLineIndent("let " + *field->name + "RawValue = try container.decode(TimeInterval?.self, forKey: ." + *field->name + ")");
+
5218 WriteLineIndent(*field->name + " = " + *field->name + "RawValue != nil ? Date(timeIntervalSince1970: " + *field->name + "RawValue! / 1_000_000_000) : nil");
+
5219 } else
+
5220 WriteLineIndent(*field->name + " = Date(timeIntervalSince1970: try container.decode(TimeInterval.self, forKey: ." + *field->name + ") / 1_000_000_000)");
+
5221 }
+
5222 else if ((*field->type == "char") || (*field->type == "wchar"))
+
5223 {
+
5224 std::string valueType = (*field->type == "char") ? "UInt8" : "UInt32";
+
5225 std::string valueOpt = (*field->type == "char") ? "" : "!";
+
5226 if (field->optional)
+
5227 {
+
5228 WriteLineIndent("let " + *field->name + "RawValue: " + valueType + "? = try container.decode(" + valueType + "?.self, forKey: ." + *field->name + ")");
+
5229 WriteLineIndent(*field->name + " = " + *field->name + "RawValue != nil ? Character(UnicodeScalar(" + *field->name + "RawValue!)" + valueOpt + ") : nil");
+
5230 } else {
+
5231 WriteLineIndent("let " + *field->name + "RawValue: " + valueType + " = try container.decode(" + valueType + ".self, forKey: ." + *field->name + ")");
+
5232 WriteLineIndent(*field->name + " = Character(UnicodeScalar(" + *field->name + "RawValue)" + valueOpt + ")");
+
5233 }
+
5234 }
+
5235 else
+
5236 WriteLineIndent(*field->name + " = try container.decode(" + ConvertTypeName(domain, package, *field, false) + ".self, forKey: ." + *field->name + ")");
+
5237 }
+
5238 }
+
5239
+
5240 Indent(-1);
+
5241 WriteLineIndent("}");
+
5242 }
+
5243
+
5244 // Generate struct clone() method
+
5245 WriteLine();
+
5246 WriteLineIndent("public func clone() throws -> " + *s->name + " {");
+
5247 Indent(1);
+
5248 WriteLineIndent("// Serialize the struct to the FBE stream");
+
5249 WriteLineIndent("let writer = " + *s->name + "Model()");
+
5250 WriteLineIndent("try _ = writer.serialize(value: self)");
+
5251 WriteLine();
+
5252 WriteLineIndent("// Deserialize the struct from the FBE stream");
+
5253 WriteLineIndent("let reader = " + *s->name + "Model()");
+
5254 WriteLineIndent("reader.attach(buffer: writer.buffer)");
+
5255 WriteLineIndent("return reader.deserialize()");
+
5256 Indent(-1);
+
5257 WriteLineIndent("}");
+
5258
+
5259 // Generate struct compareTo() method
+
5260 WriteLine();
+
5261 WriteLineIndent("public static func < (lhs: " + *s->name + ", rhs: " + *s->name + ") -> Bool {");
+
5262 Indent(1);
+
5263 if (s->body)
+
5264 for (const auto& field : s->body->fields)
+
5265 if (field->keys)
+
5266 WriteLineIndent("if !(lhs." + *field->name + " < rhs." + *field->name + ") { return false }");
+
5267 WriteLineIndent("return true");
+
5268 Indent(-1);
+
5269 WriteLineIndent("}");
+
5270
+
5271 // Generate struct equals() method
+
5272 WriteLine();
+
5273 WriteLineIndent("public static func == (lhs: " + *s->name + ", rhs: " + *s->name + ") -> Bool {");
+
5274 Indent(1);
+
5275 if (s->body)
+
5276 for (const auto& field : s->body->fields)
+
5277 if (field->keys)
+
5278 WriteLineIndent("if !(lhs." + *field->name + " == rhs." + *field->name + ") { return false }");
+
5279 WriteLineIndent("return true");
+
5280 Indent(-1);
+
5281 WriteLineIndent("}");
+
5282
+
5283 // Generate struct hashCode() method
+
5284 WriteLine();
+
5285 WriteLineIndent("public func hash(into hasher: inout Hasher) {");
+
5286 Indent(1);
+
5287 if (s->base && !s->base->empty())
+
5288 WriteLineIndent("parent.hash(into: &hasher)");
+
5289 if (s->body)
+
5290 for (const auto& field : s->body->fields)
+
5291 if (field->keys)
+
5292 WriteLineIndent("hasher.combine(" + *field->name + ")");
+
5293 Indent(-1);
+
5294 WriteLineIndent("}");
+
5295
+
5296 // Generate struct description method
+
5297 WriteLine();
+
5298 WriteLineIndent("public var description: String {");
+
5299 Indent(1);
+
5300 WriteLineIndent("var sb = String()");
+
5301 WriteLineIndent("sb.append(\"" + *s->name + "(\")");
+
5302 first = true;
+
5303 if (s->base && !s->base->empty())
+
5304 {
+
5305 WriteLineIndent("sb.append(parent.description)");
+
5306 first = false;
+
5307 }
+
5308 if (s->body)
+
5309 {
+
5310 for (const auto& field : s->body->fields)
+
5311 {
+
5312 if (field->attributes && field->attributes->hidden)
+
5313 WriteLineIndent("sb.append(\"" + std::string(first ? "" : ",") + *field->name + "=***\");");
+
5314 else if (field->array || field->vector)
+
5315 {
+
5316 WriteLineIndent("if true {");
+
5317 Indent(1);
+
5318 WriteLineIndent("var first = true");
+
5319 WriteLineIndent("sb.append(\"" + std::string(first ? "" : ",") + *field->name + "=[\"); sb.append(\"\\(" + *field->name + ".count)\"" + "); sb.append(\"][\")");
+
5320 WriteLineIndent("for item in " + *field->name + " {");
+
5321 Indent(1);
+
5322 WriteLineIndent(ConvertOutputStreamValue(*field->type, "item", field->optional, true, false));
+
5323 WriteLineIndent("first = false");
+
5324 Indent(-1);
+
5325 WriteLineIndent("}");
+
5326 WriteLineIndent("sb.append(\"]\")");
+
5327 Indent(-1);
+
5328 WriteLineIndent("}");
+
5329 }
+
5330 else if (field->list)
+
5331 {
+
5332 WriteLineIndent("if true {");
+
5333 Indent(1);
+
5334 WriteLineIndent("var first = true");
+
5335 WriteLineIndent("sb.append(\"" + std::string(first ? "" : ",") + *field->name + "=[\"); sb.append(\"\\(" + *field->name + ".count)\"" + "); sb.append(\"]<\")");
+
5336 WriteLineIndent("for item in " + *field->name + " {");
+
5337 Indent(1);
+
5338 WriteLineIndent(ConvertOutputStreamValue(*field->type, "item", field->optional, true, false));
+
5339 WriteLineIndent("first = false");
+
5340 Indent(-1);
+
5341 WriteLineIndent("}");
+
5342 WriteLineIndent("sb.append(\">\")");
+
5343 Indent(-1);
+
5344 WriteLineIndent("}");
+
5345 }
+
5346 else if (field->set)
+
5347 {
+
5348 WriteLineIndent("if true {");
+
5349 Indent(1);
+
5350 WriteLineIndent("var first = true");
+
5351 WriteLineIndent("sb.append(\"" + std::string(first ? "" : ",") + *field->name + "=[\"); sb.append(\"\\(" + *field->name + ".count)\"" + "); sb.append(\"]{\")");
+
5352 WriteLineIndent("for item in " + *field->name + " {");
+
5353 Indent(1);
+
5354 WriteLineIndent(ConvertOutputStreamValue(*field->type, "item", field->optional, true, false));
+
5355 WriteLineIndent("first = false");
+
5356 Indent(-1);
+
5357 WriteLineIndent("}");
+
5358 WriteLineIndent("sb.append(\"}\")");
+
5359 Indent(-1);
+
5360 WriteLineIndent("}");
+
5361 }
+
5362 else if (field->map)
+
5363 {
+
5364 WriteLineIndent("if true {");
+
5365 Indent(1);
+
5366 WriteLineIndent("var first = true");
+
5367 WriteLineIndent("sb.append(\"" + std::string(first ? "" : ",") + *field->name + "=[\"); sb.append(" + *field->name + ".count.description); sb.append(\"]<{\")");
+
5368 WriteLineIndent("for (key, value) in " + *field->name + " {");
+
5369 Indent(1);
+
5370 WriteLineIndent(ConvertOutputStreamValue(*field->key, "key", false, true, false));
+
5371 WriteLineIndent("sb.append(\"->\")");
+
5372 WriteLineIndent(ConvertOutputStreamValue(*field->type, "value", field->optional, false, true));
+
5373 WriteLineIndent("first = false");
+
5374 Indent(-1);
+
5375 WriteLineIndent("}");
+
5376 WriteLineIndent("sb.append(\"}>\")");
+
5377 Indent(-1);
+
5378 WriteLineIndent("}");
+
5379 }
+
5380 else if (field->hash)
+
5381 {
+
5382 WriteLineIndent("if true {");
+
5383 Indent(1);
+
5384 WriteLineIndent("var first = true");
+
5385 WriteLineIndent("sb.append(\"" + std::string(first ? "" : ",") + *field->name + "=[\"); sb.append(" + *field->name + ".count.description); sb.append(\"][{\")");
+
5386 WriteLineIndent("for (key, value) in " + *field->name + " {");
+
5387 Indent(1);
+
5388 WriteLineIndent(ConvertOutputStreamValue(*field->key, "key", false, true, false));
+
5389 WriteLineIndent("sb.append(\"->\")");
+
5390 WriteLineIndent(ConvertOutputStreamValue(*field->type, "value", field->optional, false, true));
+
5391 WriteLineIndent("first = false");
+
5392 Indent(-1);
+
5393 WriteLineIndent("}");
+
5394 WriteLineIndent("sb.append(\"}]\")");
+
5395 Indent(-1);
+
5396 WriteLineIndent("}");
+
5397 }
+
5398 else
+
5399 WriteLineIndent("sb.append(\"" + std::string(first ? "" : ",") + *field->name + "=\"); " + ConvertOutputStreamValue(*field->type, *field->name, field->optional, false, true));
+
5400 first = false;
+
5401 }
+
5402 }
+
5403 WriteLineIndent("sb.append(\")\")");
+
5404 WriteLineIndent("return sb");
+
5405 Indent(-1);
+
5406 WriteLineIndent("}");
+
5407
+
5408 // Generate struct JSON methods
+
5409 if (JSON())
+
5410 {
+
5411 WriteLineIndent("private enum CodingKeys: String, CodingKey {");
+
5412 Indent(1);
+
5413 if (s->body && !s->body->fields.empty())
+
5414 {
+
5415 for (const auto& field : s->body->fields)
+
5416 {
+
5417 std::string fieldName = (*field->name == "Type") ? ("`Type`") : *field->name;
+
5418 WriteLineIndent("case " + fieldName);
+
5419 }
+
5420 }
+
5421 else
+
5422 WriteLineIndent("case empty");
+
5423 Indent(-1);
+
5424 WriteLineIndent("}");
+
5425
+
5426 WriteLine();
+
5427 WriteLineIndent("public func encode(to encoder: Encoder) throws {");
+
5428 Indent(1);
+
5429 if (s->base && !s->base->empty())
+
5430 WriteLineIndent("try parent.encode(to: encoder)");
+
5431 WriteLineIndent("var container = encoder.container(keyedBy: CodingKeys.self)");
+
5432 if (s->body && !s->body->fields.empty())
+
5433 {
+
5434 for (const auto& field : s->body->fields)
+
5435 {
+
5436 if ((field->vector || field->list || field->set || field->map || field->hash) && *field->type == "timestamp")
+
5437 WriteLineIndent("try container.encode(Dictionary(uniqueKeysWithValues: " + *field->name + ".map { ($0.description, $1.timeIntervalSince1970) }), forKey: ." + *field->name + ")");
+
5438 else if (field->map && (*field->key != "string"))
+
5439 WriteLineIndent("try container.encode(Dictionary(uniqueKeysWithValues: " + *field->name + ".map { ($0.description, $1) }), forKey: ." + *field->name + ")");
+
5440 else if (*field->type == "decimal")
+
5441 {
+
5442 std::string opt = (field->optional) ? "?" : "";
+
5443 WriteLineIndent("try container.encode(" + *field->name + opt + ".description, forKey: ." + *field->name + ")");
+
5444 }
+
5445 else if ((*field->type == "char") || (*field->type == "wchar"))
+
5446 {
+
5447 std::string valueType = (*field->type == "char") ? "UInt8" : "UInt32";
+
5448 std::string utfType = (*field->type == "char") ? "utf8" : "utf16";
+
5449 std::string opt = (field->optional) ? "?" : "";
+
5450 WriteLineIndent("try container.encode(" + *field->name + opt + "." + utfType + ".map { " + valueType + "($0) }[0], forKey: ." + *field->name + ")");
+
5451 }
+
5452 else if (*field->type == "timestamp")
+
5453 {
+
5454 if (field->optional)
+
5455 WriteLineIndent("try container.encode(" + *field->name + " != nil ? floor(" + *field->name + "!" + ".timeIntervalSince1970 * 1000) * 1_000_000 : nil" + ", forKey: ." + *field->name + ")");
+
5456 else
+
5457 WriteLineIndent("try container.encode(floor(" + *field->name + ".timeIntervalSince1970 * 1000) * 1_000_000" + ", forKey: ." + *field->name + ")");
+
5458 }
+
5459 else
+
5460 WriteLineIndent("try container.encode(" + *field->name + ", forKey: ." + *field->name + ")");
+
5461 }
+
5462 }
+
5463 Indent(-1);
+
5464 WriteLineIndent("}");
+
5465
+
5466 WriteLine();
+
5467 WriteLineIndent("public func toJson() throws -> String {");
+
5468 Indent(1);
+
5469 WriteLineIndent("return String(data: try JSONEncoder().encode(self), encoding: .utf8)!");
+
5470 Indent(-1);
+
5471 WriteLineIndent("}");
+
5472
+
5473 WriteLine();
+
5474 WriteLineIndent("public static func fromJson(_ json: String) throws -> " + *s->name + " {");
+
5475 Indent(1);
+
5476 WriteLineIndent("return try JSONDecoder().decode(" + *s->name + ".self, from: json.data(using: .utf8)!)");
+
5477 Indent(-1);
+
5478 WriteLineIndent("}");
+
5479 }
+
5480
+
5481 Indent(-1);
+
5482 WriteLineIndent("}");
+
5483
+
5484 // Generate struct footer
+
5485 GenerateFooter();
+
5486
+
5487 // Store the output file
+
5488 WriteEnd();
+
5489 Store(output);
+
5490
+
5491 // Generate struct field models
+
5492 GenerateStructFieldModel(p, s);
+
5493 GenerateStructModel(p, s);
+
5494
+
5495 // Generate struct final models
+
5496 if (Final())
+
5497 {
+
5498 GenerateStructFinalModel(p, s);
+
5499 GenerateStructModelFinal(p, s);
+
5500 }
+
5501}
+
5502
+
5503void GeneratorSwift::GenerateStructFieldModel(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s)
+
5504{
+
5505 std::string domain = ConvertDomain(p);
+
5506 std::string package = ConvertPackage(p);
+
5507 std::string struct_name = *s->name;
+
5508
+
5509 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "Fbe";
+
5510
+
5511 // Create package path
+
5512 CppCommon::Directory::CreateTree(path);
+
5513
+
5514 // Generate the file
+
5515 CppCommon::Path file = path / ("FieldModel" + *s->name + ".swift");
+
5516 WriteBegin();
+
5517
+
5518 // Generate headers
+
5519 GenerateHeader(CppCommon::Path(_input).filename().string());
+
5520 GenerateImports("", "Foundation");
+
5521 GenerateImports(domain, "Fbe");
+
5522 GenerateImports(p);
+
5523
+
5524 // Generate struct field model begin
+
5525 WriteLine();
+
5526 WriteLineIndent("// Fast Binary Encoding " + *s->name + " field model");
+
5527 WriteLineIndent("public class FieldModel" + *s->name + ": FieldModel {");
+
5528 Indent(1);
+
5529
+
5530 WriteLine();
+
5531 WriteLineIndent("public var _buffer: Buffer");
+
5532 WriteLineIndent("public var _offset: Int");
+
5533
+
5534 // Generate struct field model accessors
+
5535 if (s->base && !s->base->empty())
+
5536 {
+
5537 WriteLine();
+
5538 WriteLineIndent("let parent: " + ConvertBaseFieldName(domain, ConvertPackageName(*s->base), false));
+
5539 }
+
5540 if (s->body && !s->body->fields.empty())
+
5541 {
+
5542 WriteLine();
+
5543 for (const auto& field : s->body->fields)
+
5544 {
+
5545 std::string fieldName = (*field->name == "Type") ? ("`Type`") : *field->name;
+
5546 WriteLineIndent("let " + fieldName + ": " + ConvertTypeFieldDeclaration(domain, *field, false));
+
5547 }
+
5548 }
+
5549
+
5550 // Generate struct field model FBE properties
+
5551 WriteLine();
+
5552 WriteLineIndent("// Field size");
+
5553 WriteLineIndent("public let fbeSize: Int = 4");
+
5554 WriteLine();
+
5555 WriteLineIndent("// Field body size");
+
5556 WriteLineIndent("public let fbeBody: Int");
+
5557
+
5558 // Generate struct field model init() method
+
5559 WriteLine();
+
5560 WriteLineIndent("// Set the struct value (end phase)");
+
5561 WriteLineIndent("public required init() {");
+
5562 Indent(1);
+
5563 WriteLineIndent("let buffer = Buffer()");
+
5564 WriteLineIndent("let offset = 0");
+
5565 WriteLine();
+
5566 WriteLineIndent("_buffer = buffer");
+
5567 WriteLineIndent("_offset = offset");
+
5568
+
5569 // Generate struct field model accessors
+
5570 std::string prev_offset("4");
+
5571 std::string prev_size("4");
+
5572 if (s->base && !s->base->empty())
+
5573 {
+
5574 WriteLine();
+
5575 WriteLineIndent("parent = " + ConvertBaseFieldName(domain, ConvertPackageName(*s->base), false) + "(buffer: buffer, offset: " + prev_offset + " + " + prev_size + ")");
+
5576 prev_offset = "parent.fbeOffset";
+
5577 prev_size = "parent.fbeBody - 4 - 4";
+
5578 }
+
5579 if (s->body && !s->body->fields.empty())
+
5580 {
+
5581 WriteLine();
+
5582 for (const auto& field : s->body->fields)
+
5583 {
+
5584 WriteLineIndent(*field->name + " = " + ConvertTypeFieldInitialization(domain, *field, prev_offset + " + " + prev_size, false));
+
5585 prev_offset = *field->name + ".fbeOffset";
+
5586 prev_size = *field->name + ".fbeSize";
+
5587 }
+
5588 }
+
5589 WriteLine();
+
5590
+
5591 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
5592 WriteLineIndent("var fbeBody = (4 + 4)");
+
5593 else
+
5594 WriteLineIndent("let fbeBody = (4 + 4)");
+
5595
+
5596 Indent(1);
+
5597 if (s->base && !s->base->empty())
+
5598 WriteLineIndent("fbeBody += parent.fbeBody - 4 - 4");
+
5599 if (s->body)
+
5600 for (const auto& field : s->body->fields)
+
5601 WriteLineIndent("fbeBody += " + *field->name + ".fbeSize");
+
5602 Indent(-1);
+
5603 WriteLineIndent("self.fbeBody = fbeBody");
+
5604 Indent(-1);
+
5605 WriteLineIndent("}");
+
5606
+
5607 // Generate struct field model init(...) method
+
5608 WriteLine();
+
5609 WriteLineIndent("// ");
+
5610 WriteLineIndent("public required init(buffer: Buffer = Buffer(), offset: Int = 0) {");
+
5611 Indent(1);
+
5612 WriteLineIndent("_buffer = buffer");
+
5613 WriteLineIndent("_offset = offset");
+
5614 WriteLine();
+
5615 // Generate struct field model accessors
+
5616 prev_offset = "4";
+
5617 prev_size = "4";
+
5618 if (s->base && !s->base->empty())
+
5619 {
+
5620 WriteLineIndent("parent = " + ConvertBaseFieldName(domain, ConvertPackageName(*s->base), false) + "(buffer: buffer, offset: " + prev_offset + " + " + prev_size + ")");
+
5621 prev_offset = "parent.fbeOffset";
+
5622 prev_size = "parent.fbeBody - 4 - 4";
+
5623 }
+
5624 if (s->body)
+
5625 {
+
5626 for (const auto& field : s->body->fields)
+
5627 {
+
5628 WriteLineIndent(*field->name + " = " + ConvertTypeFieldInitialization(domain, *field, prev_offset + " + " + prev_size, false));
+
5629 prev_offset = *field->name + ".fbeOffset";
+
5630 prev_size = *field->name + ".fbeSize";
+
5631 }
+
5632 }
+
5633 WriteLine();
+
5634 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
5635 WriteLineIndent("var fbeBody = (4 + 4)");
+
5636 else
+
5637 WriteLineIndent("let fbeBody = (4 + 4)");
+
5638 Indent(1);
+
5639 if (s->base && !s->base->empty())
+
5640 WriteLineIndent("fbeBody += parent.fbeBody - 4 - 4");
+
5641 if (s->body)
+
5642 for (const auto& field : s->body->fields)
+
5643 WriteLineIndent("fbeBody += " + *field->name + ".fbeSize");
+
5644 Indent(-1);
+
5645 WriteLineIndent("self.fbeBody = fbeBody");
+
5646 Indent(-1);
+
5647 WriteLineIndent("}");
+
5648
+
5649 WriteLine();
+
5650 WriteLineIndent("// Field extra size");
+
5651 WriteLineIndent("public var fbeExtra: Int {");
+
5652 Indent(1);
+
5653 WriteLineIndent("if _buffer.offset + fbeOffset + fbeSize > _buffer.size {");
+
5654 Indent(1);
+
5655 WriteLineIndent("return 0");
+
5656 Indent(-1);
+
5657 WriteLineIndent("}");
+
5658 WriteLine();
+
5659 WriteLineIndent("let fbeStructOffset = Int(readUInt32(offset: fbeOffset))");
+
5660 WriteLineIndent("if (fbeStructOffset == 0) || ((_buffer.offset + fbeStructOffset + 4) > _buffer.size) {");
+
5661 Indent(1);
+
5662 WriteLineIndent("return 0");
+
5663 Indent(-1);
+
5664 WriteLineIndent("}");
+
5665 WriteLine();
+
5666 WriteLineIndent("_buffer.shift(offset: fbeStructOffset)");
+
5667 WriteLine();
+
5668
+
5669 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
5670 WriteLineIndent("var fbeResult = fbeBody");
+
5671 else
+
5672 WriteLineIndent("let fbeResult = fbeBody");
+
5673 Indent(1);
+
5674 if (s->base && !s->base->empty())
+
5675 WriteLineIndent("fbeResult += parent.fbeExtra");
+
5676 if (s->body)
+
5677 for (const auto& field : s->body->fields)
+
5678 WriteLineIndent("fbeResult += " + *field->name + ".fbeExtra");
+
5679 Indent(-1);
+
5680 WriteLine();
+
5681 WriteLineIndent("_buffer.unshift(offset: fbeStructOffset)");
+
5682 WriteLine();
+
5683 WriteLineIndent("return fbeResult");
+
5684 Indent(-1);
+
5685 WriteLineIndent("}");
+
5686
+
5687 WriteLine();
+
5688 WriteLineIndent("// Field type");
+
5689 WriteLineIndent("public var fbeType: Int = fbeTypeConst");
+
5690 if (s->base && !s->base->empty() && (s->type == 0))
+
5691 WriteLineIndent("public static let fbeTypeConst: Int = " + ConvertBaseFieldName(domain, ConvertPackageName(*s->base), false) + ".fbeTypeConst");
+
5692 else
+
5693 WriteLineIndent("public static let fbeTypeConst: Int = " + std::to_string(s->type));
+
5694
+
5695 // Generate struct field model verify() methods
+
5696 WriteLine();
+
5697 WriteLineIndent("// Check if the struct value is valid");
+
5698 WriteLineIndent("func verify(fbeVerifyType: Bool = true) -> Bool {");
+
5699 Indent(1);
+
5700 WriteLineIndent("if (_buffer.offset + fbeOffset + fbeSize) > _buffer.size {");
+
5701 Indent(1);
+
5702 WriteLineIndent("return true");
+
5703 Indent(-1);
+
5704 WriteLineIndent("}");
+
5705 WriteLine();
+
5706 WriteLineIndent("let fbeStructOffset = Int(readUInt32(offset: fbeOffset))");
+
5707 WriteLineIndent("if (fbeStructOffset == 0) || ((_buffer.offset + fbeStructOffset + 4 + 4) > _buffer.size) {");
+
5708 Indent(1);
+
5709 WriteLineIndent("return false");
+
5710 Indent(-1);
+
5711 WriteLineIndent("}");
+
5712 WriteLine();
+
5713 WriteLineIndent("let fbeStructSize = Int(readUInt32(offset: fbeStructOffset))");
+
5714 WriteLineIndent("if fbeStructSize < (4 + 4) {");
+
5715 Indent(1);
+
5716 WriteLineIndent("return false");
+
5717 Indent(-1);
+
5718 WriteLineIndent("}");
+
5719 WriteLine();
+
5720 WriteLineIndent("let fbeStructType = Int(readUInt32(offset: fbeStructOffset + 4))");
+
5721 WriteLineIndent("if fbeVerifyType && (fbeStructType != fbeType) {");
+
5722 Indent(1);
+
5723 WriteLineIndent("return false");
+
5724 Indent(-1);
+
5725 WriteLineIndent("}");
+
5726 WriteLine();
+
5727 WriteLineIndent("_buffer.shift(offset: fbeStructOffset)");
+
5728 WriteLineIndent("let fbeResult = verifyFields(fbeStructSize: fbeStructSize)");
+
5729 WriteLineIndent("_buffer.unshift(offset: fbeStructOffset)");
+
5730 WriteLineIndent("return fbeResult");
+
5731 Indent(-1);
+
5732 WriteLineIndent("}");
+
5733
+
5734 // Generate struct field model verifyFields() method
+
5735 WriteLine();
+
5736 WriteLineIndent("// Check if the struct fields are valid");
+
5737 WriteLineIndent("public func verifyFields(fbeStructSize: Int) -> Bool {");
+
5738 Indent(1);
+
5739 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
5740 {
+
5741 WriteLineIndent("var fbeCurrentSize = 4 + 4");
+
5742 if (s->base && !s->base->empty())
+
5743 {
+
5744 WriteLine();
+
5745 WriteLineIndent("if fbeCurrentSize + parent.fbeBody - 4 - 4 > fbeStructSize {");
+
5746 Indent(1);
+
5747 WriteLineIndent("return true");
+
5748 Indent(-1);
+
5749 WriteLineIndent("}");
+
5750 WriteLineIndent("if !parent.verifyFields(fbeStructSize: fbeStructSize) {");
+
5751 Indent(1);
+
5752 WriteLineIndent("return false");
+
5753 Indent(-1);
+
5754 WriteLineIndent("}");
+
5755 WriteLineIndent("fbeCurrentSize += parent.fbeBody - 4 - 4");
+
5756 }
+
5757 if (s->body)
+
5758 {
+
5759 for (const auto& field : s->body->fields)
+
5760 {
+
5761 WriteLine();
+
5762 WriteLineIndent("if (fbeCurrentSize + " + *field->name + ".fbeSize) > fbeStructSize {");
+
5763 Indent(1);
+
5764 WriteLineIndent("return true");
+
5765 Indent(-1);
+
5766 WriteLineIndent("}");
+
5767 WriteLineIndent("if !" + *field->name + ".verify() {");
+
5768 Indent(1);
+
5769 WriteLineIndent("return false");
+
5770 Indent(-1);
+
5771 WriteLineIndent("}");
+
5772 WriteLineIndent("fbeCurrentSize += " + *field->name + ".fbeSize");
+
5773 }
+
5774 }
+
5775 WriteLine();
+
5776 }
+
5777 WriteLineIndent("return true");
+
5778 Indent(-1);
+
5779 WriteLineIndent("}");
+
5780
+
5781 // Generate struct field model getBegin() method
+
5782 WriteLine();
+
5783 WriteLineIndent("// Get the struct value (begin phase)");
+
5784 WriteLineIndent("func getBegin() -> Int {");
+
5785 Indent(1);
+
5786 WriteLineIndent("if _buffer.offset + fbeOffset + fbeSize > _buffer.size {");
+
5787 Indent(1);
+
5788 WriteLineIndent("return 0");
+
5789 Indent(-1);
+
5790 WriteLineIndent("}");
+
5791 WriteLine();
+
5792 WriteLineIndent("let fbeStructOffset = Int(readUInt32(offset: fbeOffset))");
+
5793 WriteLineIndent("if (fbeStructOffset == 0) || ((_buffer.offset + fbeStructOffset + 4 + 4) > _buffer.size) {");
+
5794 Indent(1);
+
5795 WriteLineIndent("assertionFailure(\"Model is broken!\")");
+
5796 WriteLineIndent("return 0");
+
5797 Indent(-1);
+
5798 WriteLineIndent("}");
+
5799 WriteLine();
+
5800 WriteLineIndent("let fbeStructSize = Int(readUInt32(offset: fbeStructOffset))");
+
5801 WriteLineIndent("if fbeStructSize < 4 + 4 {");
+
5802 Indent(1);
+
5803 WriteLineIndent("assertionFailure(\"Model is broken!\")");
+
5804 WriteLineIndent("return 0");
+
5805 Indent(-1);
+
5806 WriteLineIndent("}");
+
5807 WriteLine();
+
5808 WriteLineIndent("_buffer.shift(offset: fbeStructOffset)");
+
5809 WriteLineIndent("return fbeStructOffset");
+
5810 Indent(-1);
+
5811 WriteLineIndent("}");
+
5812
+
5813 // Generate struct field model getEnd() method
+
5814 WriteLine();
+
5815 WriteLineIndent("// Get the struct value (end phase)");
+
5816 WriteLineIndent("func getEnd(fbeBegin: Int) {");
+
5817 Indent(1);
+
5818 WriteLineIndent("_buffer.unshift(offset: fbeBegin)");
+
5819 Indent(-1);
+
5820 WriteLineIndent("}");
+
5821
+
5822 // Generate struct field model get() methods
+
5823 WriteLine();
+
5824 WriteLineIndent("// Get the struct value");
+
5825 WriteLineIndent("public func get() -> " + struct_name + " {");
+
5826 Indent(1);
+
5827 WriteLineIndent("var fbeValue = " + struct_name+ "()");
+
5828 WriteLineIndent("return get(fbeValue: &fbeValue)");
+
5829 Indent(-1);
+
5830 WriteLineIndent("}");
+
5831
+
5832 WriteLine();
+
5833 WriteLineIndent("public func get(fbeValue: inout " + struct_name + ") -> " + struct_name + " {");
+
5834 Indent(1);
+
5835 WriteLineIndent("let fbeBegin = getBegin()");
+
5836 WriteLineIndent("if fbeBegin == 0 {");
+
5837 Indent(1);
+
5838 WriteLineIndent("return fbeValue");
+
5839 Indent(-1);
+
5840 WriteLineIndent("}");
+
5841 WriteLine();
+
5842 WriteLineIndent("let fbeStructSize = Int(readUInt32(offset: 0))");
+
5843 WriteLineIndent("getFields(fbeValue: &fbeValue, fbeStructSize: fbeStructSize)");
+
5844 WriteLineIndent("getEnd(fbeBegin: fbeBegin)");
+
5845 WriteLineIndent("return fbeValue");
+
5846 Indent(-1);
+
5847 WriteLineIndent("}");
+
5848
+
5849 // Generate struct field model getFields() method
+
5850 WriteLine();
+
5851 WriteLineIndent("// Get the struct fields values");
+
5852 WriteLineIndent("public func getFields(fbeValue: inout " + struct_name + ", fbeStructSize: Int) {");
+
5853 Indent(1);
+
5854 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
5855 {
+
5856 WriteLineIndent("var fbeCurrentSize = 4 + 4");
+
5857 if (s->base && !s->base->empty())
+
5858 {
+
5859 WriteLine();
+
5860 WriteLineIndent("if fbeCurrentSize + parent.fbeBody - 4 - 4 <= fbeStructSize {");
+
5861 Indent(1);
+
5862 WriteLineIndent("parent.getFields(fbeValue: &fbeValue.parent, fbeStructSize: fbeStructSize)");
+
5863 Indent(-1);
+
5864 WriteLineIndent("}");
+
5865 WriteLineIndent("fbeCurrentSize += parent.fbeBody - 4 - 4");
+
5866 }
+
5867 if (s->body)
+
5868 {
+
5869 for (const auto& field : s->body->fields)
+
5870 {
+
5871 WriteLine();
+
5872 WriteLineIndent("if fbeCurrentSize + " + *field->name + ".fbeSize <= fbeStructSize {");
+
5873 Indent(1);
+
5874 if (field->array || field->vector || field->list || field->set || field->map || field->hash)
+
5875 WriteLineIndent(*field->name + ".get(values: &fbeValue." + *field->name + ")");
+
5876 else
+
5877 WriteLineIndent("fbeValue." + *field->name + " = " + *field->name + ".get(" + (field->value ? "defaults: " + ConvertConstant(domain, package, *field->type, *field->value, field->optional) : "") + ")");
+
5878 Indent(-1);
+
5879 WriteLineIndent("} else {");
+
5880 Indent(1);
+
5881 if (field->vector || field->list || field->set || field->map || field->hash)
+
5882 WriteLineIndent("fbeValue." + *field->name + ".removeAll()");
+
5883 else
+
5884 WriteLineIndent("fbeValue." + *field->name + " = " + ConvertDefault(domain, package, *field));
+
5885 Indent(-1);
+
5886 WriteLineIndent("}");
+
5887 WriteLineIndent("fbeCurrentSize += " + *field->name + ".fbeSize");
+
5888 }
+
5889 }
+
5890 }
+
5891 Indent(-1);
+
5892 WriteLineIndent("}");
+
5893
+
5894 // Generate struct field model setBegin() method
+
5895 WriteLine();
+
5896 WriteLineIndent("// Set the struct value (begin phase)");
+
5897 WriteLineIndent("func setBegin() throws -> Int {");
+
5898 Indent(1);
+
5899 WriteLineIndent("if (_buffer.offset + fbeOffset + fbeSize) > _buffer.size {");
+
5900 Indent(1);
+
5901 WriteLineIndent("assertionFailure(\"Model is broken!\")");
+
5902 WriteLineIndent("return 0");
+
5903 Indent(-1);
+
5904 WriteLineIndent("}");
+
5905 WriteLine();
+
5906 WriteLineIndent("let fbeStructSize = fbeBody");
+
5907 WriteLineIndent("let fbeStructOffset = try _buffer.allocate(size: fbeStructSize) - _buffer.offset");
+
5908 WriteLineIndent("if (fbeStructOffset <= 0) || ((_buffer.offset + fbeStructOffset + fbeStructSize) > _buffer.size) {");
+
5909 Indent(1);
+
5910 WriteLineIndent("assertionFailure(\"Model is broken!\")");
+
5911 WriteLineIndent("return 0");
+
5912 Indent(-1);
+
5913 WriteLineIndent("}");
+
5914 WriteLine();
+
5915 WriteLineIndent("write(offset: fbeOffset, value: UInt32(fbeStructOffset))");
+
5916 WriteLineIndent("write(offset: fbeStructOffset, value: UInt32(fbeStructSize))");
+
5917 WriteLineIndent("write(offset: fbeStructOffset + 4, value: UInt32(fbeType))");
+
5918 WriteLine();
+
5919 WriteLineIndent("_buffer.shift(offset: fbeStructOffset)");
+
5920 WriteLineIndent("return fbeStructOffset");
+
5921 Indent(-1);
+
5922 WriteLineIndent("}");
+
5923
+
5924 // Generate struct field model setEnd() method
+
5925 WriteLine();
+
5926 WriteLineIndent("// Set the struct value (end phase)");
+
5927 WriteLineIndent("public func setEnd(fbeBegin: Int) {");
+
5928 Indent(1);
+
5929 WriteLineIndent("_buffer.unshift(offset: fbeBegin)");
+
5930 Indent(-1);
+
5931 WriteLineIndent("}");
+
5932
+
5933 // Generate struct field model set() method
+
5934 WriteLine();
+
5935 WriteLineIndent("// Set the struct value");
+
5936 WriteLineIndent("public func set(value fbeValue: " + struct_name + ") throws {");
+
5937 Indent(1);
+
5938 WriteLineIndent("let fbeBegin = try setBegin()");
+
5939 WriteLineIndent("if fbeBegin == 0 {");
+
5940 Indent(1);
+
5941 WriteLineIndent("return");
+
5942 Indent(-1);
+
5943 WriteLineIndent("}");
+
5944 WriteLine();
+
5945 WriteLineIndent("try setFields(fbeValue: fbeValue)");
+
5946 WriteLineIndent("setEnd(fbeBegin: fbeBegin)");
+
5947 Indent(-1);
+
5948 WriteLineIndent("}");
+
5949
+
5950 // Generate struct field model setFields() method
+
5951 WriteLine();
+
5952 WriteLineIndent("// Set the struct fields values");
+
5953 WriteLineIndent("public func setFields(fbeValue: " + struct_name + ") throws {");
+
5954 Indent(1);
+
5955 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
5956 {
+
5957 if (s->base && !s->base->empty())
+
5958 WriteLineIndent("try parent.setFields(fbeValue: fbeValue.parent)");
+
5959 if (s->body)
+
5960 for (const auto& field : s->body->fields)
+
5961 WriteLineIndent("try " + *field->name + ".set(value: fbeValue." + *field->name + ")");
+
5962 }
+
5963 Indent(-1);
+
5964 WriteLineIndent("}");
+
5965
+
5966 // Generate struct field model end
+
5967 Indent(-1);
+
5968 WriteLineIndent("}");
+
5969
+
5970 // Generate footer
+
5971 GenerateFooter();
+
5972
+
5973 // Store the file
+
5974 WriteEnd();
+
5975 Store(file);
+
5976}
+
5977
+
5978void GeneratorSwift::GenerateStructModel(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s)
+
5979{
+
5980 std::string domain = ConvertDomain(p);
+
5981 std::string package = ConvertPackage(p);
+
5982 std::string struct_name = *s->name;
+
5983
+
5984 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "Fbe";
+
5985
+
5986 // Create package path
+
5987 CppCommon::Directory::CreateTree(path);
+
5988
+
5989 // Generate the file
+
5990 CppCommon::Path file = path / (*s->name + "Model.swift");
+
5991 WriteBegin();
+
5992
+
5993 // Generate headers
+
5994 GenerateHeader(CppCommon::Path(_input).filename().string());
+
5995 GenerateImports(domain, "Fbe");
+
5996
+
5997 // Generate struct model begin
+
5998 WriteLine();
+
5999 WriteLineIndent("// Fast Binary Encoding " + *s->name + " model");
+
6000 WriteLineIndent("public class " + *s->name + "Model: Model {");
+
6001 Indent(1);
+
6002
+
6003 // Generate struct model accessor
+
6004 WriteLineIndent("public let model: FieldModel" + *s->name);
+
6005
+
6006 // Generate struct model init(buffer: Buffer) method
+
6007 WriteLine();
+
6008 WriteLineIndent("public override init(buffer: Buffer = Buffer()) {");
+
6009 Indent(1);
+
6010 WriteLineIndent("model = FieldModel" + *s->name + "(buffer: buffer, offset: 4)");
+
6011 WriteLineIndent("super.init(buffer: buffer)");
+
6012 Indent(-1);
+
6013 WriteLineIndent("}");
+
6014
+
6015 // Generate struct model FBE properties
+
6016 WriteLine();
+
6017 WriteLineIndent("// Model size");
+
6018 WriteLineIndent("public func fbeSize() -> Int { model.fbeSize + model.fbeExtra }");
+
6019 WriteLineIndent("// Model type");
+
6020 WriteLineIndent("public var fbeType: Int = fbeTypeConst");
+
6021 WriteLineIndent("static let fbeTypeConst: Int = FieldModel" + *s->name + ".fbeTypeConst");
+
6022
+
6023 // Generate struct model verify() method
+
6024 WriteLine();
+
6025 WriteLineIndent("// Check if the struct value is valid");
+
6026 WriteLineIndent("public func verify() -> Bool {");
+
6027 Indent(1);
+
6028 WriteLineIndent("if buffer.offset + model.fbeOffset - 4 > buffer.size {");
+
6029 Indent(1);
+
6030 WriteLineIndent("return false");
+
6031 Indent(-1);
+
6032 WriteLineIndent("}");
+
6033 WriteLine();
+
6034 WriteLineIndent("let fbeFullSize = Int(readUInt32(offset: model.fbeOffset - 4))");
+
6035 WriteLineIndent("if fbeFullSize < model.fbeSize {");
+
6036 Indent(1);
+
6037 WriteLineIndent("return false");
+
6038 Indent(-1);
+
6039 WriteLineIndent("}");
+
6040 WriteLine();
+
6041 WriteLineIndent("return model.verify()");
+
6042 Indent(-1);
+
6043 WriteLineIndent("}");
+
6044
+
6045 // Create a new model (begin phase)
+
6046 WriteLine();
+
6047 WriteLineIndent("// Create a new model (begin phase)");
+
6048 WriteLineIndent("public func createBegin() throws -> Int {");
+
6049 Indent(1);
+
6050 WriteLineIndent("return try buffer.allocate(size: 4 + model.fbeSize)");
+
6051 Indent(-1);
+
6052 WriteLineIndent("}");
+
6053
+
6054 // Generate struct model createEnd() method
+
6055 WriteLine();
+
6056 WriteLineIndent("// Create a new model (end phase)");
+
6057 WriteLineIndent("public func createEnd(fbeBegin: Int) -> Int {");
+
6058 Indent(1);
+
6059 WriteLineIndent("let fbeEnd = buffer.size");
+
6060 WriteLineIndent("let fbeFullSize = fbeEnd - fbeBegin");
+
6061 WriteLineIndent("write(offset: model.fbeOffset - 4, value: UInt32(fbeFullSize))");
+
6062 WriteLineIndent("return fbeFullSize");
+
6063 Indent(-1);
+
6064 WriteLineIndent("}");
+
6065
+
6066 // Generate struct model serialize() method
+
6067 WriteLine();
+
6068 WriteLineIndent("// Serialize the struct value");
+
6069 WriteLineIndent("public func serialize(value: " + struct_name + ") throws -> Int {");
+
6070 Indent(1);
+
6071 WriteLineIndent("let fbeBegin = try createBegin()");
+
6072 WriteLineIndent("try model.set(value: value)");
+
6073 WriteLineIndent("return createEnd(fbeBegin: fbeBegin)");
+
6074 Indent(-1);
+
6075 WriteLineIndent("}");
+
6076
+
6077 // Generate struct model deserialize() methods
+
6078 WriteLine();
+
6079 WriteLineIndent("// Deserialize the struct value");
+
6080 WriteLineIndent("public func deserialize() -> " + struct_name + " { var value = " + struct_name + "(); _ = deserialize(value: &value); return value }");
+
6081 WriteLineIndent("public func deserialize(value: inout " + struct_name + ") -> Int {");
+
6082 Indent(1);
+
6083 WriteLineIndent("if buffer.offset + model.fbeOffset - 4 > buffer.size {");
+
6084 Indent(1);
+
6085 WriteLineIndent("value = " + struct_name + "()");
+
6086 WriteLineIndent("return 0");
+
6087 Indent(-1);
+
6088 WriteLineIndent("}");
+
6089 WriteLine();
+
6090 WriteLineIndent("let fbeFullSize = Int(readUInt32(offset: model.fbeOffset - 4))");
+
6091 WriteLineIndent("if fbeFullSize < model.fbeSize {");
+
6092 Indent(1);
+
6093 WriteLineIndent("assertionFailure(\"Model is broken!\")");
+
6094 WriteLineIndent("value = " + struct_name + "()");
+
6095 WriteLineIndent("return 0");
+
6096 Indent(-1);
+
6097 WriteLineIndent("}");
+
6098 WriteLine();
+
6099 WriteLineIndent("value = model.get(fbeValue: &value)");
+
6100 WriteLineIndent("return fbeFullSize");
+
6101 Indent(-1);
+
6102 WriteLineIndent("}");
+
6103
+
6104 // Generate struct model next() method
+
6105 WriteLine();
+
6106 WriteLineIndent("// Move to the next struct value");
+
6107 WriteLineIndent("public func next(prev: Int) {");
+
6108 Indent(1);
+
6109 WriteLineIndent("model.fbeShift(size: prev)");
+
6110 Indent(-1);
+
6111 WriteLineIndent("}");
+
6112
+
6113 // Generate struct model end
+
6114 Indent(-1);
+
6115 WriteLineIndent("}");
+
6116
+
6117 // Generate footer
+
6118 GenerateFooter();
+
6119
+
6120 // Store the file
+
6121 WriteEnd();
+
6122 Store(file);
+
6123}
+
6124
+
6125void GeneratorSwift::GenerateStructFinalModel(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s)
+
6126{
+
6127 std::string domain = ConvertDomain(p);
+
6128 std::string package = ConvertPackage(p);
+
6129 std::string struct_name = *s->name;
+
6130
+
6131 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "Fbe";
+
6132
+
6133 // Create package path
+
6134 CppCommon::Directory::CreateTree(path);
+
6135
+
6136 // Generate the file
+
6137 CppCommon::Path file = path / ("FinalModel" + *s->name + ".swift");
+
6138 WriteBegin();
+
6139
+
6140 // Generate headers
+
6141 GenerateHeader(CppCommon::Path(_input).filename().string());
+
6142 GenerateImports(domain, "Fbe");
+
6143 GenerateImports(p);
+
6144
+
6145 // Generate struct final model begin
+
6146 WriteLine();
+
6147 WriteLineIndent("// Fast Binary Encoding " + *s->name + " final model");
+
6148 WriteLineIndent("public class FinalModel" + *s->name + ": FinalModel {");
+
6149 Indent(1);
+
6150
+
6151 WriteLineIndent("public var _buffer: Buffer");
+
6152 WriteLineIndent("public var _offset: Int");
+
6153
+
6154 WriteLine();
+
6155
+
6156 // Generate struct final model accessors
+
6157 if (s->base && !s->base->empty())
+
6158 WriteLineIndent("let parent: " + ConvertBaseFieldName(domain, ConvertPackageName(*s->base), true));
+
6159 if (s->body)
+
6160 for (const auto& field : s->body->fields)
+
6161 WriteLineIndent("let " + *field->name + ": " + ConvertTypeFieldDeclaration(domain, *field, true));
+
6162
+
6163 WriteLine();
+
6164 WriteLineIndent("// Field type");
+
6165 WriteLineIndent("public var fbeType: Int = fbeTypeConst");
+
6166 WriteLine();
+
6167 if (s->base && !s->base->empty() && (s->type == 0))
+
6168 WriteLineIndent("public static let fbeTypeConst: Int = " + ConvertBaseFieldName(domain, ConvertPackageName(*s->base), true) + ".fbeTypeConst");
+
6169 else
+
6170 WriteLineIndent("public static let fbeTypeConst: Int = " + std::to_string(s->type));
+
6171
+
6172 // Generate struct final model init methods
+
6173 WriteLine();
+
6174 WriteLineIndent("public required init(buffer: Buffer, offset: Int) {");
+
6175 Indent(1);
+
6176 WriteLineIndent("_buffer = buffer");
+
6177 WriteLineIndent("_offset = offset");
+
6178 WriteLine();
+
6179 if (s->base && !s->base->empty())
+
6180 WriteLineIndent("parent = " + ConvertBaseFieldName(domain, ConvertPackageName(*s->base), true) + "(buffer: buffer, offset: 0)");
+
6181 if (s->body)
+
6182 for (const auto& field : s->body->fields)
+
6183 WriteLineIndent(*field->name + " = " + ConvertTypeFieldInitialization(domain, *field, "0", true));
+
6184 Indent(-1);
+
6185 WriteLineIndent("}");
+
6186
+
6187 // Generate struct final model FBE properties
+
6188 WriteLine();
+
6189 WriteLineIndent("// Get the allocation size");
+
6190 WriteLineIndent("public func fbeAllocationSize(value fbeValue: " + struct_name + ") -> Int {");
+
6191 Indent(1);
+
6192 WriteLineIndent("return 0");
+
6193 Indent(1);
+
6194 if (s->base && !s->base->empty())
+
6195 WriteLineIndent("+ parent.fbeAllocationSize(value: fbeValue.parent)");
+
6196 if (s->body)
+
6197 for (const auto& field : s->body->fields)
+
6198 WriteLineIndent("+ " + *field->name + ".fbeAllocationSize(value: fbeValue." + *field->name + ")");
+
6199 Indent(-1);
+
6200 Indent(-1);
+
6201 WriteLineIndent("}");
+
6202
+
6203 // Generate struct final model verify() methods
+
6204 WriteLine();
+
6205 WriteLineIndent("// Check if the struct value is valid");
+
6206 WriteLineIndent("public func verify() -> Int {");
+
6207 Indent(1);
+
6208 WriteLineIndent("_buffer.shift(offset: fbeOffset)");
+
6209 WriteLineIndent("let fbeResult = verifyFields()");
+
6210 WriteLineIndent("_buffer.unshift(offset: fbeOffset)");
+
6211 WriteLineIndent("return fbeResult");
+
6212 Indent(-1);
+
6213 WriteLineIndent("}");
+
6214
+
6215 // Generate struct final model verifyFields() method
+
6216 WriteLine();
+
6217 WriteLineIndent("// Check if the struct fields are valid");
+
6218 WriteLineIndent("public func verifyFields() -> Int {");
+
6219 Indent(1);
+
6220 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
6221 {
+
6222 WriteLineIndent("var fbeCurrentOffset: Int = 0");
+
6223 WriteLineIndent("var fbeFieldSize: Int = 0");
+
6224 if (s->base && !s->base->empty())
+
6225 {
+
6226 WriteLine();
+
6227 WriteLineIndent("parent.fbeOffset = fbeCurrentOffset");
+
6228 WriteLineIndent("fbeFieldSize = parent.verifyFields()");
+
6229 WriteLineIndent("if fbeFieldSize == Int.max {");
+
6230 Indent(1);
+
6231 WriteLineIndent("return Int.max");
+
6232 Indent(-1);
+
6233 WriteLineIndent("}");
+
6234 WriteLineIndent("fbeCurrentOffset += fbeFieldSize");
+
6235 }
+
6236 if (s->body)
+
6237 {
+
6238 for (const auto& field : s->body->fields)
+
6239 {
+
6240 WriteLine();
+
6241 WriteLineIndent(*field->name + ".fbeOffset = fbeCurrentOffset");
+
6242 WriteLineIndent("fbeFieldSize = " + *field->name + ".verify()");
+
6243 WriteLineIndent("if fbeFieldSize == Int.max {");
+
6244 Indent(1);
+
6245 WriteLineIndent("return Int.max");
+
6246 Indent(-1);
+
6247 WriteLineIndent("}");
+
6248 WriteLineIndent("fbeCurrentOffset += fbeFieldSize");
+
6249 }
+
6250 }
+
6251 WriteLine();
+
6252 WriteLineIndent("return fbeCurrentOffset");
+
6253 }
+
6254 else
+
6255 WriteLineIndent("return 0");
+
6256 Indent(-1);
+
6257 WriteLineIndent("}");
+
6258
+
6259 // Generate struct final model get() methods
+
6260 WriteLine();
+
6261 WriteLineIndent("// Get the struct value");
+
6262 WriteLineIndent("public func get(size: inout Size) -> " + struct_name + " {");
+
6263 Indent(1);
+
6264 WriteLineIndent("var fbeValue = " + struct_name + "()");
+
6265 WriteLineIndent("return get(size: &size, fbeValue: &fbeValue)");
+
6266 Indent(-1);
+
6267 WriteLineIndent("}");
+
6268
+
6269 WriteLine();
+
6270 WriteLineIndent("// Get the struct value");
+
6271 WriteLineIndent("public func get(size: inout Size, fbeValue: inout " + struct_name + ") -> " + struct_name + " {");
+
6272 Indent(1);
+
6273 WriteLineIndent("_buffer.shift(offset: fbeOffset)");
+
6274 WriteLineIndent("size.value = getFields(fbeValue: &fbeValue)");
+
6275 WriteLineIndent("_buffer.unshift(offset: fbeOffset)");
+
6276 WriteLineIndent("return fbeValue");
+
6277 Indent(-1);
+
6278 WriteLineIndent("}");
+
6279
+
6280 // Generate struct final model getFields() method
+
6281 WriteLine();
+
6282 WriteLineIndent("// Get the struct fields values");
+
6283 WriteLineIndent("public func getFields(fbeValue: inout " + struct_name + ") -> Int {");
+
6284 Indent(1);
+
6285 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
6286 {
+
6287 WriteLineIndent("var fbeCurrentOffset: Int = 0");
+
6288 WriteLineIndent("var fbeCurrentSize: Int = 0");
+
6289 WriteLineIndent("var fbeFieldSize = Size()");
+
6290
+
6291 if (s->base && !s->base->empty())
+
6292 {
+
6293 WriteLine();
+
6294 WriteLineIndent("parent.fbeOffset = fbeCurrentOffset");
+
6295 WriteLineIndent("fbeFieldSize.value = parent.getFields(fbeValue: &fbeValue.parent)");
+
6296 WriteLineIndent("fbeCurrentOffset += fbeFieldSize.value");
+
6297 WriteLineIndent("fbeCurrentSize += fbeFieldSize.value");
+
6298 }
+
6299 if (s->body)
+
6300 {
+
6301 for (const auto& field : s->body->fields)
+
6302 {
+
6303 WriteLine();
+
6304 WriteLineIndent(*field->name + ".fbeOffset = fbeCurrentOffset");
+
6305 if (field->array || field->vector || field->list || field->set || field->map || field->hash)
+
6306 WriteLineIndent("fbeFieldSize.value = " + *field->name + ".get(values: &fbeValue." + *field->name + ")");
+
6307 else
+
6308 WriteLineIndent("fbeValue." + *field->name + " = " + *field->name + ".get(size: &fbeFieldSize)");
+
6309 WriteLineIndent("fbeCurrentOffset += fbeFieldSize.value");
+
6310 WriteLineIndent("fbeCurrentSize += fbeFieldSize.value");
+
6311 }
+
6312 }
+
6313 WriteLine();
+
6314 WriteLineIndent("return fbeCurrentSize");
+
6315 }
+
6316 else
+
6317 WriteLineIndent("return 0");
+
6318 Indent(-1);
+
6319 WriteLineIndent("}");
+
6320
+
6321 // Generate struct final model set() method
+
6322 WriteLine();
+
6323 WriteLineIndent("// Set the struct value");
+
6324 WriteLineIndent("public func set(value fbeValue: " + struct_name + ") throws -> Int {");
+
6325 Indent(1);
+
6326 WriteLineIndent("_buffer.shift(offset: fbeOffset)");
+
6327 WriteLineIndent("let fbeSize = try setFields(fbeValue: fbeValue)");
+
6328 WriteLineIndent("_buffer.unshift(offset: fbeOffset)");
+
6329 WriteLineIndent("return fbeSize");
+
6330 Indent(-1);
+
6331 WriteLineIndent("}");
+
6332
+
6333 // Generate struct final model setFields() method
+
6334 WriteLine();
+
6335 WriteLineIndent("// Set the struct fields values");
+
6336 WriteLineIndent("public func setFields(fbeValue: " + struct_name + ") throws -> Int {");
+
6337 Indent(1);
+
6338 if ((s->base && !s->base->empty()) || (s->body && !s->body->fields.empty()))
+
6339 {
+
6340 WriteLineIndent("var fbeCurrentOffset: Int = 0");
+
6341 WriteLineIndent("var fbeCurrentSize: Int = 0");
+
6342 WriteLineIndent("let fbeFieldSize = Size()");
+
6343 if (s->base && !s->base->empty())
+
6344 {
+
6345 WriteLine();
+
6346 WriteLineIndent("parent.fbeOffset = fbeCurrentOffset");
+
6347 WriteLineIndent("fbeFieldSize.value = try parent.setFields(fbeValue: fbeValue.parent)");
+
6348 WriteLineIndent("fbeCurrentOffset += fbeFieldSize.value");
+
6349 WriteLineIndent("fbeCurrentSize += fbeFieldSize.value");
+
6350 }
+
6351 if (s->body)
+
6352 {
+
6353 for (const auto& field : s->body->fields)
+
6354 {
+
6355 WriteLine();
+
6356 WriteLineIndent(*field->name + ".fbeOffset = fbeCurrentOffset");
+
6357 WriteLineIndent("fbeFieldSize.value = try " + *field->name + ".set(value: fbeValue." + *field->name + ")");
+
6358 WriteLineIndent("fbeCurrentOffset += fbeFieldSize.value");
+
6359 WriteLineIndent("fbeCurrentSize += fbeFieldSize.value");
+
6360 }
+
6361 }
+
6362 WriteLine();
+
6363 WriteLineIndent("return fbeCurrentSize");
+
6364 }
+
6365 else
+
6366 WriteLineIndent("return 0");
+
6367 Indent(-1);
+
6368 WriteLineIndent("}");
+
6369
+
6370 // Generate struct final model end
+
6371 Indent(-1);
+
6372 WriteLineIndent("}");
+
6373
+
6374 // Generate footer
+
6375 GenerateFooter();
+
6376
+
6377 // Store the file
+
6378 WriteEnd();
+
6379 Store(file);
+
6380}
+
6381
+
6382void GeneratorSwift::GenerateStructModelFinal(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s)
+
6383{
+
6384 std::string domain = ConvertDomain(p);
+
6385 std::string package = ConvertPackage(p);
+
6386 std::string struct_name = *s->name;
+
6387
+
6388 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "Fbe";
+
6389
+
6390 // Create package path
+
6391 CppCommon::Directory::CreateTree(path);
+
6392
+
6393 // Generate the file
+
6394 CppCommon::Path file = path / (*s->name + "FinalModel.swift");
+
6395 WriteBegin();
+
6396
+
6397 // Generate headers
+
6398 GenerateHeader(CppCommon::Path(_input).filename().string());
+
6399 GenerateImports(domain, "Fbe");
+
6400
+
6401 // Generate struct model final begin
+
6402 WriteLine();
+
6403 WriteLineIndent("// Fast Binary Encoding " + *s->name + " final model");
+
6404 WriteLineIndent("public class " + *s->name + "FinalModel: Model {");
+
6405 Indent(1);
+
6406
+
6407 // Generate struct model final accessor
+
6408 WriteLineIndent("private let _model: FinalModel" + *s->name);
+
6409
+
6410 // Generate struct final model init methods
+
6411 WriteLine();
+
6412 WriteLineIndent("public override init(buffer: Buffer = Buffer()) {");
+
6413 Indent(1);
+
6414 WriteLineIndent("_model = FinalModel" + *s->name + "(buffer: buffer, offset: 8)");
+
6415 WriteLine();
+
6416 WriteLineIndent("super.init(buffer: buffer)");
+
6417 Indent(-1);
+
6418 WriteLineIndent("}");
+
6419
+
6420 // Generate struct model final FBE properties
+
6421 WriteLine();
+
6422 WriteLineIndent("// Model type");
+
6423 WriteLineIndent("public var fbeType: Int = fbeTypeConst");
+
6424 WriteLine();
+
6425 WriteLineIndent("static let fbeTypeConst: Int = FinalModel" + *s->name + ".fbeTypeConst");
+
6426
+
6427 // Generate struct model final verify() method
+
6428 WriteLine();
+
6429 WriteLineIndent("// Check if the struct value is valid");
+
6430 WriteLineIndent("public func verify() -> Bool {");
+
6431 Indent(1);
+
6432 WriteLineIndent("if (buffer.offset + _model.fbeOffset) > buffer.size {");
+
6433 Indent(1);
+
6434 WriteLineIndent("return false");
+
6435 Indent(-1);
+
6436 WriteLineIndent("}");
+
6437 WriteLine();
+
6438 WriteLineIndent("let fbeStructSize = Int(readUInt32(offset: _model.fbeOffset - 8))");
+
6439 WriteLineIndent("let fbeStructType = Int(readUInt32(offset: _model.fbeOffset - 4))");
+
6440 WriteLineIndent("if (fbeStructSize <= 0) || (fbeStructType != fbeType) {");
+
6441 Indent(1);
+
6442 WriteLineIndent("return false");
+
6443 Indent(-1);
+
6444 WriteLineIndent("}");
+
6445 WriteLine();
+
6446 WriteLineIndent("return ((8 + _model.verify()) == fbeStructSize)");
+
6447 Indent(-1);
+
6448 WriteLineIndent("}");
+
6449
+
6450 // Generate struct model final serialize() method
+
6451 WriteLine();
+
6452 WriteLineIndent("// Serialize the struct value");
+
6453 WriteLineIndent("public func serialize(value: " + struct_name + ") throws -> Int {");
+
6454 Indent(1);
+
6455 WriteLineIndent("let fbeInitialSize = buffer.size");
+
6456 WriteLine();
+
6457 WriteLineIndent("let fbeStructType = fbeType");
+
6458 WriteLineIndent("var fbeStructSize = 8 + _model.fbeAllocationSize(value: value)");
+
6459 WriteLineIndent("let fbeStructOffset = try buffer.allocate(size: fbeStructSize) - buffer.offset");
+
6460 WriteLineIndent("if (buffer.offset + fbeStructOffset + fbeStructSize) > buffer.size {");
+
6461 Indent(1);
+
6462 WriteLineIndent("assertionFailure(\"Model is broken!\")");
+
6463 WriteLineIndent("return 0");
+
6464 Indent(-1);
+
6465 WriteLineIndent("}");
+
6466 WriteLine();
+
6467 WriteLineIndent("fbeStructSize = try _model.set(value: value) + 8");
+
6468 WriteLineIndent("try buffer.resize(size: fbeInitialSize + fbeStructSize)");
+
6469 WriteLine();
+
6470 WriteLineIndent("write(offset: _model.fbeOffset - 8, value: UInt32(fbeStructSize))");
+
6471 WriteLineIndent("write(offset: _model.fbeOffset - 4, value: UInt32(fbeStructType))");
+
6472 WriteLine();
+
6473 WriteLineIndent("return fbeStructSize");
+
6474 Indent(-1);
+
6475 WriteLineIndent("}");
+
6476
+
6477 // Generate struct model final deserialize() methods
+
6478 WriteLine();
+
6479 WriteLineIndent("// Deserialize the struct value");
+
6480 WriteLineIndent("public func deserialize() -> " + struct_name + " { var value = " + struct_name + "(); _ = deserialize(value: &value); return value }");
+
6481 WriteLine();
+
6482 WriteLineIndent("public func deserialize(value: inout " + struct_name + ") -> Int {");
+
6483 Indent(1);
+
6484 WriteLineIndent("if (buffer.offset + _model.fbeOffset) > buffer.size {");
+
6485 Indent(1);
+
6486 WriteLineIndent("assertionFailure(\"Model is broken!\")");
+
6487 WriteLineIndent("return 0");
+
6488 Indent(-1);
+
6489 WriteLineIndent("}");
+
6490 WriteLine();
+
6491 WriteLineIndent("let fbeStructSize = Int32(readUInt32(offset: _model.fbeOffset - 8))");
+
6492 WriteLineIndent("let fbeStructType = Int32(readUInt32(offset: _model.fbeOffset - 4))");
+
6493 WriteLineIndent("if (fbeStructSize <= 0) || (fbeStructType != fbeType) {");
+
6494 Indent(1);
+
6495 WriteLineIndent("assertionFailure(\"Model is broken!\")");
+
6496 WriteLineIndent("return 8");
+
6497 Indent(-1);
+
6498 WriteLineIndent("}");
+
6499 WriteLine();
+
6500 WriteLineIndent("var fbeSize = Size()");
+
6501 WriteLineIndent("value = _model.get(size: &fbeSize, fbeValue: &value)");
+
6502 WriteLineIndent("return 8 + fbeSize.value");
+
6503 Indent(-1);
+
6504 WriteLineIndent("}");
+
6505
+
6506 // Generate struct model final next() method
+
6507 WriteLine();
+
6508 WriteLineIndent("// Move to the next struct value");
+
6509 WriteLineIndent("public func next(prev: Int) {");
+
6510 Indent(1);
+
6511 WriteLineIndent("_model.fbeShift(size: prev)");
+
6512 Indent(-1);
+
6513 WriteLineIndent("}");
+
6514
+
6515 // Generate struct model final end
+
6516 Indent(-1);
+
6517 WriteLineIndent("}");
+
6518
+
6519 // Generate footer
+
6520 GenerateFooter();
+
6521
+
6522 // Store the file
+
6523 WriteEnd();
+
6524 Store(file);
+
6525}
+
6526
+
6527void GeneratorSwift::GenerateProtocolVersion(const std::shared_ptr<Package>& p)
+
6528{
+
6529 std::string domain = ConvertDomain(p);
+
6530 std::string package = ConvertPackage(p);
+
6531
+
6532 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "Fbe";
+
6533
+
6534 // Create package path
+
6535 CppCommon::Directory::CreateTree(path);
+
6536
+
6537 // Generate the file
+
6538 CppCommon::Path file = path / ("ProtocolVersion.swift");
+
6539 WriteBegin();
+
6540
+
6541 // Generate headers
+
6542 GenerateHeader(CppCommon::Path(_input).filename().string());
+
6543
+
6544 // Generate protocol version class
+
6545 WriteLineIndent("// Fast Binary Encoding " + domain + package + " protocol version");
+
6546 WriteLineIndent("public struct ProtocolVersion {");
+
6547 Indent(1);
+
6548 WriteLineIndent("// Protocol major version");
+
6549 WriteLineIndent("public static let Major = " + std::to_string(p->version->major));
+
6550 WriteLineIndent("// Protocol minor version");
+
6551 WriteLineIndent("public static let Minor = " + std::to_string(p->version->minor));
+
6552 Indent(-1);
+
6553 WriteLineIndent("}");
+
6554
+
6555 // Generate footer
+
6556 GenerateFooter();
+
6557
+
6558 // Store the file
+
6559 WriteEnd();
+
6560 Store(file);
+
6561}
+
6562
+
6563void GeneratorSwift::GenerateSender(const std::shared_ptr<Package>& p, bool final)
+
6564{
+
6565 std::string domain = ConvertDomain(p);
+
6566 std::string package = ConvertPackage(p);
+
6567
+
6568 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "Fbe";
+
6569
+
6570 // Create package path
+
6571 CppCommon::Directory::CreateTree(path);
+
6572
+
6573 std::string sender = (final ? "FinalSender" : "Sender");
+
6574 std::string model = (final ? "FinalModel" : "Model");
+
6575
+
6576 // Generate the file
+
6577 CppCommon::Path file = path / (sender + ".swift");
+
6578 WriteBegin();
+
6579
+
6580 // Generate headers
+
6581 GenerateHeader(CppCommon::Path(_input).filename().string());
+
6582 GenerateImports(domain, "Fbe");
+
6583 GenerateImports("", "Foundation");
+
6584 GenerateImports(p);
+
6585
+
6586 // Generate sender begin
+
6587 WriteLine();
+
6588 if (final)
+
6589 WriteLineIndent("// Fast Binary Encoding " + domain + package + " final sender");
+
6590 else
+
6591 WriteLineIndent("// Fast Binary Encoding " + domain + package + " sender");
+
6592 WriteLineIndent("open class " + sender + ": " + domain + "Fbe.SenderProtocol {");
+
6593 Indent(1);
+
6594
+
6595 // Generate imported senders accessors
+
6596 if (p->import)
+
6597 {
+
6598 WriteLineIndent("// Imported senders");
+
6599 for (const auto& import : p->import->imports)
+
6600 WriteLineIndent("let " + ConvertPackageName(*import) + "Sender: " + domain + ConvertPackageName(*import) + "." + sender);
+
6601 WriteLine();
+
6602 }
+
6603
+
6604 // Generate sender models accessors
+
6605 if (p->body)
+
6606 {
+
6607 WriteLineIndent("// Sender models accessors");
+
6608 for (const auto& s : p->body->structs)
+
6609 if (s->message)
+
6610 WriteLineIndent("private let " + *s->name + "Model: " + *s->name + model);
+
6611 WriteLine();
+
6612 }
+
6613
+
6614 WriteLineIndent("public var buffer: Buffer = Buffer()");
+
6615 WriteLineIndent("public var final: Bool = false");
+
6616 WriteLine();
+
6617
+
6618 // Generate sender constructors
+
6619 WriteLineIndent("public init() {");
+
6620 Indent(1);
+
6621 if (p->import)
+
6622 for (const auto& import : p->import->imports)
+
6623 WriteLineIndent(ConvertPackageName(*import) + "Sender = " + domain + ConvertPackageName(*import) + "." + sender + "(buffer: buffer)");
+
6624 if (p->body)
+
6625 {
+
6626 for (const auto& s : p->body->structs)
+
6627 {
+
6628 if (s->message)
+
6629 {
+
6630 std::string struct_name = domain + package + "." + *s->name;
+
6631 WriteLineIndent(*s->name + "Model = " + struct_name + model + "(buffer: buffer)");
+
6632 }
+
6633
+
6634 }
+
6635 }
+
6636 WriteLineIndent("build(with: " + std::string(final ? "true" : "false") + ")");
+
6637 Indent(-1);
+
6638 WriteLineIndent("}");
+
6639 WriteLine();
+
6640 WriteLineIndent("public init(buffer: " + domain + "Fbe.Buffer) {");
+
6641 Indent(1);
+
6642 if (p->import)
+
6643 for (const auto& import : p->import->imports)
+
6644 WriteLineIndent(ConvertPackageName(*import) + "Sender = " + domain + ConvertPackageName(*import) + "." + sender + "(buffer: buffer)");
+
6645 if (p->body)
+
6646 {
+
6647 for (const auto& s : p->body->structs)
+
6648 {
+
6649 if (s->message)
+
6650 {
+
6651 std::string struct_name = domain + package + "." + *s->name;
+
6652 WriteLineIndent(*s->name + "Model = " + struct_name + model + "(buffer: buffer)");
+
6653 }
+
6654
+
6655 }
+
6656
+
6657 }
+
6658 WriteLineIndent("build(with: buffer, final: " + std::string(final ? "true" : "false") + ")");
+
6659 Indent(-1);
+
6660 WriteLineIndent("}");
+
6661 WriteLine();
+
6662
+
6663 bool messages = false;
+
6664 for (const auto& s : p->body->structs)
+
6665 if (s->message)
+
6666 messages = true;
+
6667
+
6668 WriteLineIndent("public func send(obj: Any) throws -> Int {");
+
6669 Indent(1);
+
6670 WriteLineIndent("guard let listener = self as? " + domain + "Fbe.SenderListener else { return 0 }");
+
6671 WriteLineIndent("return try send(obj: obj, listener: listener)");
+
6672 Indent(-1);
+
6673 WriteLineIndent("}");
+
6674 WriteLine();
+
6675
+
6676 // Generate generic sender method
+
6677 WriteLineIndent("public func send(obj: Any, listener: " + domain + "Fbe.SenderListener) throws -> Int {");
+
6678 Indent(1);
+
6679 if (p->body && messages)
+
6680 {
+
6681 WriteLineIndent("let objType = type(of: obj)");
+
6682 for (const auto& s : p->body->structs)
+
6683 {
+
6684 if (s->message)
+
6685 {
+
6686 std::string struct_name = domain + package + "." + *s->name;
+
6687 WriteLineIndent("if objType == " + struct_name + ".self, let value = obj as? " + struct_name + " { return try send(value: value, listener: listener) }");
+
6688 }
+
6689 }
+
6690 }
+
6691 WriteLine();
+
6692 if (p->import)
+
6693 {
+
6694 WriteLineIndent("// Try to send using imported senders");
+
6695 WriteLineIndent("var result: Int = 0");
+
6696 for (const auto& import : p->import->imports)
+
6697 {
+
6698 WriteLineIndent("result = try " + ConvertPackageName(*import) + "Sender.send(obj: obj, listener: listener)");
+
6699 WriteLineIndent("if result > 0 {");
+
6700 Indent(1);
+
6701 WriteLineIndent("return result");
+
6702 WriteLineIndent("}");
+
6703 Indent(-1);
+
6704 }
+
6705 WriteLine();
+
6706 }
+
6707 WriteLineIndent("return 0");
+
6708 Indent(-1);
+
6709 WriteLineIndent("}");
+
6710
+
6711 // Generate sender methods
+
6712 if (p->body)
+
6713 {
+
6714 for (const auto& s : p->body->structs)
+
6715 {
+
6716 if (s->message)
+
6717 {
+
6718 std::string struct_name = domain + package + "." + *s->name;
+
6719 WriteLine();
+
6720 WriteLineIndent("public func send(value: " + struct_name + ") throws -> Int {");
+
6721 Indent(1);
+
6722 WriteLineIndent("guard let listener = self as? " + domain + "Fbe.SenderListener else { return 0 }");
+
6723 WriteLineIndent("return try send(value: value, listener: listener)");
+
6724 Indent(-1);
+
6725 WriteLineIndent("}");
+
6726
+
6727 WriteLine();
+
6728 WriteLineIndent("public func send(value: " + struct_name + ", listener: " + domain + "Fbe.SenderListener) throws -> Int {");
+
6729 Indent(1);
+
6730 WriteLineIndent("// Serialize the value into the FBE stream");
+
6731 WriteLineIndent("let serialized = try " + *s->name + "Model.serialize(value: value)");
+
6732 WriteLineIndent("assert(serialized > 0, \"" + struct_name + " serialization failed!\")");
+
6733 WriteLineIndent("assert(" + *s->name + "Model.verify(), \"" + struct_name + " validation failed!\")");
+
6734 WriteLine();
+
6735 WriteLineIndent("// Log the value");
+
6736 WriteLineIndent("if listener.logging {");
+
6737 Indent(1);
+
6738 WriteLineIndent("let message = value.description");
+
6739 WriteLineIndent("listener.onSendLog(message: message)");
+
6740 Indent(-1);
+
6741 WriteLineIndent("}");
+
6742 WriteLine();
+
6743 WriteLineIndent("// Send the serialized value");
+
6744 WriteLineIndent("return try sendSerialized(listener: listener, serialized: serialized)");
+
6745 Indent(-1);
+
6746 WriteLineIndent("}");
+
6747 }
+
6748 }
+
6749 }
+
6750 // Generate sender end
+
6751 Indent(-1);
+
6752 WriteLineIndent("}");
+
6753
+
6754 // Generate footer
+
6755 GenerateFooter();
+
6756
+
6757 // Store the file
+
6758 WriteEnd();
+
6759 Store(file);
+
6760}
+
6761
+
6762void GeneratorSwift::GenerateReceiver(const std::shared_ptr<Package>& p, bool final)
+
6763{
+
6764 std::string domain = ConvertDomain(p);
+
6765 std::string package = ConvertPackage(p);
+
6766
+
6767 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "Fbe";
+
6768
+
6769 // Create package path
+
6770 CppCommon::Directory::CreateTree(path);
+
6771
+
6772 std::string listener = (final ? "FinalReceiverListener" : "ReceiverListener");
+
6773 std::string receiver = (final ? "FinalReceiver" : "Receiver");
+
6774 std::string model = (final ? "FinalModel" : "Model");
+
6775
+
6776 // Generate the file
+
6777 CppCommon::Path file = path / (receiver + ".swift");
+
6778 WriteBegin();
+
6779
+
6780 // Generate headers
+
6781 GenerateHeader(CppCommon::Path(_input).filename().string());
+
6782 GenerateImports("", "Foundation");
+
6783 GenerateImports(domain, "Fbe");
+
6784 GenerateImports(p);
+
6785
+
6786 // Generate receiver begin
+
6787 WriteLine();
+
6788 if (final)
+
6789 WriteLineIndent("// Fast Binary Encoding " + domain + package + " final receiver");
+
6790 else
+
6791 WriteLineIndent("// Fast Binary Encoding " + domain + package + " receiver");
+
6792 WriteLineIndent("open class " + receiver + ": " + domain + "Fbe.ReceiverProtocol {");
+
6793 Indent(1);
+
6794
+
6795 // Generate imported receivers accessors
+
6796 if (p->import)
+
6797 {
+
6798 WriteLineIndent("// Imported receivers");
+
6799 for (const auto& import : p->import->imports)
+
6800 WriteLineIndent("let " + ConvertPackageName(*import) + "Receiver: " + domain + ConvertPackageName(*import) + "." + receiver + "?");
+
6801 WriteLine();
+
6802 }
+
6803
+
6804 // Generate receiver models accessors
+
6805 if (p->body)
+
6806 {
+
6807 WriteLineIndent("// Receiver values accessors");
+
6808 for (const auto& s : p->body->structs)
+
6809 {
+
6810 if (s->message)
+
6811 {
+
6812 std::string struct_name = domain + package + "." + *s->name;
+
6813 WriteLineIndent("private var " + *s->name + "Value: " + struct_name);
+
6814 }
+
6815 }
+
6816 WriteLine();
+
6817 WriteLineIndent("// Receiver models accessors");
+
6818 for (const auto& s : p->body->structs)
+
6819 {
+
6820 if (s->message)
+
6821 {
+
6822 std::string struct_name = domain + package + "." + *s->name;
+
6823 WriteLineIndent("private var " + *s->name + "Model: " + *s->name + model);
+
6824 }
+
6825 }
+
6826
+
6827 WriteLine();
+
6828 }
+
6829
+
6830
+
6831 WriteLineIndent("public var buffer: Buffer = Buffer()");
+
6832 WriteLineIndent("public var final: Bool = false");
+
6833 WriteLine();
+
6834
+
6835 // Generate receiver constructors
+
6836 WriteLineIndent("public init() {");
+
6837 Indent(1);
+
6838 if (p->import)
+
6839 for (const auto& import : p->import->imports)
+
6840 WriteLineIndent(ConvertPackageName(*import) + "Receiver = " + domain + ConvertPackageName(*import) + "." + receiver + "(buffer: buffer)");
+
6841 if (p->body)
+
6842 {
+
6843 for (const auto& s : p->body->structs)
+
6844 {
+
6845 if (s->message)
+
6846 {
+
6847 std::string struct_name = domain + package + "." + *s->name;
+
6848 WriteLineIndent(*s->name + "Value = " + struct_name + "()");
+
6849 WriteLineIndent(*s->name + "Model = " + struct_name + model + "()");
+
6850 }
+
6851 }
+
6852 }
+
6853 WriteLineIndent("build(final: " + std::string(final ? "true" : "false") + ")");
+
6854 Indent(-1);
+
6855 WriteLineIndent("}");
+
6856 WriteLine();
+
6857
+
6858 WriteLineIndent("public init(buffer: " + domain + "Fbe.Buffer) {");
+
6859 Indent(1);
+
6860 if (p->import)
+
6861 for (const auto& import : p->import->imports)
+
6862 WriteLineIndent(ConvertPackageName(*import) + "Receiver = " + domain + ConvertPackageName(*import) + "." + receiver + "(buffer: buffer)");
+
6863 if (p->body)
+
6864 {
+
6865 for (const auto& s : p->body->structs)
+
6866 {
+
6867 if (s->message)
+
6868 {
+
6869 std::string struct_name = domain + package + "." + *s->name;
+
6870 WriteLineIndent(*s->name + "Value = " + struct_name + "()");
+
6871 WriteLineIndent(*s->name + "Model = " + struct_name + model + "()");
+
6872 }
+
6873 }
+
6874 }
+
6875 WriteLineIndent("build(with: buffer, final: " + std::string(final ? "true" : "false") + ")");
+
6876 Indent(-1);
+
6877 WriteLineIndent("}");
+
6878 WriteLine();
+
6879
+
6880 bool messages = false;
+
6881 for (const auto& s : p->body->structs)
+
6882 if (s->message)
+
6883 messages = true;
+
6884
+
6885 // Generate receiver message handler
+
6886 WriteLineIndent("open func onReceive(type: Int, buffer: Data, offset: Int, size: Int) -> Bool {");
+
6887 Indent(1);
+
6888 WriteLineIndent("guard let listener = self as? " + listener + " else { return false }");
+
6889 WriteLineIndent("return onReceiveListener(listener: listener, type: type, buffer: buffer, offset: offset, size: size)");
+
6890 Indent(-1);
+
6891 WriteLineIndent("}");
+
6892 WriteLine();
+
6893 WriteLineIndent("open func onReceiveListener(listener: " + listener + ", type: Int, buffer: Data, offset: Int, size: Int) -> Bool {");
+
6894 Indent(1);
+
6895 if (p->body && messages)
+
6896 {
+
6897 WriteLineIndent("switch type {");
+
6898 for (const auto& s : p->body->structs)
+
6899 {
+
6900 if (s->message)
+
6901 {
+
6902 WriteLineIndent("case " + domain + package + "." + *s->name + model + ".fbeTypeConst:");
+
6903 Indent(1);
+
6904 WriteLineIndent("// Deserialize the value from the FBE stream");
+
6905 WriteLineIndent(*s->name + "Model.attach(buffer: buffer, offset: offset)");
+
6906 WriteLineIndent("assert(" + *s->name + "Model.verify(), \"" + package + "." + *s->name + " validation failed!\")");
+
6907 WriteLineIndent("let deserialized = " + *s->name + "Model.deserialize(value: &" + *s->name + "Value)");
+
6908 WriteLineIndent("assert(deserialized > 0, \"" + package + "." + *s->name + " deserialization failed!\")");
+
6909 WriteLine();
+
6910 WriteLineIndent("// Log the value");
+
6911 WriteLineIndent("if listener.logging {");
+
6912 Indent(1);
+
6913 WriteLineIndent("let message = " + *s->name + "Value.description");
+
6914 WriteLineIndent("listener.onReceiveLog(message: message)");
+
6915 Indent(-1);
+
6916 WriteLineIndent("}");
+
6917 WriteLine();
+
6918 WriteLineIndent("// Call receive handler with deserialized value");
+
6919 WriteLineIndent("listener.onReceive(value: " + *s->name + "Value)");
+
6920 WriteLineIndent("return true");
+
6921 Indent(-1);
+
6922 }
+
6923 }
+
6924 WriteLineIndent("default: break");
+
6925 WriteLineIndent("}");
+
6926 }
+
6927 if (p->import)
+
6928 {
+
6929 WriteLine();
+
6930 for (const auto& import : p->import->imports)
+
6931 {
+
6932 WriteLineIndent("if let " + ConvertPackageName(*import) + "Receiver = " + ConvertPackageName(*import) + "Receiver, " + ConvertPackageName(*import) + "Receiver.onReceiveListener(listener: listener, type: type, buffer: buffer, offset: offset, size: size) {");
+
6933 Indent(1);
+
6934 WriteLineIndent("return true");
+
6935 Indent(-1);
+
6936 WriteLineIndent("}");
+
6937 }
+
6938 }
+
6939 WriteLine();
+
6940 WriteLineIndent("return false");
+
6941 Indent(-1);
+
6942 WriteLineIndent("}");
+
6943
+
6944 // Generate receiver end
+
6945 Indent(-1);
+
6946 WriteLineIndent("}");
+
6947
+
6948 // Generate footer
+
6949 GenerateFooter();
+
6950
+
6951 // Store the file
+
6952 WriteEnd();
+
6953 Store(file);
+
6954}
+
6955
+
6956void GeneratorSwift::GenerateReceiverListener(const std::shared_ptr<Package>& p, bool final)
+
6957{
+
6958 std::string domain = ConvertDomain(p);
+
6959 std::string package = ConvertPackage(p);
+
6960
+
6961 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "Fbe";
+
6962
+
6963 // Create package path
+
6964 CppCommon::Directory::CreateTree(path);
+
6965
+
6966 std::string listener = (final ? "FinalReceiverListener" : "ReceiverListener");
+
6967
+
6968 // Generate the file
+
6969 CppCommon::Path file = path / (listener + ".swift");
+
6970 WriteBegin();
+
6971
+
6972 // Generate headers
+
6973 GenerateHeader(CppCommon::Path(_input).filename().string());
+
6974 GenerateImports(domain, "Fbe");
+
6975 GenerateImports(p);
+
6976
+
6977 // Generate receiver listener begin
+
6978 WriteLine();
+
6979 if (final)
+
6980 WriteLineIndent("// Fast Binary Encoding " + package + " final receiver listener");
+
6981 else
+
6982 WriteLineIndent("// Fast Binary Encoding " + package + " receiver listener");
+
6983 WriteIndent("public protocol " + listener);
+
6984 if (p->import)
+
6985 {
+
6986 bool first = true;
+
6987 WriteIndent(": ");
+
6988 for (const auto& import : p->import->imports)
+
6989 {
+
6990 WriteIndent((first ? "" : ", ") + domain + ConvertPackageName(*import) + "." + listener);
+
6991 first = false;
+
6992 }
+
6993 }
+
6994 else
+
6995 WriteIndent(": " + domain + "Fbe.ReceiveLogListener");
+
6996 WriteIndent(" {");
+
6997 WriteLine();
+
6998 Indent(1);
+
6999
+
7000 // Generate receiver listener handlers
+
7001 if (p->body)
+
7002 {
+
7003 for (const auto& s : p->body->structs)
+
7004 {
+
7005 if (s->message)
+
7006 {
+
7007 std::string struct_name = domain + package + "." + *s->name;
+
7008 WriteLineIndent("func onReceive(value: " + struct_name + ")");
+
7009 }
+
7010 }
+
7011 }
+
7012
+
7013 // Generate receiver listener end
+
7014 Indent(-1);
+
7015 WriteLineIndent("}");
+
7016 WriteLine();
+
7017
+
7018 WriteLineIndent("public extension " + listener + " {");
+
7019 Indent(1);
+
7020 // Generate default receiver listener handlers
+
7021 if (p->body)
+
7022 {
+
7023 for (const auto& s : p->body->structs)
+
7024 {
+
7025 if (s->message)
+
7026 {
+
7027 std::string struct_name = domain + package + "." + *s->name;
+
7028 WriteLineIndent("func onReceive(value: " + struct_name + ") {}");
+
7029 }
+
7030 }
+
7031 }
+
7032 Indent(-1);
+
7033 WriteLineIndent("}");
+
7034
+
7035 // Generate footer
+
7036 GenerateFooter();
+
7037
+
7038 // Store the file
+
7039 WriteEnd();
+
7040 Store(file);
+
7041}
+
7042
+
7043void GeneratorSwift::GenerateProxy(const std::shared_ptr<Package>& p, bool final)
+
7044{
+
7045 std::string domain = ConvertDomain(p);
+
7046 std::string package = ConvertPackage(p);
+
7047
+
7048 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "Fbe";
+
7049
+
7050 // Create package path
+
7051 CppCommon::Directory::CreateTree(path);
+
7052
+
7053 std::string listener = (final ? "FinalProxyListener" : "ProxyListener");
+
7054 std::string proxy = (final ? "FinalProxy" : "Proxy");
+
7055 std::string model = (final ? "FinalModel" : "Model");
+
7056
+
7057 // Generate the file
+
7058 CppCommon::Path file = path / (proxy + ".swift");
+
7059 WriteBegin();
+
7060
+
7061 // Generate headers
+
7062 GenerateHeader(CppCommon::Path(_input).filename().string());
+
7063 GenerateImports("", "Foundation");
+
7064 GenerateImports(domain, "Fbe");
+
7065 GenerateImports(p);
+
7066
+
7067 // Generate proxy begin
+
7068 WriteLine();
+
7069 if (final)
+
7070 WriteLineIndent("// Fast Binary Encoding " + package + " final proxy");
+
7071 else
+
7072 WriteLineIndent("// Fast Binary Encoding " + package + " proxy");
+
7073 WriteLineIndent("open class " + proxy + ": " + domain + "Fbe.ReceiverProtocol {");
+
7074 Indent(1);
+
7075
+
7076 // Generate imported proxy accessors
+
7077 if (p->import)
+
7078 {
+
7079 WriteLineIndent("// Imported proxy");
+
7080 for (const auto& import : p->import->imports)
+
7081 WriteLineIndent("let " + ConvertPackageName(*import) + "Proxy: " + domain + ConvertPackageName(*import) + "." + proxy + "?");
+
7082 WriteLine();
+
7083 }
+
7084
+
7085 // Generate proxy models accessors
+
7086 if (p->body)
+
7087 {
+
7088 WriteLineIndent("// Proxy models accessors");
+
7089 for (const auto& s : p->body->structs)
+
7090 if (s->message)
+
7091 WriteLineIndent("private let " + *s->name + "Model: " + *s->name + model);
+
7092 WriteLine();
+
7093 }
+
7094
+
7095 WriteLineIndent("public var buffer: Buffer = Buffer()");
+
7096 WriteLineIndent("public var final: Bool = false");
+
7097 WriteLine();
+
7098
+
7099 // Generate proxy constructors
+
7100 WriteLineIndent("public init() {");
+
7101 Indent(1);
+
7102 if (p->import)
+
7103 for (const auto& import : p->import->imports)
+
7104 WriteLineIndent(ConvertPackageName(*import) + "Proxy = " + domain + ConvertPackageName(*import) + "." + proxy + "(buffer: buffer)");
+
7105 if (p->body)
+
7106 {
+
7107 for (const auto& s : p->body->structs)
+
7108 {
+
7109 if (s->message)
+
7110 {
+
7111 std::string struct_name = domain + package + "." + *s->name;
+
7112 WriteLineIndent(*s->name + "Model = " + struct_name + model + "()");
+
7113 }
+
7114 }
+
7115 }
+
7116 WriteLineIndent("build(final: " + std::string(final ? "true" : "false") + ")");
+
7117 Indent(-1);
+
7118 WriteLineIndent("}");
+
7119 WriteLine();
+
7120 WriteLineIndent("public init(buffer: " + domain + "Fbe.Buffer) {");
+
7121 Indent(1);
+
7122 if (p->import)
+
7123 for (const auto& import : p->import->imports)
+
7124 WriteLineIndent(ConvertPackageName(*import) + "Proxy = " + domain + ConvertPackageName(*import) + "." + proxy + "(buffer: buffer)");
+
7125 if (p->body)
+
7126 {
+
7127 for (const auto& s : p->body->structs)
+
7128 {
+
7129 if (s->message)
+
7130 {
+
7131 std::string struct_name = domain + package + "." + *s->name;
+
7132 WriteLineIndent(*s->name + "Model = " + struct_name+ model + "()");
+
7133 }
+
7134 }
+
7135 }
+
7136 WriteLineIndent("build(with: buffer, final: " + std::string(final ? "true" : "false") + ")");
+
7137 Indent(-1);
+
7138 WriteLineIndent("}");
+
7139 WriteLine();
+
7140
+
7141 bool messages = false;
+
7142 for (const auto& s : p->body->structs)
+
7143 if (s->message)
+
7144 messages = true;
+
7145
+
7146 // Generate proxy message handler
+
7147 WriteLineIndent("open func onReceive(type: Int, buffer: Data, offset: Int, size: Int) -> Bool {");
+
7148 Indent(1);
+
7149 WriteLineIndent("guard let listener = self as? " + listener + " else { return false }");
+
7150 WriteLineIndent("return onReceiveListener(listener: listener, type: type, buffer: buffer, offset: offset, size: size)");
+
7151 Indent(-1);
+
7152 WriteLineIndent("}");
+
7153 WriteLine();
+
7154 WriteLineIndent("open func onReceiveListener(listener: " + listener + ", type: Int, buffer: Data, offset: Int, size: Int) -> Bool {");
+
7155 Indent(1);
+
7156 if (p->body && messages)
+
7157 {
+
7158 WriteLineIndent("switch type {");
+
7159 for (const auto& s : p->body->structs)
+
7160 {
+
7161 if (s->message)
+
7162 {
+
7163 WriteLineIndent("case " + domain + package + "." + *s->name + model + ".fbeTypeConst:");
+
7164 Indent(1);
+
7165 WriteLineIndent("// Attach the FBE stream to the proxy model");
+
7166 WriteLineIndent(*s->name + "Model.attach(buffer: buffer, offset: offset)");
+
7167 WriteLineIndent("assert(" + *s->name + "Model.verify(), \"" + package + "." + *s->name + " validation failed!\")");
+
7168 WriteLine();
+
7169 WriteLineIndent("let fbeBegin = " + *s->name + "Model.model.getBegin()");
+
7170 WriteLineIndent("if fbeBegin == 0 {");
+
7171 Indent(1);
+
7172 WriteLineIndent("return false");
+
7173 Indent(-1);
+
7174 WriteLineIndent("}");
+
7175 WriteLineIndent("// Call proxy handler");
+
7176 WriteLineIndent("listener.onProxy(model: " + *s->name + "Model, type: type, buffer: buffer, offset: offset, size: size)");
+
7177 WriteLineIndent(*s->name + "Model.model.getEnd(fbeBegin: fbeBegin)");
+
7178 WriteLineIndent("return true");
+
7179 Indent(-1);
+
7180 }
+
7181 }
+
7182 WriteLineIndent("default: break");
+
7183 WriteLineIndent("}");
+
7184 }
+
7185 if (p->import)
+
7186 {
+
7187 WriteLine();
+
7188 for (const auto& import : p->import->imports)
+
7189 {
+
7190 WriteLineIndent("if let " + ConvertPackageName(*import) + "Proxy = " + ConvertPackageName(*import) + "Proxy, " + ConvertPackageName(*import) + "Proxy.onReceiveListener(listener: listener, type: type, buffer: buffer, offset: offset, size: size) {");
+
7191 Indent(1);
+
7192 WriteLineIndent("return true");
+
7193 Indent(-1);
+
7194 WriteLineIndent("}");
+
7195 }
+
7196 }
+
7197 WriteLine();
+
7198 WriteLineIndent("return false");
+
7199 Indent(-1);
+
7200 WriteLineIndent("}");
+
7201
+
7202 // Generate proxy end
+
7203 Indent(-1);
+
7204 WriteLineIndent("}");
+
7205
+
7206 // Generate footer
+
7207 GenerateFooter();
+
7208
+
7209 // Store the file
+
7210 WriteEnd();
+
7211 Store(file);
+
7212}
+
7213
+
7214void GeneratorSwift::GenerateProxyListener(const std::shared_ptr<Package>& p, bool final)
+
7215{
+
7216 std::string domain = ConvertDomain(p);
+
7217 std::string package = ConvertPackage(p);
+
7218
+
7219 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "Fbe";
+
7220
+
7221 // Create package path
+
7222 CppCommon::Directory::CreateTree(path);
+
7223
+
7224 std::string listener = (final ? "FinalProxyListener" : "ProxyListener");
+
7225 std::string model = (final ? "FinalModel" : "Model");
+
7226
+
7227 // Generate the file
+
7228 CppCommon::Path file = path / (listener + ".swift");
+
7229 WriteBegin();
+
7230
+
7231 // Generate headers
+
7232 GenerateHeader(CppCommon::Path(_input).filename().string());
+
7233 GenerateImports(domain, "Fbe");
+
7234 GenerateImports("", "Foundation");
+
7235 GenerateImports(p);
+
7236
+
7237 // Generate proxy listener begin
+
7238 WriteLine();
+
7239 if (final)
+
7240 WriteLineIndent("// Fast Binary Encoding " + domain + package + " final proxy listener");
+
7241 else
+
7242 WriteLineIndent("// Fast Binary Encoding " + domain + package + " proxy listener");
+
7243 WriteIndent("public protocol " + listener);
+
7244 if (p->import)
+
7245 {
+
7246 bool first = true;
+
7247 WriteIndent(": ");
+
7248 for (const auto& import : p->import->imports)
+
7249 {
+
7250 WriteIndent((first ? "" : ", ") + domain + ConvertPackageName(*import) + "." + listener);
+
7251 first = false;
+
7252 }
+
7253 }
+
7254 WriteIndent(" {");
+
7255 WriteLine();
+
7256 Indent(1);
+
7257
+
7258 // Generate proxy listener handlers
+
7259 if (p->body)
+
7260 {
+
7261 for (const auto& s : p->body->structs)
+
7262 {
+
7263 if (s->message)
+
7264 {
+
7265 std::string struct_model = *s->name + model;
+
7266 WriteLineIndent("func onProxy(model: " + struct_model + ", type: Int, buffer: Data, offset: Int, size: Int)");
+
7267 }
+
7268 }
+
7269 }
+
7270
+
7271 // Generate proxy listener end
+
7272 Indent(-1);
+
7273 WriteLineIndent("}");
+
7274
+
7275 WriteLine();
+
7276 WriteLineIndent("public extension " + listener + " {");
+
7277 Indent(1);
+
7278
+
7279 // Generate proxy listener handlers
+
7280 if (p->body)
+
7281 {
+
7282 for (const auto& s : p->body->structs)
+
7283 {
+
7284 std::string struct_model = *s->name + model;
+
7285 WriteLineIndent("func onProxy(model: " + struct_model + ", type: Int, buffer: Data, offset: Int, size: Int) {}");
+
7286 }
+
7287 }
+
7288
+
7289 Indent(-1);
+
7290 WriteLineIndent("}");
+
7291
+
7292 // Generate footer
+
7293 GenerateFooter();
+
7294
+
7295 // Store the file
+
7296 WriteEnd();
+
7297 Store(file);
+
7298}
+
7299
+
7300void GeneratorSwift::GenerateClient(const std::shared_ptr<Package>& p, bool final)
+
7301{
+
7302 std::string domain = ConvertDomain(p);
+
7303 std::string package = ConvertPackage(p);
+
7304
+
7305 CppCommon::Path path = (CppCommon::Path(_output) / CreatePackagePath(domain, package)) / "Fbe";
+
7306
+
7307 // Create package path
+
7308 CppCommon::Directory::CreateTree(path);
+
7309
+
7310 std::string listener = (final ? "FinalReceiverListener" : "ReceiverListener");
+
7311 std::string client = (final ? "FinalClient" : "Client");
+
7312 std::string model = (final ? "FinalModel" : "Model");
+
7313
+
7314 // Generate the file
+
7315 CppCommon::Path file = path / (client + ".swift");
+
7316 WriteBegin();
+
7317
+
7318 // Generate headers
+
7319 GenerateHeader(CppCommon::Path(_input).filename().string());
+
7320 GenerateImports("", "Foundation");
+
7321 GenerateImports(domain, "Fbe");
+
7322 GenerateImports(p);
+
7323
+
7324 // Generate client begin
+
7325 WriteLine();
+
7326 if (final)
+
7327 WriteLineIndent("// Fast Binary Encoding " + package + " final client");
+
7328 else
+
7329 WriteLineIndent("// Fast Binary Encoding " + package + " client");
+
7330 WriteLineIndent("open class " + client + ": " + domain + "Fbe.ClientProtocol {");
+
7331 Indent(1);
+
7332
+
7333 // Generate imported clients accessors
+
7334 if (p->import)
+
7335 {
+
7336 WriteLineIndent("// Imported clients");
+
7337 for (const auto& import : p->import->imports)
+
7338 WriteLineIndent("let " + ConvertPackageName(*import) + "Client: " + domain + ConvertPackageName(*import) + "." + client);
+
7339 WriteLine();
+
7340 }
+
7341
+
7342 // Generate client sender models accessors
+
7343 if (p->body)
+
7344 {
+
7345 WriteLineIndent("// Client sender models accessors");
+
7346 for (const auto& s : p->body->structs)
+
7347 if (s->message)
+
7348 WriteLineIndent("let " + *s->name + "SenderModel: " + *s->name + model);
+
7349 WriteLine();
+
7350 }
+
7351
+
7352 // Generate client receiver models accessors
+
7353 if (p->body)
+
7354 {
+
7355 WriteLineIndent("// Client receiver values accessors");
+
7356 for (const auto& s : p->body->structs)
+
7357 {
+
7358 if (s->message)
+
7359 {
+
7360 std::string struct_name = domain + package + "." + *s->name;
+
7361 WriteLineIndent("private var " + *s->name + "ReceiverValue: " + struct_name);
+
7362 }
+
7363 }
+
7364 WriteLine();
+
7365 WriteLineIndent("// Client receiver models accessors");
+
7366 for (const auto& s : p->body->structs)
+
7367 if (s->message)
+
7368 WriteLineIndent("private let " + *s->name + "ReceiverModel: " + *s->name + model);
+
7369 WriteLine();
+
7370 }
+
7371
+
7372 WriteLineIndent("public var sendBuffer: Buffer = Buffer()");
+
7373 WriteLineIndent("public var receiveBuffer: Buffer = Buffer()");
+
7374 WriteLineIndent("public var final: Bool = false");
+
7375 WriteLine();
+
7376
+
7377 // Generate client constructors
+
7378 WriteLineIndent("public init() {");
+
7379 Indent(1);
+
7380 if (p->import)
+
7381 for (const auto& import : p->import->imports)
+
7382 WriteLineIndent(ConvertPackageName(*import) + "Client = " + domain + ConvertPackageName(*import) + "." + client + "(sendBuffer: sendBuffer, receiveBuffer: receiveBuffer)");
+
7383 if (p->body)
+
7384 {
+
7385 for (const auto& s : p->body->structs)
+
7386 {
+
7387 if (s->message)
+
7388 {
+
7389 std::string struct_name = domain + package + "." + *s->name;
+
7390 WriteLineIndent(*s->name + "SenderModel = " + *s->name + model + "(buffer: sendBuffer)");
+
7391 WriteLineIndent(*s->name + "ReceiverValue = " + struct_name + "()");
+
7392 WriteLineIndent(*s->name + "ReceiverModel = " + *s->name + model + "()");
+
7393 }
+
7394
+
7395 }
+
7396 }
+
7397 WriteLineIndent("build(with: " + std::string(final ? "true" : "false") + ")");
+
7398 Indent(-1);
+
7399 WriteLineIndent("}");
+
7400 WriteLine();
+
7401 WriteLineIndent("public init(sendBuffer: " + domain + "Fbe.Buffer, receiveBuffer: " + domain + "Fbe.Buffer) {");
+
7402 Indent(1);
+
7403 if (p->import)
+
7404 for (const auto& import : p->import->imports)
+
7405 WriteLineIndent(ConvertPackageName(*import) + "Client = " + domain + ConvertPackageName(*import) + "." + client + "(sendBuffer: sendBuffer, receiveBuffer: receiveBuffer)");
+
7406 if (p->body)
+
7407 {
+
7408 for (const auto& s : p->body->structs)
+
7409 {
+
7410 if (s->message)
+
7411 {
+
7412 std::string struct_name = domain + package + "." + *s->name;
+
7413 WriteLineIndent(*s->name + "SenderModel = " + *s->name + model + "(buffer: sendBuffer)");
+
7414 WriteLineIndent(*s->name + "ReceiverValue = " + struct_name + "()");
+
7415 WriteLineIndent(*s->name + "ReceiverModel = " + *s->name + model + "()");
+
7416 }
+
7417
+
7418 }
+
7419 }
+
7420 WriteLineIndent("build(with: sendBuffer, receiveBuffer: receiveBuffer, final: " + std::string(final ? "true" : "false") + ")");
+
7421 Indent(-1);
+
7422 WriteLineIndent("}");
+
7423 WriteLine();
+
7424
+
7425 WriteLineIndent("public func send(obj: Any) throws -> Int {");
+
7426 Indent(1);
+
7427 WriteLineIndent("guard let listener = self as? " + domain + "Fbe.SenderListener else { return 0 }");
+
7428 WriteLineIndent("return try send(obj: obj, listener: listener)");
+
7429 Indent(-1);
+
7430 WriteLineIndent("}");
+
7431 WriteLine();
+
7432
+
7433 bool messages = false;
+
7434 for (const auto& s : p->body->structs)
+
7435 if (s->message)
+
7436 messages = true;
+
7437
+
7438 // Generate generic client send method
+
7439 WriteLineIndent("public func send(obj: Any, listener: " + domain + "Fbe.SenderListener) throws -> Int {");
+
7440 Indent(1);
+
7441 if (p->body && messages)
+
7442 {
+
7443 WriteLineIndent("let objType = type(of: obj)");
+
7444 for (const auto& s : p->body->structs)
+
7445 {
+
7446 if (s->message)
+
7447 {
+
7448 std::string struct_name = domain + package + "." + *s->name;
+
7449 WriteLineIndent("if objType == " + struct_name + ".self, let value = obj as? " + struct_name + " { return try send(value: value, listener: listener) }");
+
7450 }
+
7451 }
+
7452 }
+
7453 WriteLine();
+
7454 if (p->import)
+
7455 {
+
7456 WriteLineIndent("// Try to send using imported clients");
+
7457 WriteLineIndent("var result: Int = 0");
+
7458 for (const auto& import : p->import->imports)
+
7459 {
+
7460 WriteLineIndent("result = try " + ConvertPackageName(*import) + "Client.send(obj: obj, listener: listener)");
+
7461 WriteLineIndent("if result > 0 { return result }");
+
7462 }
+
7463 WriteLine();
+
7464 }
+
7465 WriteLineIndent("return 0");
+
7466 Indent(-1);
+
7467 WriteLineIndent("}");
+
7468
+
7469 // Generate client send methods
+
7470 if (p->body)
+
7471 {
+
7472 for (const auto& s : p->body->structs)
+
7473 {
+
7474 if (s->message)
+
7475 {
+
7476 std::string struct_name = domain + package + "." + *s->name;
+
7477 WriteLine();
+
7478 WriteLineIndent("public func send(value: " + struct_name + ") throws -> Int {");
+
7479 Indent(1);
+
7480 WriteLineIndent("guard let listener = self as? " + domain + "Fbe.SenderListener else { return 0 }");
+
7481 WriteLineIndent("return try send(value: value, listener: listener)");
+
7482 Indent(-1);
+
7483 WriteLineIndent("}");
+
7484
+
7485 WriteLine();
+
7486 WriteLineIndent("public func send(value: " + struct_name + ", listener: " + domain + "Fbe.SenderListener) throws -> Int {");
+
7487 Indent(1);
+
7488 WriteLineIndent("// Serialize the value into the FBE stream");
+
7489 WriteLineIndent("let serialized = try " + *s->name + "SenderModel.serialize(value: value)");
+
7490 WriteLineIndent("assert(serialized > 0, \"" + struct_name + " serialization failed!\")");
+
7491 WriteLineIndent("assert(" + *s->name + "SenderModel.verify(), \"" + struct_name + " validation failed!\")");
+
7492 WriteLine();
+
7493 WriteLineIndent("// Log the value");
+
7494 WriteLineIndent("if listener.logging {");
+
7495 Indent(1);
+
7496 WriteLineIndent("let message = value.description");
+
7497 WriteLineIndent("listener.onSendLog(message: message)");
+
7498 Indent(-1);
+
7499 WriteLineIndent("}");
+
7500 WriteLine();
+
7501 WriteLineIndent("// Send the serialized value");
+
7502 WriteLineIndent("return try sendSerialized(listener: listener, serialized: serialized)");
+
7503 Indent(-1);
+
7504 WriteLineIndent("}");
+
7505 }
+
7506 }
+
7507 }
+
7508
+
7509 // Generate client receive message handler
+
7510 WriteLineIndent("open func onReceive(type: Int, buffer: Data, offset: Int, size: Int) -> Bool {");
+
7511 Indent(1);
+
7512 WriteLineIndent("guard let listener = self as? " + listener + " else { return false }");
+
7513 WriteLineIndent("return onReceiveListener(listener: listener, type: type, buffer: buffer, offset: offset, size: size)");
+
7514 Indent(-1);
+
7515 WriteLineIndent("}");
+
7516 WriteLine();
+
7517 WriteLineIndent("open func onReceiveListener(listener: " + listener + ", type: Int, buffer: Data, offset: Int, size: Int) -> Bool {");
+
7518 Indent(1);
+
7519 if (p->body)
+
7520 {
+
7521 WriteLineIndent("switch type {");
+
7522 for (const auto& s : p->body->structs)
+
7523 {
+
7524 if (s->message)
+
7525 {
+
7526 WriteLineIndent("case " + domain + package + "." + *s->name + model + ".fbeTypeConst:");
+
7527 Indent(1);
+
7528 WriteLineIndent("// Deserialize the value from the FBE stream");
+
7529 WriteLineIndent(*s->name + "ReceiverModel.attach(buffer: buffer, offset: offset)");
+
7530 WriteLineIndent("assert(" + *s->name + "ReceiverModel.verify(), \"" + package + "." + *s->name + " validation failed!\")");
+
7531 WriteLineIndent("let deserialized = " + *s->name + "ReceiverModel.deserialize(value: &" + *s->name + "ReceiverValue)");
+
7532 WriteLineIndent("assert(deserialized > 0, \"" + package + "." + *s->name + " deserialization failed!\")");
+
7533 WriteLine();
+
7534 WriteLineIndent("// Log the value");
+
7535 WriteLineIndent("if listener.logging {");
+
7536 Indent(1);
+
7537 WriteLineIndent("let message = " + *s->name + "ReceiverValue.description");
+
7538 WriteLineIndent("listener.onReceiveLog(message: message)");
+
7539 Indent(-1);
+
7540 WriteLineIndent("}");
+
7541 WriteLine();
+
7542 WriteLineIndent("// Call receive handler with deserialized value");
+
7543 WriteLineIndent("listener.onReceive(value: " + *s->name + "ReceiverValue)");
+
7544 WriteLineIndent("return true");
+
7545 Indent(-1);
+
7546 }
+
7547 }
+
7548 WriteLineIndent("default: break");
+
7549 WriteLineIndent("}");
+
7550 }
+
7551 if (p->import)
+
7552 {
+
7553 WriteLine();
+
7554 for (const auto& import : p->import->imports)
+
7555 {
+
7556 WriteLineIndent("if " + ConvertPackageName(*import) + "Client.onReceiveListener(listener: listener, type: type, buffer: buffer, offset: offset, size: size) {");
+
7557 Indent(1);
+
7558 WriteLineIndent("return true");
+
7559 Indent(-1);
+
7560 WriteLineIndent("}");
+
7561 }
+
7562 }
+
7563 WriteLine();
+
7564 WriteLineIndent("return false");
+
7565 Indent(-1);
+
7566 WriteLineIndent("}");
+
7567
+
7568 // Generate client end
+
7569 Indent(-1);
+
7570 WriteLineIndent("}");
+
7571
+
7572 // Generate footer
+
7573 GenerateFooter();
+
7574
+
7575 // Store the file
+
7576 WriteEnd();
+
7577 Store(file);
+
7578}
+
7579
+
7580bool GeneratorSwift::IsKnownType(const std::string& type)
+
7581{
+
7582 return ((type == "bool") ||
+
7583 (type == "byte") || (type == "bytes") ||
+
7584 (type == "char") || (type == "wchar") ||
+
7585 (type == "int8") || (type == "uint8") ||
+
7586 (type == "int16") || (type == "uint16") ||
+
7587 (type == "int32") || (type == "uint32") ||
+
7588 (type == "int64") || (type == "uint64") ||
+
7589 (type == "float") || (type == "double") ||
+
7590 (type == "decimal") || (type == "string") ||
+
7591 (type == "timestamp") || (type == "uuid"));
+
7592}
+
7593
+
7594bool GeneratorSwift::IsImportedType(const std::string& type)
+
7595{
+
7596 size_t pos = type.find_last_of('.');
+
7597 return (pos != std::string::npos);
+
7598}
+
7599
+
7600bool GeneratorSwift::IsPackageType(const std::string& type)
+
7601{
+
7602 if (IsKnownType(type) || IsImportedType(type))
+
7603 return true;
+
7604
+
7605 return ((type == "Bool") || (type == "Bool?") ||
+
7606 (type == "UInt8") || (type == "UInt8?") || (type == "Data") || (type == "Data?") ||
+
7607 (type == "Character") || (type == "Character?") ||
+
7608 (type == "Int8") || (type == "Int8?") || (type == "UInt8") || (type == "UInt8?") ||
+
7609 (type == "Int16") || (type == "Int16?") || (type == "UInt16") || (type == "UInt16?") ||
+
7610 (type == "Int32") || (type == "Int32?") || (type == "UInt32") || (type == "UInt32?") ||
+
7611 (type == "Int64") || (type == "Int64?") || (type == "UInt64") || (type == "UInt64?") ||
+
7612 (type == "Float") || (type == "Float?") || (type == "Double") || (type == "Double?") ||
+
7613 (type == "Decimal") || (type == "Decimal?") ||
+
7614 (type == "String") || (type == "String?") || (type == "Date") || (type == "Date?") || (type == "UUID") || (type == "UUID?"));
+
7615}
+
7616
+
7617bool GeneratorSwift::IsPrimitiveType(const std::string& type, bool optional)
+
7618{
+
7619 return ((type == "bool") || (type == "byte") ||
+
7620 (type == "char") || (type == "wchar") ||
+
7621 (type == "int8") || (type == "uint8") ||
+
7622 (type == "int16") || (type == "uint16") ||
+
7623 (type == "int32") || (type == "uint32") ||
+
7624 (type == "int64") || (type == "uint64") ||
+
7625 (type == "float") || (type == "double") ||
+
7626 (type == "string"));
+
7627}
+
7628
+
7629bool GeneratorSwift::IsUnsignedType(const std::string& type)
+
7630{
+
7631 return ((type == "byte") || (type == "uint8") || (type == "uint16") || (type == "uint32") || (type == "uint64"));
+
7632}
+
7633
+
7634CppCommon::Path GeneratorSwift::CreatePackagePath(const std::string& domain, const std::string& package)
+
7635{
+
7636 return CppCommon::Path(package) / "Source" / (domain + package);
+
7637}
+
7638
+
7639std::string GeneratorSwift::ConvertEnumBase(const std::string& type)
+
7640{
+
7641 if (type == "byte")
+
7642 return "UInt8";
+
7643 else if (type == "char")
+
7644 return "UInt8";
+
7645 else if (type == "wchar")
+
7646 return "UInt32";
+
7647 else if (type == "int8")
+
7648 return "Int8";
+
7649 else if (type == "uint8")
+
7650 return "UInt8";
+
7651 else if (type == "int16")
+
7652 return "Int16";
+
7653 else if (type == "uint16")
+
7654 return "UInt16";
+
7655 else if (type == "int32")
+
7656 return "Int32";
+
7657 else if (type == "uint32")
+
7658 return "UInt32";
+
7659 else if (type == "int64")
+
7660 return "Int64";
+
7661 else if (type == "uint64")
+
7662 return "UInt64";
+
7663
+
7664 yyerror("Unsupported enum base type - " + type);
+
7665 return "";
+
7666}
+
7667
+
7668std::string GeneratorSwift::ConvertEnumType(const std::string& type)
+
7669{
+
7670 if (type == "byte")
+
7671 return "UInt8";
+
7672 else if (type == "char")
+
7673 return "UInt8";
+
7674 else if (type == "wchar")
+
7675 return "UInt32";
+
7676 else if (type == "int8")
+
7677 return "Int8";
+
7678 else if (type == "uint8")
+
7679 return "UInt8";
+
7680 else if (type == "int16")
+
7681 return "Int16";
+
7682 else if (type == "uint16")
+
7683 return "UInt16";
+
7684 else if (type == "int32")
+
7685 return "Int32";
+
7686 else if (type == "uint32")
+
7687 return "UInt32";
+
7688 else if (type == "int64")
+
7689 return "Int64";
+
7690 else if (type == "uint64")
+
7691 return "UInt64";
+
7692
+
7693 yyerror("Unsupported enum base type - " + type);
+
7694 return "";
+
7695}
+
7696
+
7697std::string GeneratorSwift::ConvertEnumSize(const std::string& type)
+
7698{
+
7699 if (type == "byte")
+
7700 return "1";
+
7701 else if (type == "char")
+
7702 return "1";
+
7703 else if (type == "wchar")
+
7704 return "4";
+
7705 else if (type == "int8")
+
7706 return "1";
+
7707 else if (type == "uint8")
+
7708 return "1";
+
7709 else if (type == "int16")
+
7710 return "2";
+
7711 else if (type == "uint16")
+
7712 return "2";
+
7713 else if (type == "int32")
+
7714 return "4";
+
7715 else if (type == "uint32")
+
7716 return "4";
+
7717 else if (type == "int64")
+
7718 return "8";
+
7719 else if (type == "uint64")
+
7720 return "8";
+
7721
+
7722 yyerror("Unsupported enum base type - " + type);
+
7723 return "";
+
7724}
+
7725
+
7726std::string GeneratorSwift::ConvertEnumGet(const std::string& type)
+
7727{
+
7728 if (type == "byte")
+
7729 return "asByte";
+
7730 else if (type == "char")
+
7731 return "asByte";
+
7732 else if (type == "wchar")
+
7733 return "asInt";
+
7734 else if (type == "int8")
+
7735 return "asByte";
+
7736 else if (type == "uint8")
+
7737 return "asByte.toUByte()";
+
7738 else if (type == "int16")
+
7739 return "asShort";
+
7740 else if (type == "uint16")
+
7741 return "asShort.toUShort()";
+
7742 else if (type == "int32")
+
7743 return "asInt";
+
7744 else if (type == "uint32")
+
7745 return "asInt.toUInt()";
+
7746 else if (type == "int64")
+
7747 return "asLong";
+
7748 else if (type == "uint64")
+
7749 return "asLong.toULong()";
+
7750
+
7751 yyerror("Unsupported enum base type - " + type);
+
7752 return "";
+
7753}
+
7754
+
7755std::string GeneratorSwift::ConvertEnumRead(const std::string& type)
+
7756{
+
7757 if (type == "byte")
+
7758 return "readByte";
+
7759 else if (type == "char")
+
7760 return "readUInt8";
+
7761 else if (type == "wchar")
+
7762 return "readUInt32";
+
7763 else if (type == "int8")
+
7764 return "readInt8";
+
7765 else if (type == "uint8")
+
7766 return "readUInt8";
+
7767 else if (type == "int16")
+
7768 return "readInt16";
+
7769 else if (type == "uint16")
+
7770 return "readUInt16";
+
7771 else if (type == "int32")
+
7772 return "readInt32";
+
7773 else if (type == "uint32")
+
7774 return "readUInt32";
+
7775 else if (type == "int64")
+
7776 return "readInt64";
+
7777 else if (type == "uint64")
+
7778 return "readUInt64";
+
7779
+
7780 yyerror("Unsupported enum base type - " + type);
+
7781 return "";
+
7782}
+
7783
+
7784std::string GeneratorSwift::ConvertEnumFrom(const std::string& type)
+
7785{
+
7786 if (type == "uint8")
+
7787 return ".toByte()";
+
7788 else if (type == "uint16")
+
7789 return ".toShort()";
+
7790 else if (type == "uint32")
+
7791 return ".toInt()";
+
7792 else if (type == "uint64")
+
7793 return ".toLong()";
+
7794
+
7795 return "";
+
7796}
+
7797
+
7798std::string GeneratorSwift::ConvertEnumTo(const std::string& type)
+
7799{
+
7800 if (type == "byte")
+
7801 return ".uint8Value";
+
7802 else if (type == "char")
+
7803 return ".uint8Value";
+
7804 else if (type == "wchar")
+
7805 return ".uint32Value";
+
7806 else if (type == "int8")
+
7807 return ".int8Value";
+
7808 else if (type == "uint8")
+
7809 return ".uint8Value";
+
7810 else if (type == "int16")
+
7811 return ".int16Value";
+
7812 else if (type == "uint16")
+
7813 return ".uint16Value";
+
7814 else if (type == "int32")
+
7815 return ".int32Value";
+
7816 else if (type == "uint32")
+
7817 return ".uint32Value";
+
7818 else if (type == "int64")
+
7819 return ".int64Value";
+
7820 else if (type == "uint64")
+
7821 return ".uint64Value";
+
7822
+
7823 yyerror("Unsupported enum base type - " + type);
+
7824 return "";
+
7825}
+
7826
+
7827std::string GeneratorSwift::ConvertEnumFlags(const std::string& type)
+
7828{
+
7829 if (type == "byte")
+
7830 return ".intValue";
+
7831 else if (type == "int8")
+
7832 return ".intValue";
+
7833 else if (type == "uint8")
+
7834 return ".uintValue";
+
7835 else if (type == "int16")
+
7836 return ".intValue";
+
7837 else if (type == "uint16")
+
7838 return ".uintValue";
+
7839 else if (type == "int32")
+
7840 return ".intValue";
+
7841 else if (type == "uint32")
+
7842 return ".uintValue";
+
7843 else if (type == "int64")
+
7844 return ".int64Value";
+
7845 else if (type == "uint64")
+
7846 return ".uint64Value";
+
7847
+
7848 yyerror("Unsupported enum base type - " + type);
+
7849 return "";
+
7850}
+
7851
+
7852std::string GeneratorSwift::ConvertEnumConstant(const std::string& base, const std::string& type, const std::string& value, bool flag)
+
7853{
+
7854 std::string result = value;
+
7855
+
7856 if (type.empty())
+
7857 {
+
7858 // Fill flags values
+
7859 std::vector<std::string> flags = CppCommon::StringUtils::Split(value, '|', true);
+
7860
+
7861 // Generate flags combination
+
7862 if (!flags.empty())
+
7863 {
+
7864 result = "";
+
7865 bool first = true;
+
7866 for (const auto& it : flags)
+
7867 {
+
7868 result += std::string(first ? "" : " | ") + "Self." + CppCommon::StringUtils::ToTrim(it) + ".rawValue";
+
7869 first = false;
+
7870 }
+
7871 }
+
7872 }
+
7873
+
7874 result = std::regex_replace(result, std::regex("'"), "\"");
+
7875 return ConvertEnumConstantPrefix(type) + result + ConvertEnumConstantSuffix(type);
+
7876}
+
7877
+
7878std::string GeneratorSwift::ConvertEnumConstantPrefix(const std::string& type)
+
7879{
+
7880 return "";
+
7881}
+
7882
+
7883std::string GeneratorSwift::ConvertEnumConstantSuffix(const std::string& type)
+
7884{
+
7885 if ((type == "char"))
+
7886 return ".utf8.map { UInt8($0) }[0]";
+
7887 if ((type == "uint8") || (type == "uint16") || (type == "uint32"))
+
7888 return "";
+
7889 if (type == "int64")
+
7890 return "";
+
7891 if (type == "uint64")
+
7892 return "";
+
7893
+
7894 return "";
+
7895}
+
7896
+
7897std::string GeneratorSwift::ConvertPrimitiveTypeName(const std::string& type)
+
7898{
+
7899 if (type == "bool")
+
7900 return "Bool";
+
7901 else if (type == "byte")
+
7902 return "UInt8";
+
7903 else if (type == "char")
+
7904 return "Character";
+
7905 else if (type == "wchar")
+
7906 return "Character";
+
7907 else if (type == "int8")
+
7908 return "Int8";
+
7909 else if (type == "uint8")
+
7910 return "UInt8";
+
7911 else if (type == "int16")
+
7912 return "Int16";
+
7913 else if (type == "uint16")
+
7914 return "UInt16";
+
7915 else if (type == "int32")
+
7916 return "Int32";
+
7917 else if (type == "uint32")
+
7918 return "UInt32";
+
7919 else if (type == "int64")
+
7920 return "Int64";
+
7921 else if (type == "uint64")
+
7922 return "UInt64";
+
7923 else if (type == "float")
+
7924 return "Float";
+
7925 else if (type == "double")
+
7926 return "Double";
+
7927
+
7928 return "";
+
7929}
+
7930
+
7931std::string GeneratorSwift::ConvertTypeName(const std::string& domain, const std::string& package, const std::string& type, bool optional)
+
7932{
+
7933 std::string opt = optional ? "?" : "";
+
7934
+
7935 if (type == "bool")
+
7936 return "Bool" + opt;
+
7937 else if (type == "byte")
+
7938 return "UInt8" + opt;
+
7939 else if (type == "bytes")
+
7940 return "Data" + opt;
+
7941 else if (type == "char")
+
7942 return "Character" + opt;
+
7943 else if (type == "wchar")
+
7944 return "Character" + opt;
+
7945 else if (type == "int8")
+
7946 return "Int8" + opt;
+
7947 else if (type == "uint8")
+
7948 return "UInt8" + opt;
+
7949 else if (type == "int16")
+
7950 return "Int16" + opt;
+
7951 else if (type == "uint16")
+
7952 return "UInt16" + opt;
+
7953 else if (type == "int32")
+
7954 return "Int32" + opt;
+
7955 else if (type == "uint32")
+
7956 return "UInt32" + opt;
+
7957 else if (type == "int64")
+
7958 return "Int64" + opt;
+
7959 else if (type == "uint64")
+
7960 return "UInt64" + opt;
+
7961 else if (type == "float")
+
7962 return "Float" + opt;
+
7963 else if (type == "double")
+
7964 return "Double" + opt;
+
7965 else if (type == "decimal")
+
7966 return "Decimal" + opt;
+
7967 else if (type == "string")
+
7968 return "String" + opt;
+
7969 else if (type == "timestamp")
+
7970 return "Date" + opt;
+
7971 else if (type == "uuid")
+
7972 return "UUID" + opt;
+
7973
+
7974 std::string ns = "";
+
7975 std::string t = type;
+
7976
+
7977 size_t pos = type.find_last_of('.');
+
7978 if (pos != std::string::npos)
+
7979 {
+
7980 ns.assign(type, 0, pos + 1);
+
7981 ns[0] = toupper(ns[0]);
+
7982 ns = domain + ns;
+
7983 t.assign(type, pos + 1, type.size() - pos);
+
7984 }
+
7985 else if (!package.empty())
+
7986 ns = domain + package + ".";
+
7987
+
7988 return ns + t + opt;
+
7989}
+
7990
+
7991std::string GeneratorSwift::ConvertTypeName(const std::string& domain, const std::string& package, const StructField& field, bool typeless)
+
7992{
+
7993 if (field.array)
+
7994 return "Array" + (typeless ? "" : ("<" + ConvertTypeName(domain, package, *field.type, field.optional) + ">"));
+
7995 else if (field.vector)
+
7996 return "Array" + (typeless ? "" : ("<" + ConvertTypeName(domain, package, *field.type, field.optional) + ">"));
+
7997 else if (field.list)
+
7998 return "Array" + (typeless ? "" : ("<" + ConvertTypeName(domain, package, *field.type, field.optional) + ">"));
+
7999 else if (field.set)
+
8000 return "Array" + (typeless ? "" : ("<" + ConvertTypeName(domain, package, *field.key, field.optional) + ">"));
+
8001 else if (field.map)
+
8002 return "Dictionary" + (typeless ? "" : ("<" + ConvertTypeName(domain, package, *field.key, false) + ", " + ConvertTypeName(domain, package, *field.type, field.optional) +">"));
+
8003 else if (field.hash)
+
8004 return "Dictionary" + (typeless ? "" : ("<" + ConvertTypeName(domain, package, *field.key, false) + ", " + ConvertTypeName(domain, package, *field.type, field.optional) +">"));
+
8005
+
8006 return ConvertTypeName(domain, package, *field.type, field.optional);
+
8007}
+
8008
+
8009std::string GeneratorSwift::ConvertTypeImport(const std::string& type)
+
8010{
+
8011 std::string ns = "";
+
8012
+
8013 size_t pos = type.find_last_of('.');
+
8014 if (pos != std::string::npos)
+
8015 ns.assign(type, 0, pos);
+
8016 else if (!type.empty())
+
8017 ns = "";
+
8018
+
8019 return ns;
+
8020}
+
8021
+
8022std::string GeneratorSwift::ConvertBaseFieldName(const std::string& domain, const std::string& type, bool final)
+
8023{
+
8024 std::string modelType = final ? "Final" : "Field";
+
8025
+
8026 std::string ns = "";
+
8027 std::string t = type;
+
8028
+
8029 size_t pos = type.find_last_of('.');
+
8030 if (pos != std::string::npos)
+
8031 {
+
8032 ns.assign(type, 0, pos + 1);
+
8033 ns[0] = toupper(ns[0]);
+
8034 ns = domain + ns;
+
8035 t.assign(type, pos + 1, type.size() - pos);
+
8036 }
+
8037
+
8038 return ns + modelType + "Model" + ConvertTypeFieldName(t);
+
8039}
+
8040
+
8041std::string GeneratorSwift::ConvertTypeFieldName(const std::string& type)
+
8042{
+
8043 if (type == "bool")
+
8044 return "Boolean";
+
8045 else if (type == "byte")
+
8046 return "UInt8";
+
8047 else if (type == "bytes")
+
8048 return "Data";
+
8049 else if (type == "char")
+
8050 return "Char";
+
8051 else if (type == "wchar")
+
8052 return "WChar";
+
8053 else if (type == "int8")
+
8054 return "Int8";
+
8055 else if (type == "uint8")
+
8056 return "UInt8";
+
8057 else if (type == "int16")
+
8058 return "Int16";
+
8059 else if (type == "uint16")
+
8060 return "UInt16";
+
8061 else if (type == "int32")
+
8062 return "Int32";
+
8063 else if (type == "uint32")
+
8064 return "UInt32";
+
8065 else if (type == "int64")
+
8066 return "Int64";
+
8067 else if (type == "uint64")
+
8068 return "UInt64";
+
8069 else if (type == "float")
+
8070 return "Float";
+
8071 else if (type == "double")
+
8072 return "Double";
+
8073 else if (type == "decimal")
+
8074 return "Decimal";
+
8075 else if (type == "string")
+
8076 return "String";
+
8077 else if (type == "timestamp")
+
8078 return "Timestamp";
+
8079 else if (type == "uuid")
+
8080 return "UUID";
+
8081
+
8082 std::string result = type;
+
8083 size_t pos = type.find_last_of('.');
+
8084 if (pos != std::string::npos)
+
8085 result.assign(type, pos + 1, type.size() - pos);
+
8086
+
8087 CppCommon::StringUtils::ReplaceAll(result, ".", "");
+
8088 return result;
+
8089}
+
8090
+
8091std::string GeneratorSwift::ConvertTypeFieldType(const std::string& domain, const std::string& type, bool optional)
+
8092{
+
8093 std::string opt = optional ? "?" : "";
+
8094
+
8095 if (type == "bool")
+
8096 return "Bool" + opt;
+
8097 else if (type == "byte")
+
8098 return "UInt8" + opt;
+
8099 else if (type == "bytes")
+
8100 return "Data" + opt;
+
8101 else if (type == "char")
+
8102 return "Character" + opt;
+
8103 else if (type == "wchar")
+
8104 return "Character" + opt;
+
8105 else if (type == "int8")
+
8106 return "Int8" + opt;
+
8107 else if (type == "uint8")
+
8108 return "UInt8" + opt;
+
8109 else if (type == "int16")
+
8110 return "Int16" + opt;
+
8111 else if (type == "uint16")
+
8112 return "UInt16" + opt;
+
8113 else if (type == "int32")
+
8114 return "Int32" + opt;
+
8115 else if (type == "uint32")
+
8116 return "UInt32" + opt;
+
8117 else if (type == "int64")
+
8118 return "Int64" + opt;
+
8119 else if (type == "uint64")
+
8120 return "UInt64" + opt;
+
8121 else if (type == "float")
+
8122 return "Float" + opt;
+
8123 else if (type == "double")
+
8124 return "Double" + opt;
+
8125 else if (type == "decimal")
+
8126 return "Decimal" + opt;
+
8127 else if (type == "string")
+
8128 return "String" + opt;
+
8129 else if (type == "timestamp")
+
8130 return "Date" + opt;
+
8131 else if (type == "uuid")
+
8132 return "UUID" + opt;
+
8133
+
8134 std::string ns = "";
+
8135 std::string t = type;
+
8136
+
8137 size_t pos = type.find_last_of('.');
+
8138 if (pos != std::string::npos)
+
8139 {
+
8140 ns.assign(type, 0, pos + 1);
+
8141 ns[0] = toupper(ns[0]);
+
8142 ns = domain + ns;
+
8143 t.assign(type, pos + 1, type.size() - pos);
+
8144 }
+
8145
+
8146 return ns + t + opt;
+
8147}
+
8148
+
8149std::string GeneratorSwift::ConvertTypeFieldDeclaration(const std::string& domain, const std::string& type, bool optional, bool final)
+
8150{
+
8151 std::string modelType = final ? "Final" : "Field";
+
8152
+
8153 std::string ns = "";
+
8154 std::string opt = optional ? "Optional" : "";
+
8155 std::string t = type;
+
8156
+
8157 size_t pos = type.find_last_of('.');
+
8158 if (pos != std::string::npos)
+
8159 {
+
8160 ns.assign(type, 0, pos + 1);
+
8161 ns[0] = toupper(ns[0]);
+
8162 ns = domain + ns;
+
8163 t.assign(type, pos + 1, type.size() - pos);
+
8164 }
+
8165 else
+
8166 ns = (IsKnownType(type) && !optional) ? (domain + "Fbe.") : "";
+
8167
+
8168 return ns + modelType + "Model" + opt + ConvertTypeFieldName(t);
+
8169}
+
8170
+
8171std::string GeneratorSwift::ConvertTypeFieldDeclaration(const std::string& domain, const StructField& field, bool final)
+
8172{
+
8173 std::string modelType = final ? "Final" : "Field";
+
8174
+
8175 if (field.array)
+
8176 return modelType + "ModelArray" + std::string(field.optional ? "Optional" : "") + ConvertTypeFieldName(*field.type);
+
8177 else if (field.vector || field.list || field.set)
+
8178 return modelType + "ModelVector" + std::string(field.optional ? "Optional" : "") + ConvertTypeFieldName(*field.type);
+
8179 else if (field.map || field.hash)
+
8180 return modelType + "ModelMap" + ConvertTypeFieldName(*field.key) + std::string(field.optional ? "Optional" : "") + ConvertTypeFieldName(*field.type);
+
8181 else if (field.optional)
+
8182 return modelType + "ModelOptional" + ConvertTypeFieldName(*field.type);
+
8183
+
8184 return ConvertTypeFieldDeclaration(domain, *field.type, field.optional, final);
+
8185}
+
8186
+
8187std::string GeneratorSwift::ConvertTypeFieldInitialization(const std::string& domain, const StructField& field, const std::string& offset, bool final)
+
8188{
+
8189 std::string modelType = final ? "Final" : "Field";
+
8190
+
8191 if (field.array)
+
8192 return modelType + "ModelArray" + std::string(field.optional ? "Optional" : "") + ConvertTypeFieldName(*field.type) + "(buffer: buffer, offset: " + offset + ", size: " + std::to_string(field.N) + ")";
+
8193 else if (field.vector || field.list || field.set)
+
8194 return modelType + "ModelVector" + std::string(field.optional ? "Optional" : "") + ConvertTypeFieldName(*field.type) + "(buffer: buffer, offset: " + offset + ")";
+
8195 else if (field.map || field.hash)
+
8196 return modelType + "ModelMap" + ConvertTypeFieldName(*field.key) + std::string(field.optional ? "Optional" : "") + ConvertTypeFieldName(*field.type) + "(buffer: buffer, offset: " + offset + ")";
+
8197 else if (field.optional)
+
8198 return modelType + "ModelOptional" + ConvertTypeFieldName(*field.type) + "(buffer: buffer, offset: " + offset + ")";
+
8199
+
8200 std::string ns = "";
+
8201 std::string t = *field.type;
+
8202 std::string type = *field.type;
+
8203
+
8204 size_t pos = type.find_last_of('.');
+
8205 if (pos != std::string::npos)
+
8206 {
+
8207 ns.assign(type, 0, pos + 1);
+
8208 ns[0] = toupper(ns[0]);
+
8209 ns = domain + ns;
+
8210 t.assign(type, pos + 1, type.size() - pos);
+
8211 }
+
8212 else
+
8213 ns = "";
+
8214
+
8215 return ns + modelType + "Model" + ConvertTypeFieldName(t) + "(buffer: buffer, offset: " + offset + ")";
+
8216}
+
8217
+
8218std::string GeneratorSwift::ConvertConstant(const std::string& domain, const std::string& package, const std::string& type, const std::string& value, bool optional)
+
8219{
+
8220 if (value == "true")
+
8221 return "true";
+
8222 else if (value == "false")
+
8223 return "false";
+
8224 else if (value == "null")
+
8225 return "nil";
+
8226 else if (value == "min")
+
8227 {
+
8228 if (type == "byte")
+
8229 return ConvertConstantPrefix(type) + "0" + ConvertConstantSuffix(type);
+
8230 else if (type == "int8")
+
8231 return "Int8.min";
+
8232 else if (type == "uint8")
+
8233 return "UInt8.min";
+
8234 else if (type == "int16")
+
8235 return "Int16.min";
+
8236 else if (type == "uint16")
+
8237 return "UInt16.min";
+
8238 else if (type == "int32")
+
8239 return "Int32.min";
+
8240 else if (type == "uint32")
+
8241 return "UInt32.min";
+
8242 else if (type == "int64")
+
8243 return "Int64.min";
+
8244 else if (type == "uint64")
+
8245 return "UInt64.min";
+
8246
+
8247 yyerror("Unsupported type " + type + " for 'min' constant");
+
8248 return "";
+
8249 }
+
8250 else if (value == "max")
+
8251 {
+
8252 if (type == "byte")
+
8253 return ConvertConstantPrefix(type) + "0xFF" + ConvertConstantSuffix(type);
+
8254 else if (type == "int8")
+
8255 return "Int8.max";
+
8256 else if (type == "uint8")
+
8257 return "UInt8.max";
+
8258 else if (type == "int16")
+
8259 return "Int16.max";
+
8260 else if (type == "uint16")
+
8261 return "UInt16.max";
+
8262 else if (type == "int32")
+
8263 return "Int32.max";
+
8264 else if (type == "uint32")
+
8265 return "UInt32.max";
+
8266 else if (type == "int64")
+
8267 return "Int64.max";
+
8268 else if (type == "uint64")
+
8269 return "UInt64.max";
+
8270
+
8271 yyerror("Unsupported type " + type + " for 'max' constant");
+
8272 return "";
+
8273 }
+
8274 else if (value == "epoch")
+
8275 return "Date(timeIntervalSince1970: 0)";
+
8276 else if (value == "utc")
+
8277 return "Date()";
+
8278 else if (value == "uuid0")
+
8279 return domain + "Fbe.UUIDGenerator.nil()";
+
8280 else if (value == "uuid1")
+
8281 return domain + "Fbe.UUIDGenerator.sequential()";
+
8282 else if (value == "uuid4")
+
8283 return domain + "Fbe.UUIDGenerator.random()";
+
8284
+
8285 std::string result = value;
+
8286 result[0] = toupper(result[0]);
+
8287
+
8288 if (!IsKnownType(type))
+
8289 {
+
8290 // Fill flags values
+
8291 std::vector<std::string> flags = CppCommon::StringUtils::Split(value, '|', true);
+
8292
+
8293 // Generate flags combination
+
8294 if (flags.size() > 1)
+
8295 {
+
8296 result = "";
+
8297 bool first = true;
+
8298 for (const auto& it : flags)
+
8299 {
+
8300 std::string flag = CppCommon::StringUtils::ToTrim(it);
+
8301 result += (first ? "" : ", ") + flag + ".value!";
+
8302 first = false;
+
8303 }
+
8304 result = type + ".fromSet(set: [" + result + "])";
+
8305 }
+
8306 else
+
8307 {
+
8308 size_t pos = result.find_last_of('.');
+
8309 if (pos != std::string::npos)
+
8310 {
+
8311 if (CppCommon::StringUtils::CountAll(result, ".") > 1)
+
8312 result = domain + result;
+
8313 else
+
8314 result = (package.empty() ? "" : (domain + package + ".")) + result;
+
8315 }
+
8316 }
+
8317 }
+
8318
+
8319 result = std::regex_replace(result, std::regex("'"), "\"");
+
8320 return ConvertConstantPrefix(type) + result + ConvertConstantSuffix(type);
+
8321}
+
8322
+
8323std::string GeneratorSwift::ConvertConstantPrefix(const std::string& type)
+
8324{
+
8325 if (type == "decimal")
+
8326 return "Decimal(string: \"";
+
8327 if (type == "uuid")
+
8328 return "UUID(uuidString: ";
+
8329 if (type == "wchar")
+
8330 return "Character(UnicodeScalar(";
+
8331
+
8332 return "";
+
8333}
+
8334
+
8335std::string GeneratorSwift::ConvertConstantSuffix(const std::string& type)
+
8336{
+
8337 if (type == "byte")
+
8338 return "";
+
8339 if ((type == "uint8") || (type == "uint16") || (type == "uint32"))
+
8340 return "";
+
8341 if (type == "int64")
+
8342 return "";
+
8343 if (type == "uint64")
+
8344 return "";
+
8345 if (type == "float")
+
8346 return "";
+
8347
+
8348 if (type == "wchar")
+
8349 return ")!)";
+
8350 if (type == "uuid")
+
8351 return ")!";
+
8352 if (type == "decimal")
+
8353 return "\")!";
+
8354
+
8355 return "";
+
8356}
+
8357
+
8358std::string GeneratorSwift::ConvertDefault(const std::string& domain, const std::string& package, const std::string& type)
+
8359{
+
8360 if (type == "bool")
+
8361 return "false";
+
8362 else if (type == "byte")
+
8363 return "0";
+
8364 else if (type == "bytes")
+
8365 return "Data()";
+
8366 else if (type == "char")
+
8367 return "\"\\0\"";
+
8368 else if (type == "wchar")
+
8369 return "Character(UnicodeScalar(0)!)";
+
8370 else if (type == "int8")
+
8371 return "0";
+
8372 else if (type == "uint8")
+
8373 return "0";
+
8374 else if (type == "int16")
+
8375 return "0";
+
8376 else if (type == "uint16")
+
8377 return "0";
+
8378 else if (type == "int32")
+
8379 return "0";
+
8380 else if (type == "uint32")
+
8381 return "0";
+
8382 else if (type == "int64")
+
8383 return "0";
+
8384 else if (type == "uint64")
+
8385 return "0";
+
8386 else if (type == "float")
+
8387 return "0.0";
+
8388 else if (type == "double")
+
8389 return "0.0";
+
8390 else if (type == "decimal")
+
8391 return "Decimal.zero";
+
8392 else if (type == "string")
+
8393 return "\"\"";
+
8394 else if (type == "timestamp")
+
8395 return "Date(timeIntervalSince1970: 0)";
+
8396 else if (type == "uuid")
+
8397 return domain + "Fbe.UUIDGenerator.nil()";
+
8398
+
8399 std::string ns = "";
+
8400 std::string t = type;
+
8401
+
8402 size_t pos = type.find_last_of('.');
+
8403 if (pos != std::string::npos)
+
8404 {
+
8405 ns.assign(type, 0, pos + 1);
+
8406 ns[0] = toupper(ns[0]);
+
8407 ns = domain + ns;
+
8408 t.assign(type, pos + 1, type.size() - pos);
+
8409 }
+
8410 else if (!package.empty())
+
8411 ns = domain + package + ".";
+
8412
+
8413 return ns + t + "()";
+
8414}
+
8415
+
8416std::string GeneratorSwift::ConvertDefault(const std::string& domain, const std::string& package, const StructField& field)
+
8417{
+
8418 if (field.value)
+
8419 return ConvertConstant(domain, package, *field.type, *field.value, field.optional);
+
8420
+
8421 if (field.array)
+
8422 return "Array()";
+
8423 else if (field.vector || field.list || field.set || field.map || field.hash)
+
8424 return ConvertTypeName(domain, package, field, true) + "()";
+
8425 else if (field.optional)
+
8426 return "nil";
+
8427 else if (!IsPackageType(*field.type))
+
8428 return ConvertTypeName(domain, package, field, true) + "()";
+
8429
+
8430 return ConvertDefault(domain, package, *field.type);
+
8431}
+
8432
+
8433std::string GeneratorSwift::ConvertOutputStreamType(const std::string& type, const std::string& name, bool optional)
+
8434{
+
8435 std::string opt = optional ? "!" : "";
+
8436
+
8437 if (type == "bool")
+
8438 return ".append(" + name + opt + " ? \"true\" : \"false\")";
+
8439 else if (type == "bytes")
+
8440 return ".append(\"bytes[\"); sb.append(\"\\(" + name + opt + ".count)\"); sb.append(\"]\")";
+
8441 else if ((type == "char") || (type == "wchar"))
+
8442 return ".append(\"'\"); sb.append(" + name + opt + "); sb.append(\"'\")";
+
8443 else if (type == "string")
+
8444 return ".append(\"\\\"\"); sb.append(" + name + opt + "); sb.append(\"\\\"\")";
+
8445 else if (type == "uuid")
+
8446 return ".append(\"\\\"\"); sb.append(" + name + opt + ".uuidString); sb.append(\"\\\"\")";
+
8447 else if (type == "timestamp")
+
8448 return ".append(\"\\(floor(" + name + opt + ".timeIntervalSince1970 * 1000) * 1_000_000)\")";
+
8449 else
+
8450 return ".append(" + name + opt + ".description)";
+
8451}
+
8452
+
8453std::string GeneratorSwift::ConvertOutputStreamValue(const std::string& type, const std::string& name, bool optional, bool separate, bool nullable)
+
8454{
+
8455 std::string comma = separate ? ".append(first ? \"\" : \",\"); sb" : "";
+
8456
+
8457 if (optional)
+
8458 return " if let " + name + " = " + name + " { sb" + comma + ConvertOutputStreamType(type, name, false) + " } else { sb" + comma + ".append(\"null\") }";
+
8459 else
+
8460 return "sb" + comma + ConvertOutputStreamType(type, name, false);
+
8461}
+
8462
+
8463std::string GeneratorSwift::ConvertDomain(const std::shared_ptr<Package>& package)
+
8464{
+
8465 std::string domain = (package->domain && !package->domain->empty()) ? (*package->domain + ".") : "";
+
8466 CppCommon::StringUtils::ReplaceAll(domain, "com.", "");
+
8467 domain[0] = toupper(domain[0]);
+
8468 size_t pos = domain.find_last_of('.');
+
8469 while(pos != std::string::npos)
+
8470 {
+
8471 domain[pos + 1] = toupper(domain[pos + 1]);
+
8472 domain.erase(pos, 1);
+
8473 pos = domain.find_last_of('.');
+
8474 }
+
8475 return domain;
+
8476}
+
8477
+
8478std::string GeneratorSwift::ConvertPackage(const std::shared_ptr<Package>& package)
+
8479{
+
8480 std::string packageName = *package->name;
+
8481 packageName[0] = toupper(packageName[0]);
+
8482 return packageName;
+
8483}
+
8484
+
8485std::string GeneratorSwift::ConvertPackageName(const std::string& package)
+
8486{
+
8487 std::string packageName = package;
+
8488 packageName[0] = toupper(packageName[0]);
+
8489 return packageName;
+
8490}
+
8491
+
8492} // namespace FBE
+
void WriteBegin()
Definition generator.inl:24
+
void Store(const CppCommon::Path &filename)
Definition generator.cpp:17
+
static std::string EndLine()
Definition generator.inl:68
+
std::string _output
Definition generator.h:26
+
void WriteLineIndent(const std::string &str)
Definition generator.inl:58
+
void Write(const std::string &str)
Definition generator.inl:29
+ +
void Generate(const std::shared_ptr< Package > &package) override
+
bool Proto() const noexcept
+
bool Final() const noexcept
+
int yyerror(const char *msg)
Definition fbe.l:163
+
Fast binary encoding Kotlin generator definition.
+
Definition fbe.h:33
+
const char version[]
Definition version.h:15
+
+ + +
+ + diff --git a/documents/html/generator__swift_8h.html b/documents/html/generator__swift_8h.html new file mode 100644 index 000000000..d067c8824 --- /dev/null +++ b/documents/html/generator__swift_8h.html @@ -0,0 +1,114 @@ + + + + + + + +FastBinaryEncoding: include/generator_swift.h File Reference + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+ +
generator_swift.h File Reference
+
+
+ +

Fast binary encoding Kotlin generator definition. +More...

+
#include "generator.h"
+
+

Go to the source code of this file.

+ + + +

+Classes

class  FBE::GeneratorSwift
+ + +

+Namespaces

namespace  FBE
+

Detailed Description

+

Fast binary encoding Kotlin generator definition.

+
Author
Andrey Zbranevich \ Based on original Fast binary encoding generator design by \ Ivan Shynkarenka
+
Date
01.08.2019
+ + +

Definition in file generator_swift.h.

+
+ + +
+ + diff --git a/documents/html/generator__swift_8h_source.html b/documents/html/generator__swift_8h_source.html new file mode 100644 index 000000000..1ad9f45a9 --- /dev/null +++ b/documents/html/generator__swift_8h_source.html @@ -0,0 +1,237 @@ + + + + + + + +FastBinaryEncoding: include/generator_swift.h Source File + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + + +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ + +
+
+
+
generator_swift.h
+
+
+Go to the documentation of this file.
1
+
10
+
11#ifndef GENERATOR_SWIFT_H
+
12#define GENERATOR_SWIFT_H
+
13
+
14#include "generator.h"
+
15
+
16namespace FBE {
+
17
+
+ +
19{
+
20public:
+ +
22
+
23 // Final protocol code generation
+
24 bool Final() const noexcept { return _final; }
+
25 GeneratorSwift& Final(bool final) noexcept { _final = final; return *this; }
+
26
+
27 // JSON protocol code generation
+
28 bool JSON() const noexcept { return _json; }
+
29 GeneratorSwift& JSON(bool json) noexcept { _json = json; return *this; }
+
30
+
31 // Sender/Receiver protocol code generation
+
32 bool Proto() const noexcept { return _proto; }
+
33 GeneratorSwift& Proto(bool proto) noexcept { _proto = proto; return *this; }
+
34
+
35 void Generate(const std::shared_ptr<Package>& package) override;
+
36
+
37private:
+
38 bool _final{false};
+
39 bool _json{false};
+
40 bool _proto{false};
+
41
+
42 void GenerateHeader(const std::string& source);
+
43 void GenerateFooter();
+
44 void GenerateImports(const std::string& domain, const std::string& package);
+
45 void GenerateImports(const std::shared_ptr<Package>& p);
+
46
+
47 void GenerateFBEPackage(const std::string& domain, const std::string& package);
+
48 void GenerateFBEUUIDGenerator(const std::string& domain, const std::string& package);
+
49 void GenerateFBEBuffer(const std::string& domain, const std::string& package);
+
50 void GenerateFBEModel(const std::string& domain, const std::string& package);
+
51 void GenerateFBESize(const std::string& domain, const std::string& package);
+
52 void GenerateFBEFieldModel(const std::string& domain, const std::string& package);
+
53 void GenerateFBEFieldModel(const std::string& domain, const std::string& package, const std::string& name, const std::string& type, const std::string& base, const std::string& size, const std::string& defaults);
+
54 void GenerateFBEFieldModelDecimal(const std::string& domain, const std::string& package);
+
55 void GenerateFBEFieldModelTimestamp(const std::string& domain, const std::string& package);
+
56 void GenerateFBEFieldModelBytes(const std::string& domain, const std::string& package);
+
57 void GenerateFBEFieldModelString(const std::string& domain, const std::string& package);
+
58 void GenerateFBEFieldModelOptional(const std::string& domain, const std::shared_ptr<Package>& p, const std::string& name, const std::string& type, const std::string& model);
+
59 void GenerateFBEFieldModelArray(const std::string& domain, const std::shared_ptr<Package>& p, const std::string& name, const std::string& type, const std::string& base, bool optional, const std::string& model);
+
60 void GenerateFBEFieldModelVector(const std::string& domain, const std::shared_ptr<Package>& p, const std::string& name, const std::string& type, const std::string& model);
+
61 void GenerateFBEFieldModelMap(const std::string& domain, const std::shared_ptr<Package>& p, const std::string& key_name, const std::string& key_type, const std::string& key_model, const std::string& value_name, const std::string& value_type, const std::string& value_model);
+
62 void GenerateFBEFieldModelEnumFlags(const std::string& domain, const std::string& package, const std::string& name, const std::string& type);
+
63 void GenerateFBEFinalModel(const std::string& domain, const std::string& package);
+
64 void GenerateFBEFinalModel(const std::string& domain, const std::string& package, const std::string& name, const std::string& type, const std::string& base, const std::string& size, const std::string& defaults);
+
65 void GenerateFBEFinalModelDecimal(const std::string& domain, const std::string& package);
+
66 void GenerateFBEFinalModelTimestamp(const std::string& domain, const std::string& package);
+
67 void GenerateFBEFinalModelBytes(const std::string& domain, const std::string& package);
+
68 void GenerateFBEFinalModelString(const std::string& domain, const std::string& package);
+
69 void GenerateFBEFinalModelOptional(const std::string& domain, const std::shared_ptr<Package>& p, const std::string& name, const std::string& type, const std::string& model);
+
70 void GenerateFBEFinalModelArray(const std::string& domain, const std::shared_ptr<Package>& p, const std::string& name, const std::string& type, const std::string& base, bool optional, const std::string& model);
+
71 void GenerateFBEFinalModelVector(const std::string& domain, const std::shared_ptr<Package>& p, const std::string& name, const std::string& type, const std::string& model);
+
72 void GenerateFBEFinalModelMap(const std::string& domain, const std::shared_ptr<Package>& p, const std::string& key_name, const std::string& key_type, const std::string& key_model, const std::string& value_name, const std::string& value_type, const std::string& value_model);
+
73 void GenerateFBEFinalModelEnumFlags(const std::string& domain, const std::string& package, const std::string& name, const std::string& type);
+
74 void GenerateFBESender(const std::string& domain, const std::string& package);
+
75 void GenerateFBEReceiver(const std::string& domain, const std::string& package);
+
76 void GenerateFBEReceiverListener(const std::string& domain, const std::string& package);
+
77 void GenerateFBEClient(const std::string& domain, const std::string& package);
+
78
+
79 void GenerateContainers(const std::shared_ptr<Package>& p, bool final);
+
80 void GeneratePackage(const std::shared_ptr<Package>& p);
+
81 void GenerateEnum(const std::shared_ptr<Package>& p, const std::shared_ptr<EnumType>& e, const CppCommon::Path& path);
+
82 void GenerateEnumClass(const std::shared_ptr<Package>& p, const std::shared_ptr<EnumType>& e, const CppCommon::Path& path);
+
83 void GenerateFlags(const std::shared_ptr<Package>& p, const std::shared_ptr<FlagsType>& e, const CppCommon::Path& path);
+
84 void GenerateFlagsClass(const std::shared_ptr<Package>& p, const std::shared_ptr<FlagsType>& e, const CppCommon::Path& path);
+
85 void GenerateStruct(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s, const CppCommon::Path& path);
+
86 void GenerateStructFieldModel(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s);
+
87 void GenerateStructModel(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s);
+
88 void GenerateStructFinalModel(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s);
+
89 void GenerateStructModelFinal(const std::shared_ptr<Package>& p, const std::shared_ptr<StructType>& s);
+
90 void GenerateProtocolVersion(const std::shared_ptr<Package>& p);
+
91 void GenerateSender(const std::shared_ptr<Package>& p, bool final);
+
92 void GenerateReceiver(const std::shared_ptr<Package>& p, bool final);
+
93 void GenerateReceiverListener(const std::shared_ptr<Package>& p, bool final);
+
94 void GenerateProxy(const std::shared_ptr<Package>& p, bool final);
+
95 void GenerateProxyListener(const std::shared_ptr<Package>& p, bool final);
+
96 void GenerateClient(const std::shared_ptr<Package>& p, bool final);
+
97
+
98 bool IsKnownType(const std::string& type);
+
99 bool IsImportedType(const std::string& type);
+
100 bool IsPackageType(const std::string& type);
+
101 bool IsPrimitiveType(const std::string& type, bool optional);
+
102 bool IsUnsignedType(const std::string& type);
+
103
+
104 CppCommon::Path CreatePackagePath(const std::string& domain, const std::string& package);
+
105
+
106 std::string ConvertEnumBase(const std::string& type);
+
107 std::string ConvertEnumType(const std::string& type);
+
108 std::string ConvertEnumSize(const std::string& type);
+
109 std::string ConvertEnumGet(const std::string& type);
+
110 std::string ConvertEnumRead(const std::string& type);
+
111 std::string ConvertEnumFrom(const std::string& type);
+
112 std::string ConvertEnumTo(const std::string& type);
+
113 std::string ConvertEnumFlags(const std::string& type);
+
114 std::string ConvertEnumConstant(const std::string& base, const std::string& type, const std::string& value, bool flag);
+
115 std::string ConvertEnumConstantPrefix(const std::string& type);
+
116 std::string ConvertEnumConstantSuffix(const std::string& type);
+
117 std::string ConvertPrimitiveTypeName(const std::string& type);
+
118 std::string ConvertTypeName(const std::string& domain, const std::string& package, const std::string& type, bool optional);
+
119 std::string ConvertTypeName(const std::string& domain, const std::string& package, const StructField& field, bool typeless);
+
120 std::string ConvertTypeImport(const std::string& type);
+
121 std::string ConvertBaseFieldName(const std::string& domain, const std::string& type, bool final);
+
122 std::string ConvertTypeFieldName(const std::string& type);
+
123 std::string ConvertTypeFieldType(const std::string& domain, const std::string& type, bool optional);
+
124 std::string ConvertTypeFieldDeclaration(const std::string& domain, const std::string& type, bool optional, bool final);
+
125 std::string ConvertTypeFieldDeclaration(const std::string& domain, const StructField& field, bool final);
+
126 std::string ConvertTypeFieldInitialization(const std::string& domain, const StructField& field, const std::string& offset, bool final);
+
127 std::string ConvertConstant(const std::string& domain, const std::string& package, const std::string& type, const std::string& value, bool optional);
+
128 std::string ConvertConstantPrefix(const std::string& type);
+
129 std::string ConvertConstantSuffix(const std::string& type);
+
130 std::string ConvertDefault(const std::string& domain, const std::string& package, const std::string& type);
+
131 std::string ConvertDefault(const std::string& domain, const std::string& package, const StructField& field);
+
132
+
133 std::string ConvertOutputStreamType(const std::string& type, const std::string& name, bool optional);
+
134 std::string ConvertOutputStreamValue(const std::string& type, const std::string& name, bool optional, bool separate, bool nullable);
+
135 std::string ConvertDomain(const std::shared_ptr<Package>& package);
+
136 std::string ConvertPackage(const std::shared_ptr<Package>& package);
+
137 std::string ConvertPackageName(const std::string& package);
+
138};
+
+
139
+
140} // namespace FBE
+
141
+
142#endif // GENERATOR_SWIFT_H
+
Generator(const std::string &input, const std::string &output, int indent, char space)
Definition generator.inl:11
+ +
void Generate(const std::shared_ptr< Package > &package) override
+
bool Proto() const noexcept
+
GeneratorSwift & Proto(bool proto) noexcept
+
GeneratorSwift & Final(bool final) noexcept
+
GeneratorSwift & JSON(bool json) noexcept
+
bool Final() const noexcept
+
Generator(const std::string &input, const std::string &output, int indent, char space)
Definition generator.inl:11
+
bool JSON() const noexcept
+
Fast binary encoding generator definition.
+
Definition fbe.h:33
+
+ + +
+ + diff --git a/documents/html/globals.html b/documents/html/globals.html new file mode 100644 index 000000000..4ef729052 --- /dev/null +++ b/documents/html/globals.html @@ -0,0 +1,95 @@ + + + + + + + +FastBinaryEncoding: File Members + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + +
+
+ +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
Here is a list of all file members with links to the files they belong to:
+
+ + +
+ + diff --git a/documents/html/globals_func.html b/documents/html/globals_func.html new file mode 100644 index 000000000..ba012fa9b --- /dev/null +++ b/documents/html/globals_func.html @@ -0,0 +1,92 @@ + + + + + + + +FastBinaryEncoding: File Members + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + +
+
+ +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
Here is a list of all functions with links to the files they belong to:
+
+ + +
+ + diff --git a/documents/html/globals_vars.html b/documents/html/globals_vars.html new file mode 100644 index 000000000..769188d9f --- /dev/null +++ b/documents/html/globals_vars.html @@ -0,0 +1,87 @@ + + + + + + + +FastBinaryEncoding: File Members + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + +
+
+ +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
Here is a list of all variables with links to the files they belong to:
+
+ + +
+ + diff --git a/documents/html/hierarchy.html b/documents/html/hierarchy.html new file mode 100644 index 000000000..700ff1277 --- /dev/null +++ b/documents/html/hierarchy.html @@ -0,0 +1,120 @@ + + + + + + + +FastBinaryEncoding: Class Hierarchy + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + +
+
+ +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
Class Hierarchy
+
+ + + +
+ + diff --git a/documents/html/index.html b/documents/html/index.html new file mode 100644 index 000000000..8e42ceac2 --- /dev/null +++ b/documents/html/index.html @@ -0,0 +1,86 @@ + + + + + + + +FastBinaryEncoding: Main Page + + + + + + + + + + + +
+
+ + + + + + +
+
FastBinaryEncoding 1.15.0.0 +
+
Fast Binary Encoding
+
+
+ + + + + + + + +
+
+ +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
FastBinaryEncoding Documentation
+
+
+ +
+ + +
+ + diff --git a/documents/html/jquery.js b/documents/html/jquery.js new file mode 100644 index 000000000..875ada738 --- /dev/null +++ b/documents/html/jquery.js @@ -0,0 +1,204 @@ +/*! jQuery v3.6.0 | (c) OpenJS Foundation and other contributors | jquery.org/license */ +!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],r=Object.getPrototypeOf,s=t.slice,g=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType&&"function"!=typeof e.item},x=function(e){return null!=e&&e===e.window},E=C.document,c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e} +var f="3.6.0",S=function(e,t){return new S.fn.init(e,t)};function p(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp( +"^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\([^\\r\\n\\f])","g"),ne=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"�":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(p.childNodes),p.childNodes),t[p.childNodes.length].nodeType +}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!N[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&(U.test(t)||z.test(t))){(f=ee.test(t)&&ye(e.parentNode)||e)===e&&d.scope||((s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=S)),o=(l=h(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+xe(l[o]);c=l.join(",")}try{return H.apply(n,f.querySelectorAll(c +)),n}catch(e){N(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return g(t.replace($,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[S]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){ +return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e&&e.namespaceURI,n=e&&(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:p;return r!=C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),p!=C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement("div")),"undefined"!=typeof e.querySelectorAll&&!e.querySelectorAll( +":scope fieldset div").length}),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=S,!C.getElementsByName||!C.getElementsByName(S).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id") +)&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+S+"-]").length||v.push("~="),(t=C.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||v.push( +"\\["+M+"*name"+M+"*="+M+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+S+"+*").length||v.push(".#.+[+~]"),e.querySelectorAll("\\\f"),v.push("[\\r\\n\\f]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",F)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test( +a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},j=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==p&&y(p,e)?-1:t==C||t.ownerDocument==p&&y(p,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==C?-1:t==C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]==p?-1:s[r]==p?1:0}),C},se.matches=function(e,t){return se(e,null, +null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&E&&!N[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){N(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne +).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&m(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):"string"!=typeof n?S.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(S.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||D,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),N.test(r[1])&&S.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this)}).prototype=S.fn,D=S(E);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){while((e=e[t])&&1!==e.nodeType);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for( +var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i;ce=E.createDocumentFragment().appendChild(E.createElement("div")),(fe=E.createElement("input")).setAttribute("type","radio"),fe.setAttribute("checked","checked"),fe.setAttribute("name","t"),ce.appendChild(fe),y.checkClone=ce.cloneNode(!0).cloneNode(!0).lastChild.checked,ce.innerHTML="",y.noCloneChecked=!!ce.cloneNode(!0).lastChild.defaultValue,ce.innerHTML="",y.option=!!ce.lastChild;var ge={thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};function ve(e,t){var n; +return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?S.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;n",""]);var me=/<|&#?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function je(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&S(e).children("tbody")[0]||e}function De(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function qe(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Le(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(Y.hasData(e)&&(s=Y.get(e).events))for(i in Y.remove(t,"handle events"),s)for(n=0, +r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var _t,zt=[],Ut=/(=)\?(?=&|$)|\?\?/;S.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=zt.pop()||S.expando+"_"+wt.guid++;return this[e]=!0,e}}),S.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Ut.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Ut.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Ut,"$1"+r):!1!==e.jsonp&&(e.url+=(Tt.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||S.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r] +,C[r]=function(){o=arguments},n.always(function(){void 0===i?S(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,zt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((_t=E.implementation.createHTMLDocument("").body).innerHTML="
",2===_t.childNodes.length),S.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=N.exec(e))?[t.createElement(i[1])]:(i=xe([e],t,o),o&&o.length&&S(o).remove(),S.merge([],i.childNodes)));var r,i,o},S.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each( +function(){n.apply(this,o||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=S.css(e,"position"),c=S(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=S.css(e,"top"),u=S.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,S.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===S.css(r, +"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===S.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=S(e).offset()).top+=S.css(e,"borderTopWidth",!0),i.left+=S.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-S.css(r,"marginTop",!0),left:t.left-i.left-S.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===S.css(e,"position"))e=e.offsetParent;return e||re})}}),S.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;S.fn[t]=function(e){return $(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),S.each(["top","left"],function(e,n){S.cssHooks[n]=Fe(y.pixelPosition,function(e,t){if(t)return t=We(e,n),Pe.test(t)?S(e).position()[n]+"px":t})} +),S.each({Height:"height",Width:"width"},function(a,s){S.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){S.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return $(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?S.css(e,t,i):S.style(e,t,n,i)},s,n?e:void 0,n)}})}),S.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),S.each( +"blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){S.fn[n]=function(e,t){return 0",options:{classes:{},disabled:!1,create:null},_createWidget:function(t,e){e=y(e||this.defaultElement||this)[0],this.element=y(e),this.uuid=i++,this.eventNamespace="."+this.widgetName+this.uuid,this.bindings=y(),this.hoverable=y(),this.focusable=y(),this.classesElementLookup={},e!==this&&(y.data(e,this.widgetFullName,this),this._on(!0,this.element,{remove:function(t +){t.target===e&&this.destroy()}}),this.document=y(e.style?e.ownerDocument:e.document||e),this.window=y(this.document[0].defaultView||this.document[0].parentWindow)),this.options=y.widget.extend({},this.options,this._getCreateOptions(),t),this._create(),this.options.disabled&&this._setOptionDisabled(this.options.disabled),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:function(){return{}},_getCreateEventData:y.noop,_create:y.noop,_init:y.noop,destroy:function(){var i=this;this._destroy(),y.each(this.classesElementLookup,function(t,e){i._removeClass(e,t)}),this.element.off(this.eventNamespace).removeData(this.widgetFullName),this.widget().off(this.eventNamespace).removeAttr("aria-disabled"),this.bindings.off(this.eventNamespace)},_destroy:y.noop,widget:function(){return this.element},option:function(t,e){var i,s,n,o=t;if(0===arguments.length)return y.widget.extend({},this.options);if("string"==typeof t)if(o={},t=(i=t.split(".")).shift(),i.length){for(s=o[t +]=y.widget.extend({},this.options[t]),n=0;n
"),i=e.children()[0];return y("body").append(e),t=i.offsetWidth,e.css("overflow","scroll"),t===(i=i.offsetWidth)&&(i=e[0].clientWidth),e.remove(),s=t-i}, +getScrollInfo:function(t){var e=t.isWindow||t.isDocument?"":t.element.css("overflow-x"),i=t.isWindow||t.isDocument?"":t.element.css("overflow-y"),e="scroll"===e||"auto"===e&&t.widthx(D(s),D(n))?o.important="horizontal":o.important="vertical",p.using.call(this,t,o)}),h.offset(y.extend(l,{using:t}))})},y.ui.position={fit:{left:function(t,e){var i=e.within, +s=i.isWindow?i.scrollLeft:i.offset.left,n=i.width,o=t.left-e.collisionPosition.marginLeft,h=s-o,a=o+e.collisionWidth-n-s;e.collisionWidth>n?0n?0=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return!0}}),y.ui.plugin={add:function(t,e,i){var s,n=y.ui[t].prototype;for(s in i)n.plugins[s]=n.plugins[s]||[],n.plugins[s].push([e,i[s]])},call:function(t,e,i,s){var n,o=t.plugins[e];if(o&&(s||t.element[0].parentNode&&11!==t.element[0].parentNode.nodeType))for(n=0;n").css({overflow:"hidden",position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")})), +this.element=this.element.parent().data("ui-resizable",this.element.resizable("instance")),this.elementIsWrapper=!0,t={marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom"),marginLeft:this.originalElement.css("marginLeft")},this.element.css(t),this.originalElement.css("margin",0),this.originalResizeStyle=this.originalElement.css("resize"),this.originalElement.css("resize","none"),this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"})),this.originalElement.css(t),this._proportionallyResize()),this._setupHandles(),e.autoHide&&y(this.element).on("mouseenter",function(){e.disabled||(i._removeClass("ui-resizable-autohide"),i._handles.show())}).on("mouseleave",function(){e.disabled||i.resizing||(i._addClass("ui-resizable-autohide"),i._handles.hide())}),this._mouseInit()},_destroy:function(){this._mouseDestroy(),this._addedHandles.remove();function t(t){y(t +).removeData("resizable").removeData("ui-resizable").off(".resizable")}var e;return this.elementIsWrapper&&(t(this.element),e=this.element,this.originalElement.css({position:e.css("position"),width:e.outerWidth(),height:e.outerHeight(),top:e.css("top"),left:e.css("left")}).insertAfter(e),e.remove()),this.originalElement.css("resize",this.originalResizeStyle),t(this.originalElement),this},_setOption:function(t,e){switch(this._super(t,e),t){case"handles":this._removeHandles(),this._setupHandles();break;case"aspectRatio":this._aspectRatio=!!e}},_setupHandles:function(){var t,e,i,s,n,o=this.options,h=this;if(this.handles=o.handles||(y(".ui-resizable-handle",this.element).length?{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"}:"e,s,se"),this._handles=y(),this._addedHandles=y(),this.handles.constructor===String)for("all"===this.handles&&(this.handles="n,e,s,w,se,sw,ne,nw"),i=this.handles.split( +","),this.handles={},e=0;e"),this._addClass(n,"ui-resizable-handle "+s),n.css({zIndex:o.zIndex}),this.handles[t]=".ui-resizable-"+t,this.element.children(this.handles[t]).length||(this.element.append(n),this._addedHandles=this._addedHandles.add(n));this._renderAxis=function(t){var e,i,s;for(e in t=t||this.element,this.handles)this.handles[e].constructor===String?this.handles[e]=this.element.children(this.handles[e]).first().show():(this.handles[e].jquery||this.handles[e].nodeType)&&(this.handles[e]=y(this.handles[e]),this._on(this.handles[e],{mousedown:h._mouseDown})),this.elementIsWrapper&&this.originalElement[0].nodeName.match(/^(textarea|input|select|button)$/i)&&(i=y(this.handles[e],this.element),s=/sw|ne|nw|se|n|s/.test(e)?i.outerHeight():i.outerWidth(),i=["padding",/ne|nw|n/.test(e)?"Top":/se|sw|s/.test(e)?"Bottom":/^e$/.test(e)?"Right":"Left"].join(""),t.css(i,s),this._proportionallyResize()),this._handles=this._handles.add( +this.handles[e])},this._renderAxis(this.element),this._handles=this._handles.add(this.element.find(".ui-resizable-handle")),this._handles.disableSelection(),this._handles.on("mouseover",function(){h.resizing||(this.className&&(n=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i)),h.axis=n&&n[1]?n[1]:"se")}),o.autoHide&&(this._handles.hide(),this._addClass("ui-resizable-autohide"))},_removeHandles:function(){this._addedHandles.remove()},_mouseCapture:function(t){var e,i,s=!1;for(e in this.handles)(i=y(this.handles[e])[0])!==t.target&&!y.contains(i,t.target)||(s=!0);return!this.options.disabled&&s},_mouseStart:function(t){var e,i,s=this.options,n=this.element;return this.resizing=!0,this._renderProxy(),e=this._num(this.helper.css("left")),i=this._num(this.helper.css("top")),s.containment&&(e+=y(s.containment).scrollLeft()||0,i+=y(s.containment).scrollTop()||0),this.offset=this.helper.offset(),this.position={left:e,top:i},this.size=this._helper?{width:this.helper.width(),height:this.helper.height()}:{ +width:n.width(),height:n.height()},this.originalSize=this._helper?{width:n.outerWidth(),height:n.outerHeight()}:{width:n.width(),height:n.height()},this.sizeDiff={width:n.outerWidth()-n.width(),height:n.outerHeight()-n.height()},this.originalPosition={left:e,top:i},this.originalMousePosition={left:t.pageX,top:t.pageY},this.aspectRatio="number"==typeof s.aspectRatio?s.aspectRatio:this.originalSize.width/this.originalSize.height||1,s=y(".ui-resizable-"+this.axis).css("cursor"),y("body").css("cursor","auto"===s?this.axis+"-resize":s),this._addClass("ui-resizable-resizing"),this._propagate("start",t),!0},_mouseDrag:function(t){var e=this.originalMousePosition,i=this.axis,s=t.pageX-e.left||0,e=t.pageY-e.top||0,i=this._change[i];return this._updatePrevProperties(),i&&(e=i.apply(this,[t,s,e]),this._updateVirtualBoundaries(t.shiftKey),(this._aspectRatio||t.shiftKey)&&(e=this._updateRatio(e,t)),e=this._respectSize(e,t),this._updateCache(e),this._propagate("resize",t),e=this._applyChanges(), +!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize(),y.isEmptyObject(e)||(this._updatePrevProperties(),this._trigger("resize",t,this.ui()),this._applyChanges())),!1},_mouseStop:function(t){this.resizing=!1;var e,i,s,n=this.options,o=this;return this._helper&&(s=(e=(i=this._proportionallyResizeElements).length&&/textarea/i.test(i[0].nodeName))&&this._hasScroll(i[0],"left")?0:o.sizeDiff.height,i=e?0:o.sizeDiff.width,e={width:o.helper.width()-i,height:o.helper.height()-s},i=parseFloat(o.element.css("left"))+(o.position.left-o.originalPosition.left)||null,s=parseFloat(o.element.css("top"))+(o.position.top-o.originalPosition.top)||null,n.animate||this.element.css(y.extend(e,{top:s,left:i})),o.helper.height(o.size.height),o.helper.width(o.size.width),this._helper&&!n.animate&&this._proportionallyResize()),y("body").css("cursor","auto"),this._removeClass("ui-resizable-resizing"),this._propagate("stop",t),this._helper&&this.helper.remove(),!1},_updatePrevProperties:function(){ +this.prevPosition={top:this.position.top,left:this.position.left},this.prevSize={width:this.size.width,height:this.size.height}},_applyChanges:function(){var t={};return this.position.top!==this.prevPosition.top&&(t.top=this.position.top+"px"),this.position.left!==this.prevPosition.left&&(t.left=this.position.left+"px"),this.size.width!==this.prevSize.width&&(t.width=this.size.width+"px"),this.size.height!==this.prevSize.height&&(t.height=this.size.height+"px"),this.helper.css(t),t},_updateVirtualBoundaries:function(t){var e,i,s=this.options,n={minWidth:this._isNumber(s.minWidth)?s.minWidth:0,maxWidth:this._isNumber(s.maxWidth)?s.maxWidth:1/0,minHeight:this._isNumber(s.minHeight)?s.minHeight:0,maxHeight:this._isNumber(s.maxHeight)?s.maxHeight:1/0};(this._aspectRatio||t)&&(e=n.minHeight*this.aspectRatio,i=n.minWidth/this.aspectRatio,s=n.maxHeight*this.aspectRatio,t=n.maxWidth/this.aspectRatio,e>n.minWidth&&(n.minWidth=e),i>n.minHeight&&(n.minHeight=i),st.width,h=this._isNumber(t.height)&&e.minHeight&&e.minHeight>t.height,a=this.originalPosition.left+this.originalSize.width,r=this.originalPosition.top+this.originalSize.height +,l=/sw|nw|w/.test(i),i=/nw|ne|n/.test(i);return o&&(t.width=e.minWidth),h&&(t.height=e.minHeight),s&&(t.width=e.maxWidth),n&&(t.height=e.maxHeight),o&&l&&(t.left=a-e.minWidth),s&&l&&(t.left=a-e.maxWidth),h&&i&&(t.top=r-e.minHeight),n&&i&&(t.top=r-e.maxHeight),t.width||t.height||t.left||!t.top?t.width||t.height||t.top||!t.left||(t.left=null):t.top=null,t},_getPaddingPlusBorderDimensions:function(t){for(var e=0,i=[],s=[t.css("borderTopWidth"),t.css("borderRightWidth"),t.css("borderBottomWidth"),t.css("borderLeftWidth")],n=[t.css("paddingTop"),t.css("paddingRight"),t.css("paddingBottom"),t.css("paddingLeft")];e<4;e++)i[e]=parseFloat(s[e])||0,i[e]+=parseFloat(n[e])||0;return{height:i[0]+i[2],width:i[1]+i[3]}},_proportionallyResize:function(){if(this._proportionallyResizeElements.length)for(var t,e=0,i=this.helper||this.element;e").css({overflow:"hidden"}),this._addClass(this.helper,this._helper),this.helper.css({width:this.element.outerWidth(),height:this.element.outerHeight(),position:"absolute",left:this.elementOffset.left+"px",top:this.elementOffset.top+"px",zIndex:++e.zIndex}),this.helper.appendTo("body").disableSelection()):this.helper=this.element},_change:{e:function(t,e){return{width:this.originalSize.width+e}},w:function(t,e){var i=this.originalSize;return{left:this.originalPosition.left+e,width:i.width-e}},n:function(t,e,i){var s=this.originalSize;return{top:this.originalPosition.top+i,height:s.height-i}},s:function(t,e,i){return{height:this.originalSize.height+i}},se:function(t,e,i){return y.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[t,e,i]))},sw:function(t,e, +i){return y.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[t,e,i]))},ne:function(t,e,i){return y.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[t,e,i]))},nw:function(t,e,i){return y.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[t,e,i]))}},_propagate:function(t,e){y.ui.plugin.call(this,t,[e,this.ui()]),"resize"!==t&&this._trigger(t,e,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}),y.ui.plugin.add("resizable","animate",{stop:function(e){var i=y(this).resizable("instance"),t=i.options,s=i._proportionallyResizeElements,n=s.length&&/textarea/i.test(s[0].nodeName),o=n&&i._hasScroll(s[0],"left")?0:i.sizeDiff.height,h=n?0:i.sizeDiff.width,n={width:i.size.width-h,height:i.size.height-o},h=parseFloat(i.element.css("left"))+(i.position.left-i.originalPosition.left +)||null,o=parseFloat(i.element.css("top"))+(i.position.top-i.originalPosition.top)||null;i.element.animate(y.extend(n,o&&h?{top:o,left:h}:{}),{duration:t.animateDuration,easing:t.animateEasing,step:function(){var t={width:parseFloat(i.element.css("width")),height:parseFloat(i.element.css("height")),top:parseFloat(i.element.css("top")),left:parseFloat(i.element.css("left"))};s&&s.length&&y(s[0]).css({width:t.width,height:t.height}),i._updateCache(t),i._propagate("resize",e)}})}}),y.ui.plugin.add("resizable","containment",{start:function(){var i,s,n=y(this).resizable("instance"),t=n.options,e=n.element,o=t.containment,h=o instanceof y?o.get(0):/parent/.test(o)?e.parent().get(0):o;h&&(n.containerElement=y(h),/document/.test(o)||o===document?(n.containerOffset={left:0,top:0},n.containerPosition={left:0,top:0},n.parentData={element:y(document),left:0,top:0,width:y(document).width(),height:y(document).height()||document.body.parentNode.scrollHeight}):(i=y(h),s=[],y(["Top","Right","Left","Bottom"]).each(function(t,e +){s[t]=n._num(i.css("padding"+e))}),n.containerOffset=i.offset(),n.containerPosition=i.position(),n.containerSize={height:i.innerHeight()-s[3],width:i.innerWidth()-s[1]},t=n.containerOffset,e=n.containerSize.height,o=n.containerSize.width,o=n._hasScroll(h,"left")?h.scrollWidth:o,e=n._hasScroll(h)?h.scrollHeight:e,n.parentData={element:h,left:t.left,top:t.top,width:o,height:e}))},resize:function(t){var e=y(this).resizable("instance"),i=e.options,s=e.containerOffset,n=e.position,o=e._aspectRatio||t.shiftKey,h={top:0,left:0},a=e.containerElement,t=!0;a[0]!==document&&/static/.test(a.css("position"))&&(h=s),n.left<(e._helper?s.left:0)&&(e.size.width=e.size.width+(e._helper?e.position.left-s.left:e.position.left-h.left),o&&(e.size.height=e.size.width/e.aspectRatio,t=!1),e.position.left=i.helper?s.left:0),n.top<(e._helper?s.top:0)&&(e.size.height=e.size.height+(e._helper?e.position.top-s.top:e.position.top),o&&(e.size.width=e.size.height*e.aspectRatio,t=!1),e.position.top=e._helper?s.top:0), +i=e.containerElement.get(0)===e.element.parent().get(0),n=/relative|absolute/.test(e.containerElement.css("position")),i&&n?(e.offset.left=e.parentData.left+e.position.left,e.offset.top=e.parentData.top+e.position.top):(e.offset.left=e.element.offset().left,e.offset.top=e.element.offset().top),n=Math.abs(e.sizeDiff.width+(e._helper?e.offset.left-h.left:e.offset.left-s.left)),s=Math.abs(e.sizeDiff.height+(e._helper?e.offset.top-h.top:e.offset.top-s.top)),n+e.size.width>=e.parentData.width&&(e.size.width=e.parentData.width-n,o&&(e.size.height=e.size.width/e.aspectRatio,t=!1)),s+e.size.height>=e.parentData.height&&(e.size.height=e.parentData.height-s,o&&(e.size.width=e.size.height*e.aspectRatio,t=!1)),t||(e.position.left=e.prevPosition.left,e.position.top=e.prevPosition.top,e.size.width=e.prevSize.width,e.size.height=e.prevSize.height)},stop:function(){var t=y(this).resizable("instance"),e=t.options,i=t.containerOffset,s=t.containerPosition,n=t.containerElement,o=y(t.helper),h=o.offset(),a=o.outerWidth( +)-t.sizeDiff.width,o=o.outerHeight()-t.sizeDiff.height;t._helper&&!e.animate&&/relative/.test(n.css("position"))&&y(this).css({left:h.left-s.left-i.left,width:a,height:o}),t._helper&&!e.animate&&/static/.test(n.css("position"))&&y(this).css({left:h.left-s.left-i.left,width:a,height:o})}}),y.ui.plugin.add("resizable","alsoResize",{start:function(){var t=y(this).resizable("instance").options;y(t.alsoResize).each(function(){var t=y(this);t.data("ui-resizable-alsoresize",{width:parseFloat(t.width()),height:parseFloat(t.height()),left:parseFloat(t.css("left")),top:parseFloat(t.css("top"))})})},resize:function(t,i){var e=y(this).resizable("instance"),s=e.options,n=e.originalSize,o=e.originalPosition,h={height:e.size.height-n.height||0,width:e.size.width-n.width||0,top:e.position.top-o.top||0,left:e.position.left-o.left||0};y(s.alsoResize).each(function(){var t=y(this),s=y(this).data("ui-resizable-alsoresize"),n={},e=t.parents(i.originalElement[0]).length?["width","height"]:["width","height","top","left"];y.each(e, +function(t,e){var i=(s[e]||0)+(h[e]||0);i&&0<=i&&(n[e]=i||null)}),t.css(n)})},stop:function(){y(this).removeData("ui-resizable-alsoresize")}}),y.ui.plugin.add("resizable","ghost",{start:function(){var t=y(this).resizable("instance"),e=t.size;t.ghost=t.originalElement.clone(),t.ghost.css({opacity:.25,display:"block",position:"relative",height:e.height,width:e.width,margin:0,left:0,top:0}),t._addClass(t.ghost,"ui-resizable-ghost"),!1!==y.uiBackCompat&&"string"==typeof t.options.ghost&&t.ghost.addClass(this.options.ghost),t.ghost.appendTo(t.helper)},resize:function(){var t=y(this).resizable("instance");t.ghost&&t.ghost.css({position:"relative",height:t.size.height,width:t.size.width})},stop:function(){var t=y(this).resizable("instance");t.ghost&&t.helper&&t.helper.get(0).removeChild(t.ghost.get(0))}}),y.ui.plugin.add("resizable","grid",{resize:function(){var t,e=y(this).resizable("instance"),i=e.options,s=e.size,n=e.originalSize,o=e.originalPosition,h=e.axis,a="number"==typeof i.grid?[i.grid,i.grid]:i.grid,r=a[0 +]||1,l=a[1]||1,u=Math.round((s.width-n.width)/r)*r,p=Math.round((s.height-n.height)/l)*l,d=n.width+u,c=n.height+p,f=i.maxWidth&&i.maxWidthd,s=i.minHeight&&i.minHeight>c;i.grid=a,m&&(d+=r),s&&(c+=l),f&&(d-=r),g&&(c-=l),/^(se|s|e)$/.test(h)?(e.size.width=d,e.size.height=c):/^(ne)$/.test(h)?(e.size.width=d,e.size.height=c,e.position.top=o.top-p):/^(sw)$/.test(h)?(e.size.width=d,e.size.height=c,e.position.left=o.left-u):((c-l<=0||d-r<=0)&&(t=e._getPaddingPlusBorderDimensions(this)),0=f[g]?0:Math.min(f[g],n));!a&&1-1){ +targetElements.on(evt+EVENT_NAMESPACE,function elementToggle(event){$.powerTip.toggle(this,event)})}else{targetElements.on(evt+EVENT_NAMESPACE,function elementOpen(event){$.powerTip.show(this,event)})}});$.each(options.closeEvents,function(idx,evt){if($.inArray(evt,options.openEvents)<0){targetElements.on(evt+EVENT_NAMESPACE,function elementClose(event){$.powerTip.hide(this,!isMouseEvent(event))})}});targetElements.on("keydown"+EVENT_NAMESPACE,function elementKeyDown(event){if(event.keyCode===27){$.powerTip.hide(this,true)}})}return targetElements};$.fn.powerTip.defaults={fadeInTime:200,fadeOutTime:100,followMouse:false,popupId:"powerTip",popupClass:null,intentSensitivity:7,intentPollInterval:100,closeDelay:100,placement:"n",smartPlacement:false,offset:10,mouseOnToPopup:false,manual:false,openEvents:["mouseenter","focus"],closeEvents:["mouseleave","blur"]};$.fn.powerTip.smartPlacementLists={n:["n","ne","nw","s"],e:["e","ne","se","w","nw","sw","n","s","e"],s:["s","se","sw","n"],w:["w","nw","sw","e","ne","se", +"n","s","w"],nw:["nw","w","sw","n","s","se","nw"],ne:["ne","e","se","n","s","sw","ne"],sw:["sw","w","nw","s","n","ne","sw"],se:["se","e","ne","s","n","nw","se"],"nw-alt":["nw-alt","n","ne-alt","sw-alt","s","se-alt","w","e"],"ne-alt":["ne-alt","n","nw-alt","se-alt","s","sw-alt","e","w"],"sw-alt":["sw-alt","s","se-alt","nw-alt","n","ne-alt","w","e"],"se-alt":["se-alt","s","sw-alt","ne-alt","n","nw-alt","e","w"]};$.powerTip={show:function apiShowTip(element,event){if(isMouseEvent(event)){trackMouse(event);session.previousX=event.pageX;session.previousY=event.pageY;$(element).data(DATA_DISPLAYCONTROLLER).show()}else{$(element).first().data(DATA_DISPLAYCONTROLLER).show(true,true)}return element},reposition:function apiResetPosition(element){$(element).first().data(DATA_DISPLAYCONTROLLER).resetPosition();return element},hide:function apiCloseTip(element,immediate){var displayController;immediate=element?immediate:true;if(element){displayController=$(element).first().data(DATA_DISPLAYCONTROLLER)}else if( +session.activeHover){displayController=session.activeHover.data(DATA_DISPLAYCONTROLLER)}if(displayController){displayController.hide(immediate)}return element},toggle:function apiToggle(element,event){if(session.activeHover&&session.activeHover.is(element)){$.powerTip.hide(element,!isMouseEvent(event))}else{$.powerTip.show(element,event)}return element}};$.powerTip.showTip=$.powerTip.show;$.powerTip.closeTip=$.powerTip.hide;function CSSCoordinates(){var me=this;me.top="auto";me.left="auto";me.right="auto";me.bottom="auto";me.set=function(property,value){if($.isNumeric(value)){me[property]=Math.round(value)}}}function DisplayController(element,options,tipController){var hoverTimer=null,myCloseDelay=null;function openTooltip(immediate,forceOpen){cancelTimer();if(!element.data(DATA_HASACTIVEHOVER)){if(!immediate){session.tipOpenImminent=true;hoverTimer=setTimeout(function intentDelay(){hoverTimer=null;checkForIntent()},options.intentPollInterval)}else{if(forceOpen){element.data(DATA_FORCEDOPEN,true)} +closeAnyDelayed();tipController.showTip(element)}}else{cancelClose()}}function closeTooltip(disableDelay){if(myCloseDelay){myCloseDelay=session.closeDelayTimeout=clearTimeout(myCloseDelay);session.delayInProgress=false}cancelTimer();session.tipOpenImminent=false;if(element.data(DATA_HASACTIVEHOVER)){element.data(DATA_FORCEDOPEN,false);if(!disableDelay){session.delayInProgress=true;session.closeDelayTimeout=setTimeout(function closeDelay(){session.closeDelayTimeout=null;tipController.hideTip(element);session.delayInProgress=false;myCloseDelay=null},options.closeDelay);myCloseDelay=session.closeDelayTimeout}else{tipController.hideTip(element)}}}function checkForIntent(){var xDifference=Math.abs(session.previousX-session.currentX),yDifference=Math.abs(session.previousY-session.currentY),totalDifference=xDifference+yDifference;if(totalDifference",{id:options.popupId});if($body.length===0){$body=$("body")}$body.append(tipElement);session.tooltips=session.tooltips?session.tooltips.add(tipElement):tipElement}if(options.followMouse){if(!tipElement.data(DATA_HASMOUSEMOVE)){$document.on("mousemove"+EVENT_NAMESPACE,positionTipOnCursor);$window.on("scroll"+EVENT_NAMESPACE,positionTipOnCursor);tipElement.data(DATA_HASMOUSEMOVE,true)}}function beginShowTip(element){element.data(DATA_HASACTIVEHOVER,true);tipElement.queue(function queueTipInit(next){showTip(element);next()})}function showTip(element){var tipContent;if(!element.data(DATA_HASACTIVEHOVER)){return}if( +session.isTipOpen){if(!session.isClosing){hideTip(session.activeHover)}tipElement.delay(100).queue(function queueTipAgain(next){showTip(element);next()});return}element.trigger("powerTipPreRender");tipContent=getTooltipContent(element);if(tipContent){tipElement.empty().append(tipContent)}else{return}element.trigger("powerTipRender");session.activeHover=element;session.isTipOpen=true;tipElement.data(DATA_MOUSEONTOTIP,options.mouseOnToPopup);tipElement.addClass(options.popupClass);if(!options.followMouse||element.data(DATA_FORCEDOPEN)){positionTipOnElement(element);session.isFixedTipOpen=true}else{positionTipOnCursor()}if(!element.data(DATA_FORCEDOPEN)&&!options.followMouse){$document.on("click"+EVENT_NAMESPACE,function documentClick(event){var target=event.target;if(target!==element[0]){if(options.mouseOnToPopup){if(target!==tipElement[0]&&!$.contains(tipElement[0],target)){$.powerTip.hide()}}else{$.powerTip.hide()}}})}if(options.mouseOnToPopup&&!options.manual){tipElement.on("mouseenter"+EVENT_NAMESPACE, +function tipMouseEnter(){if(session.activeHover){session.activeHover.data(DATA_DISPLAYCONTROLLER).cancel()}});tipElement.on("mouseleave"+EVENT_NAMESPACE,function tipMouseLeave(){if(session.activeHover){session.activeHover.data(DATA_DISPLAYCONTROLLER).hide()}})}tipElement.fadeIn(options.fadeInTime,function fadeInCallback(){if(!session.desyncTimeout){session.desyncTimeout=setInterval(closeDesyncedTip,500)}element.trigger("powerTipOpen")})}function hideTip(element){session.isClosing=true;session.isTipOpen=false;session.desyncTimeout=clearInterval(session.desyncTimeout);element.data(DATA_HASACTIVEHOVER,false);element.data(DATA_FORCEDOPEN,false);$document.off("click"+EVENT_NAMESPACE);tipElement.off(EVENT_NAMESPACE);tipElement.fadeOut(options.fadeOutTime,function fadeOutCallback(){var coords=new CSSCoordinates;session.activeHover=null;session.isClosing=false;session.isFixedTipOpen=false;tipElement.removeClass();coords.set("top",session.currentY+options.offset);coords.set("left",session.currentX+options.offset); +tipElement.css(coords);element.trigger("powerTipClose")})}function positionTipOnCursor(){var tipWidth,tipHeight,coords,collisions,collisionCount;if(!session.isFixedTipOpen&&(session.isTipOpen||session.tipOpenImminent&&tipElement.data(DATA_HASMOUSEMOVE))){tipWidth=tipElement.outerWidth();tipHeight=tipElement.outerHeight();coords=new CSSCoordinates;coords.set("top",session.currentY+options.offset);coords.set("left",session.currentX+options.offset);collisions=getViewportCollisions(coords,tipWidth,tipHeight);if(collisions!==Collision.none){collisionCount=countFlags(collisions);if(collisionCount===1){if(collisions===Collision.right){coords.set("left",session.scrollLeft+session.windowWidth-tipWidth)}else if(collisions===Collision.bottom){coords.set("top",session.scrollTop+session.windowHeight-tipHeight)}}else{coords.set("left",session.currentX-tipWidth-options.offset);coords.set("top",session.currentY-tipHeight-options.offset)}}tipElement.css(coords)}}function positionTipOnElement(element){var priorityList, +finalPlacement;if(options.smartPlacement||options.followMouse&&element.data(DATA_FORCEDOPEN)){priorityList=$.fn.powerTip.smartPlacementLists[options.placement];$.each(priorityList,function(idx,pos){var collisions=getViewportCollisions(placeTooltip(element,pos),tipElement.outerWidth(),tipElement.outerHeight());finalPlacement=pos;return collisions!==Collision.none})}else{placeTooltip(element,options.placement);finalPlacement=options.placement}tipElement.removeClass("w nw sw e ne se n s w se-alt sw-alt ne-alt nw-alt");tipElement.addClass(finalPlacement)}function placeTooltip(element,placement){var iterationCount=0,tipWidth,tipHeight,coords=new CSSCoordinates;coords.set("top",0);coords.set("left",0);tipElement.css(coords);do{tipWidth=tipElement.outerWidth();tipHeight=tipElement.outerHeight();coords=placementCalculator.compute(element,placement,tipWidth,tipHeight,options.offset);tipElement.css(coords)}while(++iterationCount<=5&&(tipWidth!==tipElement.outerWidth()||tipHeight!==tipElement.outerHeight())); +return coords}function closeDesyncedTip(){var isDesynced=false,hasDesyncableCloseEvent=$.grep(["mouseleave","mouseout","blur","focusout"],function(eventType){return $.inArray(eventType,options.closeEvents)!==-1}).length>0;if(session.isTipOpen&&!session.isClosing&&!session.delayInProgress&&hasDesyncableCloseEvent){if(session.activeHover.data(DATA_HASACTIVEHOVER)===false||session.activeHover.is(":disabled")){isDesynced=true}else if(!isMouseOver(session.activeHover)&&!session.activeHover.is(":focus")&&!session.activeHover.data(DATA_FORCEDOPEN)){if(tipElement.data(DATA_MOUSEONTOTIP)){if(!isMouseOver(tipElement)){isDesynced=true}}else{isDesynced=true}}if(isDesynced){hideTip(session.activeHover)}}}this.showTip=beginShowTip;this.hideTip=hideTip;this.resetPosition=positionTipOnElement}function isSvgElement(element){return Boolean(window.SVGElement&&element[0]instanceof SVGElement)}function isMouseEvent(event){return Boolean(event&&$.inArray(event.type,MOUSE_EVENTS)>-1&&typeof event.pageX==="number")} +function initTracking(){if(!session.mouseTrackingActive){session.mouseTrackingActive=true;getViewportDimensions();$(getViewportDimensions);$document.on("mousemove"+EVENT_NAMESPACE,trackMouse);$window.on("resize"+EVENT_NAMESPACE,trackResize);$window.on("scroll"+EVENT_NAMESPACE,trackScroll)}}function getViewportDimensions(){session.scrollLeft=$window.scrollLeft();session.scrollTop=$window.scrollTop();session.windowWidth=$window.width();session.windowHeight=$window.height()}function trackResize(){session.windowWidth=$window.width();session.windowHeight=$window.height()}function trackScroll(){var x=$window.scrollLeft(),y=$window.scrollTop();if(x!==session.scrollLeft){session.currentX+=x-session.scrollLeft;session.scrollLeft=x}if(y!==session.scrollTop){session.currentY+=y-session.scrollTop;session.scrollTop=y}}function trackMouse(event){session.currentX=event.pageX;session.currentY=event.pageY}function isMouseOver(element){var elementPosition=element.offset(),elementBox=element[0].getBoundingClientRect(), +elementWidth=elementBox.right-elementBox.left,elementHeight=elementBox.bottom-elementBox.top;return session.currentX>=elementPosition.left&&session.currentX<=elementPosition.left+elementWidth&&session.currentY>=elementPosition.top&&session.currentY<=elementPosition.top+elementHeight}function getTooltipContent(element){var tipText=element.data(DATA_POWERTIP),tipObject=element.data(DATA_POWERTIPJQ),tipTarget=element.data(DATA_POWERTIPTARGET),targetElement,content;if(tipText){if($.isFunction(tipText)){tipText=tipText.call(element[0])}content=tipText}else if(tipObject){if($.isFunction(tipObject)){tipObject=tipObject.call(element[0])}if(tipObject.length>0){content=tipObject.clone(true,true)}}else if(tipTarget){targetElement=$("#"+tipTarget);if(targetElement.length>0){content=targetElement.html()}}return content}function getViewportCollisions(coords,elementWidth,elementHeight){var viewportTop=session.scrollTop,viewportLeft=session.scrollLeft,viewportBottom=viewportTop+session.windowHeight, +viewportRight=viewportLeft+session.windowWidth,collisions=Collision.none;if(coords.topviewportBottom||Math.abs(coords.bottom-session.windowHeight)>viewportBottom){collisions|=Collision.bottom}if(coords.leftviewportRight){collisions|=Collision.left}if(coords.left+elementWidth>viewportRight||coords.right1)){a.preventDefault();var c=a.originalEvent.changedTouches[0],d=document.createEvent("MouseEvents");d.initMouseEvent(b,!0,!0,window,1,c.screenX,c.screenY,c.clientX,c.clientY,!1,!1,!1,!1,0,null),a.target.dispatchEvent(d)}}if(a.support.touch="ontouchend"in document,a.support.touch){var e,b=a.ui.mouse.prototype,c=b._mouseInit,d=b._mouseDestroy;b._touchStart=function(a){var b=this;!e&&b._mouseCapture(a.originalEvent.changedTouches[0])&&(e=!0,b._touchMoved=!1,f(a,"mouseover"),f(a,"mousemove"),f(a,"mousedown"))},b._touchMove=function(a){e&&(this._touchMoved=!0,f(a,"mousemove"))},b._touchEnd=function(a){e&&(f(a,"mouseup"),f(a,"mouseout"),this._touchMoved||f(a,"click"),e=!1)},b._mouseInit=function(){var b=this;b.element.bind({touchstart:a.proxy(b,"_touchStart"),touchmove:a.proxy(b,"_touchMove"),touchend:a.proxy(b,"_touchEnd")}),c.call(b)},b._mouseDestroy=function(){var b=this;b.element.unbind({touchstart:a.proxy(b,"_touchStart"),touchmove:a.proxy(b, +"_touchMove"),touchend:a.proxy(b,"_touchEnd")}),d.call(b)}}}(jQuery); +/*! SmartMenus jQuery Plugin - v1.1.0 - September 17, 2017 + * http://www.smartmenus.org/ + * Copyright Vasil Dinkov, Vadikom Web Ltd. http://vadikom.com; Licensed MIT */(function(t){"function"==typeof define&&define.amd?define(["jquery"],t):"object"==typeof module&&"object"==typeof module.exports?module.exports=t(require("jquery")):t(jQuery)})(function($){function initMouseDetection(t){var e=".smartmenus_mouse";if(mouseDetectionEnabled||t)mouseDetectionEnabled&&t&&($(document).off(e),mouseDetectionEnabled=!1);else{var i=!0,s=null,o={mousemove:function(t){var e={x:t.pageX,y:t.pageY,timeStamp:(new Date).getTime()};if(s){var o=Math.abs(s.x-e.x),a=Math.abs(s.y-e.y);if((o>0||a>0)&&2>=o&&2>=a&&300>=e.timeStamp-s.timeStamp&&(mouse=!0,i)){var n=$(t.target).closest("a");n.is("a")&&$.each(menuTrees,function(){return $.contains(this.$root[0],n[0])?(this.itemEnter({currentTarget:n[0]}),!1):void 0}),i=!1}}s=e}};o[touchEvents?"touchstart":"pointerover pointermove pointerout MSPointerOver MSPointerMove MSPointerOut"]=function(t){isTouchEvent(t.originalEvent)&&(mouse=!1)},$(document).on(getEventsNS(o,e)), +mouseDetectionEnabled=!0}}function isTouchEvent(t){return!/^(4|mouse)$/.test(t.pointerType)}function getEventsNS(t,e){e||(e="");var i={};for(var s in t)i[s.split(" ").join(e+" ")+e]=t[s];return i}var menuTrees=[],mouse=!1,touchEvents="ontouchstart"in window,mouseDetectionEnabled=!1,requestAnimationFrame=window.requestAnimationFrame||function(t){return setTimeout(t,1e3/60)},cancelAnimationFrame=window.cancelAnimationFrame||function(t){clearTimeout(t)},canAnimate=!!$.fn.animate;return $.SmartMenus=function(t,e){this.$root=$(t),this.opts=e,this.rootId="",this.accessIdPrefix="",this.$subArrow=null,this.activatedItems=[],this.visibleSubMenus=[],this.showTimeout=0,this.hideTimeout=0,this.scrollTimeout=0,this.clickActivated=!1,this.focusActivated=!1,this.zIndexInc=0,this.idInc=0,this.$firstLink=null,this.$firstSub=null,this.disabled=!1,this.$disableOverlay=null,this.$touchScrollingSub=null,this.cssTransforms3d="perspective"in t.style||"webkitPerspective"in t.style,this.wasCollapsible=!1,this.init()},$.extend( +$.SmartMenus,{hideAll:function(){$.each(menuTrees,function(){this.menuHideAll()})},destroy:function(){for(;menuTrees.length;)menuTrees[0].destroy();initMouseDetection(!0)},prototype:{init:function(t){var e=this;if(!t){menuTrees.push(this),this.rootId=((new Date).getTime()+Math.random()+"").replace(/\D/g,""),this.accessIdPrefix="sm-"+this.rootId+"-",this.$root.hasClass("sm-rtl")&&(this.opts.rightToLeftSubMenus=!0);var i=".smartmenus";this.$root.data("smartmenus",this).attr("data-smartmenus-id",this.rootId).dataSM("level",1).on(getEventsNS({"mouseover focusin":$.proxy(this.rootOver,this),"mouseout focusout":$.proxy(this.rootOut,this),keydown:$.proxy(this.rootKeyDown,this)},i)).on(getEventsNS({mouseenter:$.proxy(this.itemEnter,this),mouseleave:$.proxy(this.itemLeave,this),mousedown:$.proxy(this.itemDown,this),focus:$.proxy(this.itemFocus,this),blur:$.proxy(this.itemBlur,this),click:$.proxy(this.itemClick,this)},i),"a"),i+=this.rootId,this.opts.hideOnClick&&$(document).on(getEventsNS({touchstart:$.proxy( +this.docTouchStart,this),touchmove:$.proxy(this.docTouchMove,this),touchend:$.proxy(this.docTouchEnd,this),click:$.proxy(this.docClick,this)},i)),$(window).on(getEventsNS({"resize orientationchange":$.proxy(this.winResize,this)},i)),this.opts.subIndicators&&(this.$subArrow=$("").addClass("sub-arrow"),this.opts.subIndicatorsText&&this.$subArrow.html(this.opts.subIndicatorsText)),initMouseDetection()}if(this.$firstSub=this.$root.find("ul").each(function(){e.menuInit($(this))}).eq(0),this.$firstLink=this.$root.find("a").eq(0),this.opts.markCurrentItem){var s=/(index|default)\.[^#\?\/]*/i,o=/#.*/,a=window.location.href.replace(s,""),n=a.replace(o,"");this.$root.find("a").each(function(){var t=this.href.replace(s,""),i=$(this);(t==a||t==n)&&(i.addClass("current"),e.opts.markCurrentTree&&i.parentsUntil("[data-smartmenus-id]","ul").each(function(){$(this).dataSM("parent-a").addClass("current")}))})}this.wasCollapsible=this.isCollapsible()},destroy:function(t){if(!t){var e=".smartmenus";this.$root.removeData( +"smartmenus").removeAttr("data-smartmenus-id").removeDataSM("level").off(e),e+=this.rootId,$(document).off(e),$(window).off(e),this.opts.subIndicators&&(this.$subArrow=null)}this.menuHideAll();var i=this;this.$root.find("ul").each(function(){var t=$(this);t.dataSM("scroll-arrows")&&t.dataSM("scroll-arrows").remove(),t.dataSM("shown-before")&&((i.opts.subMenusMinWidth||i.opts.subMenusMaxWidth)&&t.css({width:"",minWidth:"",maxWidth:""}).removeClass("sm-nowrap"),t.dataSM("scroll-arrows")&&t.dataSM("scroll-arrows").remove(),t.css({zIndex:"",top:"",left:"",marginLeft:"",marginTop:"",display:""})),0==(t.attr("id")||"").indexOf(i.accessIdPrefix)&&t.removeAttr("id")}).removeDataSM("in-mega").removeDataSM("shown-before").removeDataSM("scroll-arrows").removeDataSM("parent-a").removeDataSM("level").removeDataSM("beforefirstshowfired").removeAttr("role").removeAttr("aria-hidden").removeAttr("aria-labelledby").removeAttr("aria-expanded"),this.$root.find("a.has-submenu").each(function(){var t=$(this);0==t.attr("id" +).indexOf(i.accessIdPrefix)&&t.removeAttr("id")}).removeClass("has-submenu").removeDataSM("sub").removeAttr("aria-haspopup").removeAttr("aria-controls").removeAttr("aria-expanded").closest("li").removeDataSM("sub"),this.opts.subIndicators&&this.$root.find("span.sub-arrow").remove(),this.opts.markCurrentItem&&this.$root.find("a.current").removeClass("current"),t||(this.$root=null,this.$firstLink=null,this.$firstSub=null,this.$disableOverlay&&(this.$disableOverlay.remove(),this.$disableOverlay=null),menuTrees.splice($.inArray(this,menuTrees),1))},disable:function(t){if(!this.disabled){if(this.menuHideAll(),!t&&!this.opts.isPopup&&this.$root.is(":visible")){var e=this.$root.offset();this.$disableOverlay=$('
').css({position:"absolute",top:e.top,left:e.left,width:this.$root.outerWidth(),height:this.$root.outerHeight(),zIndex:this.getStartZIndex(!0),opacity:0}).appendTo(document.body)}this.disabled=!0}},docClick:function(t){return this.$touchScrollingSub?( +this.$touchScrollingSub=null,void 0):((this.visibleSubMenus.length&&!$.contains(this.$root[0],t.target)||$(t.target).closest("a").length)&&this.menuHideAll(),void 0)},docTouchEnd:function(){if(this.lastTouch){if(!(!this.visibleSubMenus.length||void 0!==this.lastTouch.x2&&this.lastTouch.x1!=this.lastTouch.x2||void 0!==this.lastTouch.y2&&this.lastTouch.y1!=this.lastTouch.y2||this.lastTouch.target&&$.contains(this.$root[0],this.lastTouch.target))){this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=0);var t=this;this.hideTimeout=setTimeout(function(){t.menuHideAll()},350)}this.lastTouch=null}},docTouchMove:function(t){if(this.lastTouch){var e=t.originalEvent.touches[0];this.lastTouch.x2=e.pageX,this.lastTouch.y2=e.pageY}},docTouchStart:function(t){var e=t.originalEvent.touches[0];this.lastTouch={x1:e.pageX,y1:e.pageY,target:e.target}},enable:function(){this.disabled&&(this.$disableOverlay&&(this.$disableOverlay.remove(),this.$disableOverlay=null),this.disabled=!1)},getClosestMenu:function(t){for( +var e=$(t).closest("ul");e.dataSM("in-mega");)e=e.parent().closest("ul");return e[0]||null},getHeight:function(t){return this.getOffset(t,!0)},getOffset:function(t,e){var i;"none"==t.css("display")&&(i={position:t[0].style.position,visibility:t[0].style.visibility},t.css({position:"absolute",visibility:"hidden"}).show());var s=t[0].getBoundingClientRect&&t[0].getBoundingClientRect(),o=s&&(e?s.height||s.bottom-s.top:s.width||s.right-s.left);return o||0===o||(o=e?t[0].offsetHeight:t[0].offsetWidth),i&&t.hide().css(i),o},getStartZIndex:function(t){var e=parseInt(this[t?"$root":"$firstSub"].css("z-index"));return!t&&isNaN(e)&&(e=parseInt(this.$root.css("z-index"))),isNaN(e)?1:e},getTouchPoint:function(t){return t.touches&&t.touches[0]||t.changedTouches&&t.changedTouches[0]||t},getViewport:function(t){var e=t?"Height":"Width",i=document.documentElement["client"+e],s=window["inner"+e];return s&&(i=Math.min(i,s)),i},getViewportHeight:function(){return this.getViewport(!0)},getViewportWidth:function(){ +return this.getViewport()},getWidth:function(t){return this.getOffset(t)},handleEvents:function(){return!this.disabled&&this.isCSSOn()},handleItemEvents:function(t){return this.handleEvents()&&!this.isLinkInMegaMenu(t)},isCollapsible:function(){return"static"==this.$firstSub.css("position")},isCSSOn:function(){return"inline"!=this.$firstLink.css("display")},isFixed:function(){var t="fixed"==this.$root.css("position");return t||this.$root.parentsUntil("body").each(function(){return"fixed"==$(this).css("position")?(t=!0,!1):void 0}),t},isLinkInMegaMenu:function(t){return $(this.getClosestMenu(t[0])).hasClass("mega-menu")},isTouchMode:function(){return!mouse||this.opts.noMouseOver||this.isCollapsible()},itemActivate:function(t,e){var i=t.closest("ul"),s=i.dataSM("level");if(s>1&&(!this.activatedItems[s-2]||this.activatedItems[s-2][0]!=i.dataSM("parent-a")[0])){var o=this;$(i.parentsUntil("[data-smartmenus-id]","ul").get().reverse()).add(i).each(function(){o.itemActivate($(this).dataSM("parent-a"))})}if(( +!this.isCollapsible()||e)&&this.menuHideSubMenus(this.activatedItems[s-1]&&this.activatedItems[s-1][0]==t[0]?s:s-1),this.activatedItems[s-1]=t,this.$root.triggerHandler("activate.smapi",t[0])!==!1){var a=t.dataSM("sub");a&&(this.isTouchMode()||!this.opts.showOnClick||this.clickActivated)&&this.menuShow(a)}},itemBlur:function(t){var e=$(t.currentTarget);this.handleItemEvents(e)&&this.$root.triggerHandler("blur.smapi",e[0])},itemClick:function(t){var e=$(t.currentTarget);if(this.handleItemEvents(e)){if(this.$touchScrollingSub&&this.$touchScrollingSub[0]==e.closest("ul")[0])return this.$touchScrollingSub=null,t.stopPropagation(),!1;if(this.$root.triggerHandler("click.smapi",e[0])===!1)return!1;var i=$(t.target).is(".sub-arrow"),s=e.dataSM("sub"),o=s?2==s.dataSM("level"):!1,a=this.isCollapsible(),n=/toggle$/.test(this.opts.collapsibleBehavior),r=/link$/.test(this.opts.collapsibleBehavior),h=/^accordion/.test(this.opts.collapsibleBehavior);if(s&&!s.is(":visible")){if((!r||!a||i)&&(this.opts.showOnClick&&o&&( +this.clickActivated=!0),this.itemActivate(e,h),s.is(":visible")))return this.focusActivated=!0,!1}else if(a&&(n||i))return this.itemActivate(e,h),this.menuHide(s),n&&(this.focusActivated=!1),!1;return this.opts.showOnClick&&o||e.hasClass("disabled")||this.$root.triggerHandler("select.smapi",e[0])===!1?!1:void 0}},itemDown:function(t){var e=$(t.currentTarget);this.handleItemEvents(e)&&e.dataSM("mousedown",!0)},itemEnter:function(t){var e=$(t.currentTarget);if(this.handleItemEvents(e)){if(!this.isTouchMode()){this.showTimeout&&(clearTimeout(this.showTimeout),this.showTimeout=0);var i=this;this.showTimeout=setTimeout(function(){i.itemActivate(e)},this.opts.showOnClick&&1==e.closest("ul").dataSM("level")?1:this.opts.showTimeout)}this.$root.triggerHandler("mouseenter.smapi",e[0])}},itemFocus:function(t){var e=$(t.currentTarget);this.handleItemEvents(e)&&(!this.focusActivated||this.isTouchMode()&&e.dataSM("mousedown")||this.activatedItems.length&&this.activatedItems[this.activatedItems.length-1][0]==e[0 +]||this.itemActivate(e,!0),this.$root.triggerHandler("focus.smapi",e[0]))},itemLeave:function(t){var e=$(t.currentTarget);this.handleItemEvents(e)&&(this.isTouchMode()||(e[0].blur(),this.showTimeout&&(clearTimeout(this.showTimeout),this.showTimeout=0)),e.removeDataSM("mousedown"),this.$root.triggerHandler("mouseleave.smapi",e[0]))},menuHide:function(t){if(this.$root.triggerHandler("beforehide.smapi",t[0])!==!1&&(canAnimate&&t.stop(!0,!0),"none"!=t.css("display"))){var e=function(){t.css("z-index","")};this.isCollapsible()?canAnimate&&this.opts.collapsibleHideFunction?this.opts.collapsibleHideFunction.call(this,t,e):t.hide(this.opts.collapsibleHideDuration,e):canAnimate&&this.opts.hideFunction?this.opts.hideFunction.call(this,t,e):t.hide(this.opts.hideDuration,e),t.dataSM("scroll")&&(this.menuScrollStop(t),t.css({"touch-action":"","-ms-touch-action":"","-webkit-transform":"",transform:""}).off(".smartmenus_scroll").removeDataSM("scroll").dataSM("scroll-arrows").hide()),t.dataSM("parent-a").removeClass( +"highlighted").attr("aria-expanded","false"),t.attr({"aria-expanded":"false","aria-hidden":"true"});var i=t.dataSM("level");this.activatedItems.splice(i-1,1),this.visibleSubMenus.splice($.inArray(t,this.visibleSubMenus),1),this.$root.triggerHandler("hide.smapi",t[0])}},menuHideAll:function(){this.showTimeout&&(clearTimeout(this.showTimeout),this.showTimeout=0);for(var t=this.opts.isPopup?1:0,e=this.visibleSubMenus.length-1;e>=t;e--)this.menuHide(this.visibleSubMenus[e]);this.opts.isPopup&&(canAnimate&&this.$root.stop(!0,!0),this.$root.is(":visible")&&(canAnimate&&this.opts.hideFunction?this.opts.hideFunction.call(this,this.$root):this.$root.hide(this.opts.hideDuration))),this.activatedItems=[],this.visibleSubMenus=[],this.clickActivated=!1,this.focusActivated=!1,this.zIndexInc=0,this.$root.triggerHandler("hideAll.smapi")},menuHideSubMenus:function(t){for(var e=this.activatedItems.length-1;e>=t;e--){var i=this.activatedItems[e].dataSM("sub");i&&this.menuHide(i)}},menuInit:function(t){if(!t.dataSM("in-mega")){ +t.hasClass("mega-menu")&&t.find("ul").dataSM("in-mega",!0);for(var e=2,i=t[0];(i=i.parentNode.parentNode)!=this.$root[0];)e++;var s=t.prevAll("a").eq(-1);s.length||(s=t.prevAll().find("a").eq(-1)),s.addClass("has-submenu").dataSM("sub",t),t.dataSM("parent-a",s).dataSM("level",e).parent().dataSM("sub",t);var o=s.attr("id")||this.accessIdPrefix+ ++this.idInc,a=t.attr("id")||this.accessIdPrefix+ ++this.idInc;s.attr({id:o,"aria-haspopup":"true","aria-controls":a,"aria-expanded":"false"}),t.attr({id:a,role:"group","aria-hidden":"true","aria-labelledby":o,"aria-expanded":"false"}),this.opts.subIndicators&&s[this.opts.subIndicatorsPos](this.$subArrow.clone())}},menuPosition:function(t){var e,i,s=t.dataSM("parent-a"),o=s.closest("li"),a=o.parent(),n=t.dataSM("level"),r=this.getWidth(t),h=this.getHeight(t),u=s.offset(),l=u.left,c=u.top,d=this.getWidth(s),m=this.getHeight(s),p=$(window),f=p.scrollLeft(),v=p.scrollTop(),b=this.getViewportWidth(),S=this.getViewportHeight(),g=a.parent().is("[data-sm-horizontal-sub]" +)||2==n&&!a.hasClass("sm-vertical"),M=this.opts.rightToLeftSubMenus&&!o.is("[data-sm-reverse]")||!this.opts.rightToLeftSubMenus&&o.is("[data-sm-reverse]"),w=2==n?this.opts.mainMenuSubOffsetX:this.opts.subMenusSubOffsetX,T=2==n?this.opts.mainMenuSubOffsetY:this.opts.subMenusSubOffsetY;if(g?(e=M?d-r-w:w,i=this.opts.bottomToTopSubMenus?-h-T:m+T):(e=M?w-r:d-w,i=this.opts.bottomToTopSubMenus?m-T-h:T),this.opts.keepInViewport){var y=l+e,I=c+i;if(M&&f>y?e=g?f-y+e:d-w:!M&&y+r>f+b&&(e=g?f+b-r-y+e:w-r),g||(S>h&&I+h>v+S?i+=v+S-h-I:(h>=S||v>I)&&(i+=v-I)),g&&(I+h>v+S+.49||v>I)||!g&&h>S+.49){var x=this;t.dataSM("scroll-arrows")||t.dataSM("scroll-arrows",$([$('')[0],$('')[0]]).on({mouseenter:function(){t.dataSM("scroll").up=$(this).hasClass("scroll-up"),x.menuScroll(t)},mouseleave:function(e){x.menuScrollStop(t),x.menuScrollOut(t,e)},"mousewheel DOMMouseScroll":function(t){ +t.preventDefault()}}).insertAfter(t));var A=".smartmenus_scroll";if(t.dataSM("scroll",{y:this.cssTransforms3d?0:i-m,step:1,itemH:m,subH:h,arrowDownH:this.getHeight(t.dataSM("scroll-arrows").eq(1))}).on(getEventsNS({mouseover:function(e){x.menuScrollOver(t,e)},mouseout:function(e){x.menuScrollOut(t,e)},"mousewheel DOMMouseScroll":function(e){x.menuScrollMousewheel(t,e)}},A)).dataSM("scroll-arrows").css({top:"auto",left:"0",marginLeft:e+(parseInt(t.css("border-left-width"))||0),width:r-(parseInt(t.css("border-left-width"))||0)-(parseInt(t.css("border-right-width"))||0),zIndex:t.css("z-index")}).eq(g&&this.opts.bottomToTopSubMenus?0:1).show(),this.isFixed()){var C={};C[touchEvents?"touchstart touchmove touchend":"pointerdown pointermove pointerup MSPointerDown MSPointerMove MSPointerUp"]=function(e){x.menuScrollTouch(t,e)},t.css({"touch-action":"none","-ms-touch-action":"none"}).on(getEventsNS(C,A))}}}t.css({top:"auto",left:"0",marginLeft:e,marginTop:i-m})},menuScroll:function(t,e,i){var s,o=t.dataSM("scroll"), +a=t.dataSM("scroll-arrows"),n=o.up?o.upEnd:o.downEnd;if(!e&&o.momentum){if(o.momentum*=.92,s=o.momentum,.5>s)return this.menuScrollStop(t),void 0}else s=i||(e||!this.opts.scrollAccelerate?this.opts.scrollStep:Math.floor(o.step));var r=t.dataSM("level");if(this.activatedItems[r-1]&&this.activatedItems[r-1].dataSM("sub")&&this.activatedItems[r-1].dataSM("sub").is(":visible")&&this.menuHideSubMenus(r-1),o.y=o.up&&o.y>=n||!o.up&&n>=o.y?o.y:Math.abs(n-o.y)>s?o.y+(o.up?s:-s):n,t.css(this.cssTransforms3d?{"-webkit-transform":"translate3d(0, "+o.y+"px, 0)",transform:"translate3d(0, "+o.y+"px, 0)"}:{marginTop:o.y}),mouse&&(o.up&&o.y>o.downEnd||!o.up&&o.y0;t.dataSM("scroll-arrows").eq(i?0:1).is(":visible")&&(t.dataSM("scroll").up=i,this.menuScroll(t,!0))}e.preventDefault()},menuScrollOut:function(t,e){mouse&&(/^scroll-(up|down)/.test((e.relatedTarget||"").className)||(t[0]==e.relatedTarget||$.contains(t[0],e.relatedTarget))&&this.getClosestMenu(e.relatedTarget)==t[0]||t.dataSM("scroll-arrows").css("visibility","hidden"))},menuScrollOver:function(t,e){if(mouse&&!/^scroll-(up|down)/.test(e.target.className)&&this.getClosestMenu(e.target)==t[0]){this.menuScrollRefreshData(t);var i=t.dataSM("scroll"),s=$(window).scrollTop()-t.dataSM("parent-a").offset().top-i.itemH;t.dataSM("scroll-arrows").eq(0).css("margin-top",s).end().eq(1).css("margin-top",s+this.getViewportHeight()-i.arrowDownH).end().css("visibility","visible")}},menuScrollRefreshData:function(t){var e=t.dataSM("scroll"),i=$(window).scrollTop()-t.dataSM("parent-a").offset().top-e.itemH;this.cssTransforms3d&&(i=-(parseFloat(t.css("margin-top"))-i)),$.extend(e,{upEnd:i, +downEnd:i+this.getViewportHeight()-e.subH})},menuScrollStop:function(t){return this.scrollTimeout?(cancelAnimationFrame(this.scrollTimeout),this.scrollTimeout=0,t.dataSM("scroll").step=1,!0):void 0},menuScrollTouch:function(t,e){if(e=e.originalEvent,isTouchEvent(e)){var i=this.getTouchPoint(e);if(this.getClosestMenu(i.target)==t[0]){var s=t.dataSM("scroll");if(/(start|down)$/i.test(e.type))this.menuScrollStop(t)?(e.preventDefault(),this.$touchScrollingSub=t):this.$touchScrollingSub=null,this.menuScrollRefreshData(t),$.extend(s,{touchStartY:i.pageY,touchStartTime:e.timeStamp});else if(/move$/i.test(e.type)){var o=void 0!==s.touchY?s.touchY:s.touchStartY;if(void 0!==o&&o!=i.pageY){this.$touchScrollingSub=t;var a=i.pageY>o;void 0!==s.up&&s.up!=a&&$.extend(s,{touchStartY:i.pageY,touchStartTime:e.timeStamp}),$.extend(s,{up:a,touchY:i.pageY}),this.menuScroll(t,!0,Math.abs(i.pageY-o))}e.preventDefault()}else void 0!==s.touchY&&((s.momentum=15*Math.pow(Math.abs(i.pageY-s.touchStartY)/(e.timeStamp-s.touchStartTime),2) +)&&(this.menuScrollStop(t),this.menuScroll(t),e.preventDefault()),delete s.touchY)}}},menuShow:function(t){if((t.dataSM("beforefirstshowfired")||(t.dataSM("beforefirstshowfired",!0),this.$root.triggerHandler("beforefirstshow.smapi",t[0])!==!1))&&this.$root.triggerHandler("beforeshow.smapi",t[0])!==!1&&(t.dataSM("shown-before",!0),canAnimate&&t.stop(!0,!0),!t.is(":visible"))){var e=t.dataSM("parent-a"),i=this.isCollapsible();if((this.opts.keepHighlighted||i)&&e.addClass("highlighted"),i)t.removeClass("sm-nowrap").css({zIndex:"",width:"auto",minWidth:"",maxWidth:"",top:"",left:"",marginLeft:"",marginTop:""});else{if(t.css("z-index",this.zIndexInc=(this.zIndexInc||this.getStartZIndex())+1),(this.opts.subMenusMinWidth||this.opts.subMenusMaxWidth)&&(t.css({width:"auto",minWidth:"",maxWidth:""}).addClass("sm-nowrap"),this.opts.subMenusMinWidth&&t.css("min-width",this.opts.subMenusMinWidth),this.opts.subMenusMaxWidth)){var s=this.getWidth(t);t.css("max-width",this.opts.subMenusMaxWidth),s>this.getWidth(t +)&&t.removeClass("sm-nowrap").css("width",this.opts.subMenusMaxWidth)}this.menuPosition(t)}var o=function(){t.css("overflow","")};i?canAnimate&&this.opts.collapsibleShowFunction?this.opts.collapsibleShowFunction.call(this,t,o):t.show(this.opts.collapsibleShowDuration,o):canAnimate&&this.opts.showFunction?this.opts.showFunction.call(this,t,o):t.show(this.opts.showDuration,o),e.attr("aria-expanded","true"),t.attr({"aria-expanded":"true","aria-hidden":"false"}),this.visibleSubMenus.push(t),this.$root.triggerHandler("show.smapi",t[0])}},popupHide:function(t){this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=0);var e=this;this.hideTimeout=setTimeout(function(){e.menuHideAll()},t?1:this.opts.hideTimeout)},popupShow:function(t,e){if(!this.opts.isPopup)return alert('SmartMenus jQuery Error:\n\nIf you want to show this menu via the "popupShow" method, set the isPopup:true option.'),void 0;if(this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=0),this.$root.dataSM("shown-before",!0), +canAnimate&&this.$root.stop(!0,!0),!this.$root.is(":visible")){this.$root.css({left:t,top:e});var i=this,s=function(){i.$root.css("overflow","")};canAnimate&&this.opts.showFunction?this.opts.showFunction.call(this,this.$root,s):this.$root.show(this.opts.showDuration,s),this.visibleSubMenus[0]=this.$root}},refresh:function(){this.destroy(!0),this.init(!0)},rootKeyDown:function(t){if(this.handleEvents())switch(t.keyCode){case 27:var e=this.activatedItems[0];if(e){this.menuHideAll(),e[0].focus();var i=e.dataSM("sub");i&&this.menuHide(i)}break;case 32:var s=$(t.target);if(s.is("a")&&this.handleItemEvents(s)){var i=s.dataSM("sub");i&&!i.is(":visible")&&(this.itemClick({currentTarget:t.target}),t.preventDefault())}}},rootOut:function(t){if(this.handleEvents()&&!this.isTouchMode()&&t.target!=this.$root[0]&&(this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=0),!this.opts.showOnClick||!this.opts.hideOnClick)){var e=this;this.hideTimeout=setTimeout(function(){e.menuHideAll()},this.opts.hideTimeout)}}, +rootOver:function(t){this.handleEvents()&&!this.isTouchMode()&&t.target!=this.$root[0]&&this.hideTimeout&&(clearTimeout(this.hideTimeout),this.hideTimeout=0)},winResize:function(t){if(this.handleEvents()){if(!("onorientationchange"in window)||"orientationchange"==t.type){var e=this.isCollapsible();this.wasCollapsible&&e||(this.activatedItems.length&&this.activatedItems[this.activatedItems.length-1][0].blur(),this.menuHideAll()),this.wasCollapsible=e}}else if(this.$disableOverlay){var i=this.$root.offset();this.$disableOverlay.css({top:i.top,left:i.left,width:this.$root.outerWidth(),height:this.$root.outerHeight()})}}}}),$.fn.dataSM=function(t,e){return e?this.data(t+"_smartmenus",e):this.data(t+"_smartmenus")},$.fn.removeDataSM=function(t){return this.removeData(t+"_smartmenus")},$.fn.smartmenus=function(options){if("string"==typeof options){var args=arguments,method=options;return Array.prototype.shift.call(args),this.each(function(){var t=$(this).data("smartmenus");t&&t[method]&&t[method].apply(t,args)})} +return this.each(function(){var dataOpts=$(this).data("sm-options")||null;if(dataOpts)try{dataOpts=eval("("+dataOpts+")")}catch(e){dataOpts=null,alert('ERROR\n\nSmartMenus jQuery init:\nInvalid "data-sm-options" attribute value syntax.')}new $.SmartMenus(this,$.extend({},$.fn.smartmenus.defaults,options,dataOpts))})},$.fn.smartmenus.defaults={isPopup:!1,mainMenuSubOffsetX:0,mainMenuSubOffsetY:0,subMenusSubOffsetX:0,subMenusSubOffsetY:0,subMenusMinWidth:"10em",subMenusMaxWidth:"20em",subIndicators:!0,subIndicatorsPos:"append",subIndicatorsText:"",scrollStep:30,scrollAccelerate:!0,showTimeout:250,hideTimeout:500,showDuration:0,showFunction:null,hideDuration:0,hideFunction:function(t,e){t.fadeOut(200,e)},collapsibleShowDuration:0,collapsibleShowFunction:function(t,e){t.slideDown(200,e)},collapsibleHideDuration:0,collapsibleHideFunction:function(t,e){t.slideUp(200,e)},showOnClick:!1,hideOnClick:!0,noMouseOver:!1,keepInViewport:!0,keepHighlighted:!0,markCurrentItem:!1,markCurrentTree:!0,rightToLeftSubMenus:!1, +bottomToTopSubMenus:!1,collapsibleBehavior:"default"},$}); diff --git a/documents/html/menu.js b/documents/html/menu.js new file mode 100644 index 000000000..15f9c522d --- /dev/null +++ b/documents/html/menu.js @@ -0,0 +1,131 @@ +/* + @licstart The following is the entire license notice for the JavaScript code in this file. + + The MIT License (MIT) + + Copyright (C) 1997-2020 by Dimitri van Heesch + + Permission is hereby granted, free of charge, to any person obtaining a copy of this software + and associated documentation files (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, publish, distribute, + sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or + substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING + BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + @licend The above is the entire license notice for the JavaScript code in this file + */ +function initMenu(relPath,searchEnabled,serverSide,searchPage,search,treeview) { + function makeTree(data,relPath) { + let result=''; + if ('children' in data) { + result+='
    '; + for (let i in data.children) { + let url; + const link = data.children[i].url; + if (link.substring(0,1)=='^') { + url = link.substring(1); + } else { + url = relPath+link; + } + result+='
  • '+ + data.children[i].text+''+ + makeTree(data.children[i],relPath)+'
  • '; + } + result+='
'; + } + return result; + } + let searchBoxHtml; + if (searchEnabled) { + if (serverSide) { + searchBoxHtml='
'+ + '
'+ + '
'+ + ''+ + '
'+ + '
'+ + '
'+ + '
'; + } else { + searchBoxHtml='
'+ + ''+ + ''+ + ''+ + ''+ + ''+ + '
'+ + '
'+ + '
'; + } + } + + $('#main-nav').before('
'+ + ''+ + ''+ + '
'); + $('#main-nav').append(makeTree(menudata,relPath)); + $('#main-nav').children(':first').addClass('sm sm-dox').attr('id','main-menu'); + $('#main-menu').append('
  • '); + const $mainMenuState = $('#main-menu-state'); + let prevWidth = 0; + if ($mainMenuState.length) { + const initResizableIfExists = function() { + if (typeof initResizable==='function') initResizable(treeview); + } + // animate mobile menu + $mainMenuState.change(function() { + const $menu = $('#main-menu'); + let options = { duration: 250, step: initResizableIfExists }; + if (this.checked) { + options['complete'] = () => $menu.css('display', 'block'); + $menu.hide().slideDown(options); + } else { + options['complete'] = () => $menu.css('display', 'none'); + $menu.show().slideUp(options); + } + }); + // set default menu visibility + const resetState = function() { + const $menu = $('#main-menu'); + const newWidth = $(window).outerWidth(); + if (newWidth!=prevWidth) { + if ($(window).outerWidth()<768) { + $mainMenuState.prop('checked',false); $menu.hide(); + $('#searchBoxPos1').html(searchBoxHtml); + $('#searchBoxPos2').hide(); + } else { + $menu.show(); + $('#searchBoxPos1').empty(); + $('#searchBoxPos2').html(searchBoxHtml); + $('#searchBoxPos2').show(); + } + if (typeof searchBox!=='undefined') { + searchBox.CloseResultsWindow(); + } + prevWidth = newWidth; + } + } + $(window).ready(function() { resetState(); initResizableIfExists(); }); + $(window).resize(resetState); + } + $('#main-menu').smartmenus(); +} +/* @license-end */ diff --git a/documents/html/menudata.js b/documents/html/menudata.js new file mode 100644 index 000000000..0f9fea98e --- /dev/null +++ b/documents/html/menudata.js @@ -0,0 +1,98 @@ +/* + @licstart The following is the entire license notice for the JavaScript code in this file. + + The MIT License (MIT) + + Copyright (C) 1997-2020 by Dimitri van Heesch + + Permission is hereby granted, free of charge, to any person obtaining a copy of this software + and associated documentation files (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, publish, distribute, + sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or + substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING + BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + @licend The above is the entire license notice for the JavaScript code in this file +*/ +var menudata={children:[ +{text:"Main Page",url:"index.html"}, +{text:"Namespaces",url:"namespaces.html",children:[ +{text:"Namespace List",url:"namespaces.html"}, +{text:"Namespace Members",url:"namespacemembers.html",children:[ +{text:"All",url:"namespacemembers.html"}, +{text:"Variables",url:"namespacemembers_vars.html"}]}]}, +{text:"Classes",url:"annotated.html",children:[ +{text:"Class List",url:"annotated.html"}, +{text:"Class Index",url:"classes.html"}, +{text:"Class Hierarchy",url:"hierarchy.html"}, +{text:"Class Members",url:"functions.html",children:[ +{text:"All",url:"functions.html",children:[ +{text:"_",url:"functions.html#index__5F"}, +{text:"a",url:"functions.html#index_a"}, +{text:"b",url:"functions.html#index_b"}, +{text:"c",url:"functions.html#index_c"}, +{text:"d",url:"functions.html#index_d"}, +{text:"e",url:"functions.html#index_e"}, +{text:"f",url:"functions.html#index_f"}, +{text:"g",url:"functions.html#index_g"}, +{text:"h",url:"functions.html#index_h"}, +{text:"i",url:"functions.html#index_i"}, +{text:"j",url:"functions.html#index_j"}, +{text:"k",url:"functions.html#index_k"}, +{text:"l",url:"functions.html#index_l"}, +{text:"m",url:"functions.html#index_m"}, +{text:"n",url:"functions.html#index_n"}, +{text:"o",url:"functions.html#index_o"}, +{text:"p",url:"functions.html#index_p"}, +{text:"r",url:"functions.html#index_r"}, +{text:"s",url:"functions.html#index_s"}, +{text:"t",url:"functions.html#index_t"}, +{text:"v",url:"functions.html#index_v"}, +{text:"w",url:"functions.html#index_w"}]}, +{text:"Functions",url:"functions_func.html",children:[ +{text:"a",url:"functions_func.html#index_a"}, +{text:"e",url:"functions_func.html#index_e"}, +{text:"f",url:"functions_func.html#index_f"}, +{text:"g",url:"functions_func.html#index_g"}, +{text:"i",url:"functions_func.html#index_i"}, +{text:"j",url:"functions_func.html#index_j"}, +{text:"l",url:"functions_func.html#index_l"}, +{text:"m",url:"functions_func.html#index_m"}, +{text:"p",url:"functions_func.html#index_p"}, +{text:"s",url:"functions_func.html#index_s"}, +{text:"v",url:"functions_func.html#index_v"}, +{text:"w",url:"functions_func.html#index_w"}]}, +{text:"Variables",url:"functions_vars.html",children:[ +{text:"_",url:"functions_vars.html#index__5F"}, +{text:"a",url:"functions_vars.html#index_a"}, +{text:"b",url:"functions_vars.html#index_b"}, +{text:"c",url:"functions_vars.html#index_c"}, +{text:"d",url:"functions_vars.html#index_d"}, +{text:"e",url:"functions_vars.html#index_e"}, +{text:"f",url:"functions_vars.html#index_f"}, +{text:"g",url:"functions_vars.html#index_g"}, +{text:"h",url:"functions_vars.html#index_h"}, +{text:"i",url:"functions_vars.html#index_i"}, +{text:"k",url:"functions_vars.html#index_k"}, +{text:"l",url:"functions_vars.html#index_l"}, +{text:"m",url:"functions_vars.html#index_m"}, +{text:"n",url:"functions_vars.html#index_n"}, +{text:"o",url:"functions_vars.html#index_o"}, +{text:"r",url:"functions_vars.html#index_r"}, +{text:"s",url:"functions_vars.html#index_s"}, +{text:"t",url:"functions_vars.html#index_t"}, +{text:"v",url:"functions_vars.html#index_v"}]}]}]}, +{text:"Files",url:"files.html",children:[ +{text:"File List",url:"files.html"}, +{text:"File Members",url:"globals.html",children:[ +{text:"All",url:"globals.html"}, +{text:"Functions",url:"globals_func.html"}, +{text:"Variables",url:"globals_vars.html"}]}]}]} diff --git a/documents/html/namespace_f_b_e.html b/documents/html/namespace_f_b_e.html new file mode 100644 index 000000000..50700d51f --- /dev/null +++ b/documents/html/namespace_f_b_e.html @@ -0,0 +1,144 @@ + + + + + + + +FastBinaryEncoding: FBE Namespace Reference + + + + + + + + + + + +
    +
    + + + + + + +
    +
    FastBinaryEncoding 1.15.0.0 +
    +
    Fast Binary Encoding
    +
    +
    + + + + + + + + + +
    +
    + + +
    +
    +
    +
    +
    +
    Loading...
    +
    Searching...
    +
    No Matches
    +
    +
    +
    +
    + +
    +
    +
    + +
    FBE Namespace Reference
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    +Classes

    struct  Attributes
    struct  EnumConst
    struct  EnumValue
    struct  EnumBody
    struct  EnumType
    struct  FlagsConst
    struct  FlagsValue
    struct  FlagsBody
    struct  FlagsType
    struct  StructField
    struct  StructBody
    struct  StructRequest
    struct  StructResponse
    struct  StructReject
    struct  StructRejects
    struct  StructType
    struct  Statement
    struct  Statements
    struct  Import
    struct  Version
    struct  Package
    class  Generator
    class  GeneratorCpp
    class  GeneratorCSharp
    class  GeneratorGo
    class  GeneratorJava
    class  GeneratorJavaScript
    class  GeneratorKotlin
    class  GeneratorPython
    class  GeneratorRuby
    class  GeneratorSwift
    + + +

    +Variables

    const char version [] = "1.15.0.0"
    +

    Variable Documentation

    + +

    ◆ version

    + +
    +
    + + + + +
    const char FBE::version[] = "1.15.0.0"
    +
    + +

    Definition at line 15 of file version.h.

    + +
    +
    +
    + + +
    + + diff --git a/documents/html/namespacemembers.html b/documents/html/namespacemembers.html new file mode 100644 index 000000000..c713bbc13 --- /dev/null +++ b/documents/html/namespacemembers.html @@ -0,0 +1,85 @@ + + + + + + + +FastBinaryEncoding: Namespace Members + + + + + + + + + + + +
    +
    + + + + + + +
    +
    FastBinaryEncoding 1.15.0.0 +
    +
    Fast Binary Encoding
    +
    +
    + + + + + + + + +
    +
    + +
    +
    + + +
    +
    +
    +
    +
    +
    Loading...
    +
    Searching...
    +
    No Matches
    +
    +
    +
    +
    + +
    +
    Here is a list of all namespace members with links to the namespace documentation for each member:
      +
    • version : FBE
    • +
    +
    + + +
    + + diff --git a/documents/html/namespacemembers_vars.html b/documents/html/namespacemembers_vars.html new file mode 100644 index 000000000..07a0ee1a2 --- /dev/null +++ b/documents/html/namespacemembers_vars.html @@ -0,0 +1,85 @@ + + + + + + + +FastBinaryEncoding: Namespace Members + + + + + + + + + + + +
    +
    + + + + + + +
    +
    FastBinaryEncoding 1.15.0.0 +
    +
    Fast Binary Encoding
    +
    +
    + + + + + + + + +
    +
    + +
    +
    + + +
    +
    +
    +
    +
    +
    Loading...
    +
    Searching...
    +
    No Matches
    +
    +
    +
    +
    + +
    +
    Here is a list of all namespace variables with links to the namespace documentation for each variable:
      +
    • version : FBE
    • +
    +
    + + +
    + + diff --git a/documents/html/namespaces.html b/documents/html/namespaces.html new file mode 100644 index 000000000..2975c2cf8 --- /dev/null +++ b/documents/html/namespaces.html @@ -0,0 +1,90 @@ + + + + + + + +FastBinaryEncoding: Namespace List + + + + + + + + + + + +
    +
    + + + + + + +
    +
    FastBinaryEncoding 1.15.0.0 +
    +
    Fast Binary Encoding
    +
    +
    + + + + + + + + +
    +
    + +
    +
    + + +
    +
    +
    +
    +
    +
    Loading...
    +
    Searching...
    +
    No Matches
    +
    +
    +
    +
    + +
    +
    Namespace List
    +
    +
    +
    Here is a list of all namespaces with brief descriptions:
    + + +
     NFBE
    +
    +
    + + +
    + + diff --git a/documents/html/navtree.css b/documents/html/navtree.css new file mode 100644 index 000000000..0ea3a07a5 --- /dev/null +++ b/documents/html/navtree.css @@ -0,0 +1,327 @@ +#nav-tree .children_ul { + margin:0; + padding:4px; +} + +#nav-tree ul { + list-style:none outside none; + margin:0px; + padding:0px; +} + +#nav-tree li { + white-space:nowrap; + margin:0; + padding:0; +} + +#nav-tree .plus { + margin:0px; +} + +#nav-tree .selected { + position: relative; + background-color: var(--nav-menu-active-bg); + border-radius: 0 6px 6px 0; + /*margin-right: 5px;*/ +} + +#nav-tree img { + margin:0px; + padding:0px; + border:0px; + vertical-align: middle; +} + +#nav-tree a { + text-decoration:none; + padding:0px; + margin:0px; +} + +#nav-tree .label { + margin:0px; + padding:0px; + font: 12px var(--font-family-nav); + line-height: 22px; +} + +#nav-tree .label a { + padding:2px; +} + +#nav-tree .selected a { + text-decoration:none; + color:var(--page-link-color); +} + +#nav-tree .children_ul { + margin:0px; + padding:0px; +} + +#nav-tree .item { + margin: 0 6px 0 -5px; + padding: 0 0 0 5px; + height: 22px; +} + +#nav-tree { + padding: 0px 0px; + font-size:14px; + overflow:auto; +} + +#doc-content { + overflow:auto; + display:block; + padding:0px; + margin:0px; + -webkit-overflow-scrolling : touch; /* iOS 5+ */ +} + +#side-nav { + padding:0 6px 0 0; + margin: 0px; + display:block; + position: absolute; + left: 0px; + overflow : hidden; +} + +.ui-resizable .ui-resizable-handle { + display:block; +} + +.ui-resizable-e { + transition: opacity 0.5s ease; + background-color: var(--nav-splitbar-bg-color); + opacity:0; + cursor:col-resize; + height:100%; + right:0; + top:0; + width:6px; + position: relative; +} + +.ui-resizable-e:after { + content: ''; + display: block; + top: 50%; + left: 1px; + width: 2px; + height: 15px; + border-left: 1px solid var(--nav-splitbar-handle-color); + border-right: 1px solid var(--nav-splitbar-handle-color); + position: absolute; +} + +.ui-resizable-e:hover { + opacity: 1; +} + +.ui-resizable-handle { + display:none; + font-size:0.1px; + position:absolute; + z-index:1; +} + +#nav-tree-contents { + margin: 6px 0px 0px 0px; +} + +#nav-tree { + background-color: var(--nav-background-color); + -webkit-overflow-scrolling : touch; /* iOS 5+ */ + scrollbar-width: thin; + border-right: 1px solid var(--nav-border-color); + padding-left: 5px; +} + +#nav-sync { + position:absolute; + top:0px; + right:0px; + z-index:1; +} + +#nav-sync img { + opacity:0.3; +} + +div.nav-sync-icon { + position: relative; + width: 24px; + height: 17px; + left: -6px; + top: -1px; + opacity: 0.7; + display: inline-block; + background-color: var(--sync-icon-background-color); + border: 1px solid var(--sync-icon-border-color); + box-sizing: content-box; +} + +div.nav-sync-icon:hover { + background-color: var(--sync-icon-selected-background-color); + opacity: 1.0; +} + +div.nav-sync-icon.active:after { + content: ''; + background-color: var(--sync-icon-background-color); + border-top: 2px solid var(--sync-icon-color); + position: absolute; + width: 16px; + height: 0px; + top: 7px; + left: 4px; +} + +div.nav-sync-icon.active:hover:after { + border-top: 2px solid var(--sync-icon-selected-color); +} + +span.sync-icon-left { + position: absolute; + padding: 0; + margin: 0; + top: 3px; + left: 4px; + display: inline-block; + width: 8px; + height: 8px; + border-left: 2px solid var(--sync-icon-color); + border-top: 2px solid var(--sync-icon-color); + transform: rotate(-45deg); +} + +span.sync-icon-right { + position: absolute; + padding: 0; + margin: 0; + top: 3px; + left: 10px; + display: inline-block; + width: 8px; + height: 8px; + border-right: 2px solid var(--sync-icon-color); + border-bottom: 2px solid var(--sync-icon-color); + transform: rotate(-45deg); +} + +div.nav-sync-icon:hover span.sync-icon-left { + border-left: 2px solid var(--sync-icon-selected-color); + border-top: 2px solid var(--sync-icon-selected-color); +} + +div.nav-sync-icon:hover span.sync-icon-right { + border-right: 2px solid var(--sync-icon-selected-color); + border-bottom: 2px solid var(--sync-icon-selected-color); +} + +#nav-path ul { + border-top: 1px solid var(--nav-breadcrumb-separator-color); +} + +@media print +{ + #nav-tree { display: none; } + div.ui-resizable-handle { display: none; position: relative; } +} + +/*---------------------------*/ +#container { + display: grid; + grid-template-columns: auto auto; + overflow: hidden; +} + +#page-nav { + background: var(--nav-background-color); + display: block; + width: 250px; + box-sizing: content-box; + position: relative; + border-left: 1px solid var(--nav-border-color); +} + +#page-nav-tree { + display: inline-block; +} + +#page-nav-resize-handle { + transition: opacity 0.5s ease; + background-color: var(--nav-splitbar-bg-color); + opacity:0; + cursor:col-resize; + height:100%; + right:0; + top:0; + width:6px; + position: relative; + z-index: 1; + user-select: none; +} + +#page-nav-resize-handle:after { + content: ''; + display: block; + top: 50%; + left: 1px; + width: 2px; + height: 15px; + border-left: 1px solid var(--nav-splitbar-handle-color); + border-right: 1px solid var(--nav-splitbar-handle-color); + position: absolute; +} + +#page-nav-resize-handle.dragging, +#page-nav-resize-handle:hover { + opacity: 1; +} + +#page-nav-contents { + padding: 0; + margin: 0; + display: block; + top: 0; + left: 0; + height: 100%; + width: 100%; + position: absolute; + overflow: auto; + scrollbar-width: thin; + -webkit-overflow-scrolling : touch; /* iOS 5+ */ +} + +ul.page-outline, +ul.page-outline ul { + text-indent: 0; + list-style: none outside none; + padding: 0 0 0 4px; +} + +ul.page-outline { + margin: 0 4px 4px 6px; +} + +ul.page-outline div.item { + font: 12px var(--font-family-nav); + line-height: 22px; +} + +ul.page-outline li { + white-space: nowrap; +} + +ul.page-outline li.vis { + background-color: var(--nav-breadcrumb-active-bg); +} + +#container.resizing { + cursor: col-resize; + user-select: none; +} diff --git a/documents/html/search/all_0.js b/documents/html/search/all_0.js new file mode 100644 index 000000000..30ff8677c --- /dev/null +++ b/documents/html/search/all_0.js @@ -0,0 +1,9 @@ +var searchData= +[ + ['_5fbuffer_0',['_buffer',['../class_f_b_e_1_1_generator.html#ad9f2df99d420bb605f742af6661ffc79',1,'FBE::Generator']]], + ['_5fcursor_1',['_cursor',['../class_f_b_e_1_1_generator.html#a75f5c696a53bad681e0ece2b2adcf4cf',1,'FBE::Generator']]], + ['_5findent_2',['_indent',['../class_f_b_e_1_1_generator.html#aa0b5fd577012b5875458cc63f7637be3',1,'FBE::Generator']]], + ['_5finput_3',['_input',['../class_f_b_e_1_1_generator.html#a7b58d6e8262763ae3b74a588c31a62c7',1,'FBE::Generator']]], + ['_5foutput_4',['_output',['../class_f_b_e_1_1_generator.html#ab02a44c5ed682d240135826fc6ef8340',1,'FBE::Generator']]], + ['_5fspace_5',['_space',['../class_f_b_e_1_1_generator.html#a6372da6d8b20a5e3e7d5a6707d413778',1,'FBE::Generator']]] +]; diff --git a/documents/html/search/all_1.js b/documents/html/search/all_1.js new file mode 100644 index 000000000..bb29ccfda --- /dev/null +++ b/documents/html/search/all_1.js @@ -0,0 +1,14 @@ +var searchData= +[ + ['addenum_0',['AddEnum',['../struct_f_b_e_1_1_statements.html#a6f741111b23b343cc3a81b3478f84471',1,'FBE::Statements']]], + ['addfield_1',['AddField',['../struct_f_b_e_1_1_struct_body.html#a4760c4da4fc917201f73e3fc12a6e572',1,'FBE::StructBody']]], + ['addflags_2',['AddFlags',['../struct_f_b_e_1_1_statements.html#a1cc1519825446a301deca7f9b8945135',1,'FBE::Statements']]], + ['addimport_3',['AddImport',['../struct_f_b_e_1_1_import.html#a77750b41d35db2e1e23f4670103dca0b',1,'FBE::Import']]], + ['addreject_4',['AddReject',['../struct_f_b_e_1_1_struct_rejects.html#a5172761722db77ec4f16aedd9629e4ca',1,'FBE::StructRejects']]], + ['addstatement_5',['AddStatement',['../struct_f_b_e_1_1_statements.html#aa267edbe1b0b702237fe2b7762c38e9e',1,'FBE::Statements']]], + ['addstruct_6',['AddStruct',['../struct_f_b_e_1_1_statements.html#a9c65826ba2117acd94cd70e09052e9d0',1,'FBE::Statements']]], + ['addvalue_7',['AddValue',['../struct_f_b_e_1_1_enum_body.html#a6e5dfd73a4a7cb509c44a085a391f087',1,'FBE::EnumBody::AddValue()'],['../struct_f_b_e_1_1_flags_body.html#a2fa3b0930898923930f1366eecbd5544',1,'FBE::FlagsBody::AddValue()']]], + ['array_8',['array',['../struct_f_b_e_1_1_struct_field.html#a2f17f92ad8cf34870ad73d190635c7fb',1,'FBE::StructField']]], + ['attributes_9',['Attributes',['../struct_f_b_e_1_1_attributes.html',1,'FBE']]], + ['attributes_10',['attributes',['../struct_f_b_e_1_1_enum_value.html#a9c929cfab852d30aa3eeac3eb3a9f10f',1,'FBE::EnumValue::attributes'],['../struct_f_b_e_1_1_enum_type.html#a94c91f54e87f568808758f1c6951c031',1,'FBE::EnumType::attributes'],['../struct_f_b_e_1_1_flags_value.html#a1d5e28b42a97341f4303bc7724aafd21',1,'FBE::FlagsValue::attributes'],['../struct_f_b_e_1_1_flags_type.html#ac3ee58fb63ae1ed27ca83fa6b9a5be92',1,'FBE::FlagsType::attributes'],['../struct_f_b_e_1_1_struct_field.html#ae8a99ad6597022951bfc0210eea34c9a',1,'FBE::StructField::attributes'],['../struct_f_b_e_1_1_struct_type.html#a1b0f245b94424fd285475ae82d2353d9',1,'FBE::StructType::attributes']]] +]; diff --git a/documents/html/search/all_10.js b/documents/html/search/all_10.js new file mode 100644 index 000000000..02d35573a --- /dev/null +++ b/documents/html/search/all_10.js @@ -0,0 +1,5 @@ +var searchData= +[ + ['package_0',['Package',['../struct_f_b_e_1_1_package.html',1,'FBE::Package'],['../struct_f_b_e_1_1_package.html#aa2a5a2ba45503345e6c016508fceeeaa',1,'FBE::Package::Package()']]], + ['proto_1',['Proto',['../class_f_b_e_1_1_generator_cpp.html#a21ab15f74b25f32b709ba00e4aa7d622',1,'FBE::GeneratorCpp::Proto() const noexcept'],['../class_f_b_e_1_1_generator_cpp.html#a2e6583e9a7ba00edbb75aff09835efb7',1,'FBE::GeneratorCpp::Proto(bool proto) noexcept'],['../class_f_b_e_1_1_generator_c_sharp.html#ab9398c91d39f3c3318f832a26d30a647',1,'FBE::GeneratorCSharp::Proto() const noexcept'],['../class_f_b_e_1_1_generator_c_sharp.html#a704d83732c9fc16c57e182dafac31a91',1,'FBE::GeneratorCSharp::Proto(bool proto) noexcept'],['../class_f_b_e_1_1_generator_go.html#ade7ac2f7121d8964de6debcba416bfc6',1,'FBE::GeneratorGo::Proto() const noexcept'],['../class_f_b_e_1_1_generator_go.html#a309d080fd76fed3083172ff24b6446e2',1,'FBE::GeneratorGo::Proto(bool proto) noexcept'],['../class_f_b_e_1_1_generator_java.html#abd9b4d911301864ec9885c8b41f644e4',1,'FBE::GeneratorJava::Proto() const noexcept'],['../class_f_b_e_1_1_generator_java.html#a8fc27769454046d8f95d5b3b6f904145',1,'FBE::GeneratorJava::Proto(bool proto) noexcept'],['../class_f_b_e_1_1_generator_java_script.html#a18127dd7e5ea89376107f5666ef28a48',1,'FBE::GeneratorJavaScript::Proto() const noexcept'],['../class_f_b_e_1_1_generator_java_script.html#abb53e364ff969810b80b530ea2247fc2',1,'FBE::GeneratorJavaScript::Proto(bool proto) noexcept'],['../class_f_b_e_1_1_generator_kotlin.html#afb64fab23bdb33f8dfad9aee2efa5757',1,'FBE::GeneratorKotlin::Proto() const noexcept'],['../class_f_b_e_1_1_generator_kotlin.html#acfa2d83b57f112c6eddb3f00b0034048',1,'FBE::GeneratorKotlin::Proto(bool proto) noexcept'],['../class_f_b_e_1_1_generator_python.html#a08968f6d5774caaf11361efbafe96d5d',1,'FBE::GeneratorPython::Proto() const noexcept'],['../class_f_b_e_1_1_generator_python.html#a0839e975c597e26f8bfe165220c68ec2',1,'FBE::GeneratorPython::Proto(bool proto) noexcept'],['../class_f_b_e_1_1_generator_ruby.html#ac8760a0e0f5f10f84a0cdc98e47a4cee',1,'FBE::GeneratorRuby::Proto() const noexcept'],['../class_f_b_e_1_1_generator_ruby.html#acc41fb8d2f9fa5cc34e80a769e7d0e4b',1,'FBE::GeneratorRuby::Proto(bool proto) noexcept'],['../class_f_b_e_1_1_generator_swift.html#a43a38724df66b64dcc20a054ba0c1600',1,'FBE::GeneratorSwift::Proto() const noexcept'],['../class_f_b_e_1_1_generator_swift.html#a44a3146ef4c453b3322d0b19e7352602',1,'FBE::GeneratorSwift::Proto(bool proto) noexcept']]] +]; diff --git a/documents/html/search/all_11.js b/documents/html/search/all_11.js new file mode 100644 index 000000000..bf6bc4a35 --- /dev/null +++ b/documents/html/search/all_11.js @@ -0,0 +1,10 @@ +var searchData= +[ + ['reference_0',['reference',['../struct_f_b_e_1_1_enum_const.html#aedc2e6b4ffa30f2f8bcb440f8b9b726b',1,'FBE::EnumConst::reference'],['../struct_f_b_e_1_1_flags_const.html#a091b3ae1900fb52b33c0af79cfedc6b6',1,'FBE::FlagsConst::reference']]], + ['reject_1',['reject',['../struct_f_b_e_1_1_struct_reject.html#a8fd1314d0aba57dee08e22519394ec58',1,'FBE::StructReject']]], + ['rejects_2',['rejects',['../struct_f_b_e_1_1_struct_rejects.html#aac30b48bb5c457d1c8f5a96c9a023634',1,'FBE::StructRejects::rejects'],['../struct_f_b_e_1_1_struct_type.html#ad23e7c314e46c1f6ab7c16a943eab322',1,'FBE::StructType::rejects']]], + ['request_3',['request',['../struct_f_b_e_1_1_struct_type.html#a770765345d589d3e092075c3c662e0dc',1,'FBE::StructType']]], + ['reseter_4',['reseter',['../struct_f_b_e_1_1_struct_field.html#a177610f76f9a00583da7dc0537f5b971',1,'FBE::StructField']]], + ['response_5',['response',['../struct_f_b_e_1_1_struct_response.html#a13095a46d14fbb25157e6ea1345f22d8',1,'FBE::StructResponse::response'],['../struct_f_b_e_1_1_struct_type.html#a09d74609e2d772dcc3706d9e6a27be19',1,'FBE::StructType::response']]], + ['root_6',['root',['../struct_f_b_e_1_1_package.html#a82859ccee70222e493b9a068bd68a575',1,'FBE::Package']]] +]; diff --git a/documents/html/search/all_12.js b/documents/html/search/all_12.js new file mode 100644 index 000000000..8b98e2fba --- /dev/null +++ b/documents/html/search/all_12.js @@ -0,0 +1,18 @@ +var searchData= +[ + ['s_0',['s',['../struct_f_b_e_1_1_statement.html#aedbd0aebc395e0f3f19214cab8740e9f',1,'FBE::Statement']]], + ['set_1',['set',['../struct_f_b_e_1_1_struct_field.html#afa182f136bacaf11ee89d434f5434397',1,'FBE::StructField']]], + ['setarraysize_2',['SetArraySize',['../struct_f_b_e_1_1_struct_field.html#a37590ebb3e5bb54b86245597100a9154',1,'FBE::StructField']]], + ['statement_3',['Statement',['../struct_f_b_e_1_1_statement.html',1,'FBE']]], + ['statements_4',['Statements',['../struct_f_b_e_1_1_statements.html',1,'FBE']]], + ['store_5',['Store',['../class_f_b_e_1_1_generator.html#a317020135e1df2b12cb4b28f80e02d8b',1,'FBE::Generator']]], + ['structbody_6',['StructBody',['../struct_f_b_e_1_1_struct_body.html',1,'FBE']]], + ['structfield_7',['StructField',['../struct_f_b_e_1_1_struct_field.html',1,'FBE']]], + ['structreject_8',['StructReject',['../struct_f_b_e_1_1_struct_reject.html',1,'FBE']]], + ['structrejects_9',['StructRejects',['../struct_f_b_e_1_1_struct_rejects.html',1,'FBE']]], + ['structrequest_10',['StructRequest',['../struct_f_b_e_1_1_struct_request.html',1,'FBE']]], + ['structresponse_11',['StructResponse',['../struct_f_b_e_1_1_struct_response.html',1,'FBE']]], + ['structs_12',['structs',['../struct_f_b_e_1_1_statements.html#a3edb282ba76785797f6a99c8f15f5631',1,'FBE::Statements']]], + ['structtype_13',['StructType',['../struct_f_b_e_1_1_struct_type.html',1,'FBE::StructType'],['../struct_f_b_e_1_1_struct_type.html#abe2e58bd721ed0e1df3b4070445c38ec',1,'FBE::StructType::StructType(int t, bool f)']]], + ['stype_14',['stype',['../struct_f_b_e_1_1_struct_type.html#a054cbbeb3544e3f05fac058980a62bb6',1,'FBE::StructType']]] +]; diff --git a/documents/html/search/all_13.js b/documents/html/search/all_13.js new file mode 100644 index 000000000..0c52ce730 --- /dev/null +++ b/documents/html/search/all_13.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['type_0',['type',['../struct_f_b_e_1_1_struct_field.html#adb054f46c131e8390e7df67ab6c083e4',1,'FBE::StructField::type'],['../struct_f_b_e_1_1_struct_type.html#afb4c247371025bedd3e7a3f6710084de',1,'FBE::StructType::type']]] +]; diff --git a/documents/html/search/all_14.js b/documents/html/search/all_14.js new file mode 100644 index 000000000..a7dab5e3c --- /dev/null +++ b/documents/html/search/all_14.js @@ -0,0 +1,9 @@ +var searchData= +[ + ['value_0',['value',['../struct_f_b_e_1_1_enum_value.html#a6f7b3157839e710267617dc5089542eb',1,'FBE::EnumValue::value'],['../struct_f_b_e_1_1_flags_value.html#ab7c76c83cc96a9fc2f5e50d0982b63d0',1,'FBE::FlagsValue::value'],['../struct_f_b_e_1_1_struct_field.html#aec3f176737e270f82bcd815fc700c277',1,'FBE::StructField::value']]], + ['values_1',['values',['../struct_f_b_e_1_1_enum_body.html#acc572931047e81cdde318ad5d98a1b06',1,'FBE::EnumBody::values'],['../struct_f_b_e_1_1_flags_body.html#a9d294b129405702570dc72c99328c97c',1,'FBE::FlagsBody::values']]], + ['vector_2',['vector',['../struct_f_b_e_1_1_struct_field.html#a6202ac8931f0470643117b0a93a050a9',1,'FBE::StructField']]], + ['version_3',['Version',['../struct_f_b_e_1_1_version.html',1,'FBE::Version'],['../struct_f_b_e_1_1_version.html#ae2b1d0e5a6bfbc6718cd6f6d4f62ac4d',1,'FBE::Version::Version()=default'],['../struct_f_b_e_1_1_version.html#a97dcc94bdd0ec98f14ffb59ca1aef00b',1,'FBE::Version::Version(const std::string &v)'],['../class_f_b_e_1_1_generator_java.html#ab1d6ac3883e4bfa3e3c0f2526b751c6f',1,'FBE::GeneratorJava::Version() const noexcept'],['../class_f_b_e_1_1_generator_java.html#adc1faed80996bc9b68342c4cb7dc76bd',1,'FBE::GeneratorJava::Version(int v) noexcept'],['../class_f_b_e_1_1_generator_kotlin.html#a6dcf38a5a5b4d30ab1199775285e20c9',1,'FBE::GeneratorKotlin::Version() const noexcept'],['../class_f_b_e_1_1_generator_kotlin.html#a87b8027c47b4ade6d4211629219b1dad',1,'FBE::GeneratorKotlin::Version(int v) noexcept']]], + ['version_4',['version',['../struct_f_b_e_1_1_package.html#a56d53fcf570d4a1e34aa078af25bf5f5',1,'FBE::Package::version'],['../namespace_f_b_e.html#a29df7c46e2e10cb83211c546a25484de',1,'FBE::version']]], + ['version_2eh_5',['version.h',['../version_8h.html',1,'']]] +]; diff --git a/documents/html/search/all_15.js b/documents/html/search/all_15.js new file mode 100644 index 000000000..001ff321d --- /dev/null +++ b/documents/html/search/all_15.js @@ -0,0 +1,9 @@ +var searchData= +[ + ['write_0',['Write',['../class_f_b_e_1_1_generator.html#ae55fd80c0b9d0ef6190a2887d84f2639',1,'FBE::Generator']]], + ['writebegin_1',['WriteBegin',['../class_f_b_e_1_1_generator.html#a037a8f7b1c2f6df995bea922ded418d8',1,'FBE::Generator']]], + ['writeend_2',['WriteEnd',['../class_f_b_e_1_1_generator.html#aed2498685efcd442908c0c8e62fa0c8a',1,'FBE::Generator']]], + ['writeindent_3',['WriteIndent',['../class_f_b_e_1_1_generator.html#af7140aa26c3e38d967d8c4ae31963a37',1,'FBE::Generator::WriteIndent()'],['../class_f_b_e_1_1_generator.html#aa906b53274f2768bef7cb4b9c3f5ff75',1,'FBE::Generator::WriteIndent(const std::string &str)']]], + ['writeline_4',['WriteLine',['../class_f_b_e_1_1_generator.html#a9cddebdbffb75de7aca0c6a54cad4729',1,'FBE::Generator::WriteLine()'],['../class_f_b_e_1_1_generator.html#a872432c6fddf6e35f19911bf6cf494f8',1,'FBE::Generator::WriteLine(const std::string &str)']]], + ['writelineindent_5',['WriteLineIndent',['../class_f_b_e_1_1_generator.html#ab3b100edfa26f498801b910bbd4b49bd',1,'FBE::Generator']]] +]; diff --git a/documents/html/search/all_16.js b/documents/html/search/all_16.js new file mode 100644 index 000000000..cc635349a --- /dev/null +++ b/documents/html/search/all_16.js @@ -0,0 +1,13 @@ +var searchData= +[ + ['yychar_0',['yychar',['../fbe_8l.html#a7b17763b4208d3203bdc74b82653d232',1,'fbe.l']]], + ['yycolumn_1',['yycolumn',['../fbe_8l.html#ad07414281701fc1288df7325c7d52b01',1,'fbe.l']]], + ['yycount_2',['yycount',['../fbe_8l.html#a055a5458b38b06fd55209e5df6406979',1,'fbe.l']]], + ['yyerror_3',['yyerror',['../fbe_8h.html#a5f1ec9d89d16809037ec688e8c2223c8',1,'yyerror(const char *msg): fbe.l'],['../fbe_8h.html#a69d2be71b2fb587c8a37ce51b7554993',1,'yyerror(const std::string &msg): fbe.l'],['../fbe_8l.html#a5f1ec9d89d16809037ec688e8c2223c8',1,'yyerror(const char *msg): fbe.l'],['../fbe_8l.html#a69d2be71b2fb587c8a37ce51b7554993',1,'yyerror(const std::string &msg): fbe.l']]], + ['yyfile_4',['yyfile',['../fbe_8l.html#a4bbf0ec999a5f60e8ebd022922d3df3f',1,'fbe.l']]], + ['yylex_5',['yylex',['../fbe_8l.html#a9a7bd1b3d14701eb97c03f3ef34deff1',1,'fbe.l']]], + ['yyline_6',['yyline',['../fbe_8l.html#a6ea8f0bb8d095e4ff0ac5553dd2d2a3d',1,'fbe.l']]], + ['yyparse_7',['yyparse',['../fbe_8l.html#acd8617a8f2ac0de8bc1cc032cf449e19',1,'fbe.l']]], + ['yystring_8',['yystring',['../fbe_8l.html#ac266565ec4b56884d76333eac74928c6',1,'fbe.l']]], + ['yytoken_9',['yytoken',['../fbe_8l.html#a593c3cc55c469994e350c7f394161eb2',1,'fbe.l']]] +]; diff --git a/documents/html/search/all_2.js b/documents/html/search/all_2.js new file mode 100644 index 000000000..b458ad0a8 --- /dev/null +++ b/documents/html/search/all_2.js @@ -0,0 +1,5 @@ +var searchData= +[ + ['base_0',['base',['../struct_f_b_e_1_1_enum_type.html#ae1868b6f3c411d581640b843db70f475',1,'FBE::EnumType::base'],['../struct_f_b_e_1_1_flags_type.html#aa506fedbbb960f98616dfbc2a1995634',1,'FBE::FlagsType::base'],['../struct_f_b_e_1_1_struct_type.html#a55d56308e7fa04c6ac8879b31517f979',1,'FBE::StructType::base']]], + ['body_1',['body',['../struct_f_b_e_1_1_enum_type.html#ae33c0f13df08326456c3e70e72ed49bb',1,'FBE::EnumType::body'],['../struct_f_b_e_1_1_flags_type.html#a3d304800f8bf092657994579592d1f86',1,'FBE::FlagsType::body'],['../struct_f_b_e_1_1_struct_type.html#a36dd7094f7ec6024d2cdaeb7c943609b',1,'FBE::StructType::body'],['../struct_f_b_e_1_1_package.html#a780782205fd3e137496ecd5e48240490',1,'FBE::Package::body']]] +]; diff --git a/documents/html/search/all_3.js b/documents/html/search/all_3.js new file mode 100644 index 000000000..8d01f10ce --- /dev/null +++ b/documents/html/search/all_3.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['constant_0',['constant',['../struct_f_b_e_1_1_enum_const.html#a8f88153ef5ba675d7e0579567a4a86a5',1,'FBE::EnumConst::constant'],['../struct_f_b_e_1_1_flags_const.html#a4e2353426e052071832a08ddefb2a94f',1,'FBE::FlagsConst::constant']]] +]; diff --git a/documents/html/search/all_4.js b/documents/html/search/all_4.js new file mode 100644 index 000000000..117b656c6 --- /dev/null +++ b/documents/html/search/all_4.js @@ -0,0 +1,5 @@ +var searchData= +[ + ['deprecated_0',['deprecated',['../struct_f_b_e_1_1_attributes.html#aedd8b6803d4296060d06c4457d9c9970',1,'FBE::Attributes']]], + ['domain_1',['domain',['../struct_f_b_e_1_1_package.html#a58888b5b00331a363d6e33562e9af08a',1,'FBE::Package']]] +]; diff --git a/documents/html/search/all_5.js b/documents/html/search/all_5.js new file mode 100644 index 000000000..a8e2a5911 --- /dev/null +++ b/documents/html/search/all_5.js @@ -0,0 +1,10 @@ +var searchData= +[ + ['e_0',['e',['../struct_f_b_e_1_1_statement.html#a9bdf0f86452907b6cab29db2d2565656',1,'FBE::Statement']]], + ['endline_1',['EndLine',['../class_f_b_e_1_1_generator.html#a392f73b2ac0ece7b0f7ae0c035907cd5',1,'FBE::Generator']]], + ['enumbody_2',['EnumBody',['../struct_f_b_e_1_1_enum_body.html',1,'FBE']]], + ['enumconst_3',['EnumConst',['../struct_f_b_e_1_1_enum_const.html',1,'FBE']]], + ['enums_4',['enums',['../struct_f_b_e_1_1_statements.html#a81c50566162e707084a9e947dddcdb47',1,'FBE::Statements']]], + ['enumtype_5',['EnumType',['../struct_f_b_e_1_1_enum_type.html',1,'FBE']]], + ['enumvalue_6',['EnumValue',['../struct_f_b_e_1_1_enum_value.html',1,'FBE']]] +]; diff --git a/documents/html/search/all_6.js b/documents/html/search/all_6.js new file mode 100644 index 000000000..c2064e8fe --- /dev/null +++ b/documents/html/search/all_6.js @@ -0,0 +1,16 @@ +var searchData= +[ + ['f_0',['f',['../struct_f_b_e_1_1_statement.html#a25ee654eb9a18b42acec4a03eb48bd57',1,'FBE::Statement']]], + ['fbe_1',['FBE',['../namespace_f_b_e.html',1,'']]], + ['fbe_2ecpp_2',['fbe.cpp',['../fbe_8cpp.html',1,'']]], + ['fbe_2eh_3',['fbe.h',['../fbe_8h.html',1,'']]], + ['fbe_2el_4',['fbe.l',['../fbe_8l.html',1,'']]], + ['fields_5',['fields',['../struct_f_b_e_1_1_struct_body.html#a83a4a36033eec0dbd3fa5ab49060db03',1,'FBE::StructBody']]], + ['final_6',['Final',['../class_f_b_e_1_1_generator_cpp.html#af8c12f24e00cfff97ab1b7fbce070074',1,'FBE::GeneratorCpp::Final() const noexcept'],['../class_f_b_e_1_1_generator_cpp.html#ad66fe901546003265f3a478eae7d9da6',1,'FBE::GeneratorCpp::Final(bool final) noexcept'],['../class_f_b_e_1_1_generator_c_sharp.html#a3a34e76fc43b82179560153ac14203f0',1,'FBE::GeneratorCSharp::Final() const noexcept'],['../class_f_b_e_1_1_generator_c_sharp.html#a67cce180607164b764071919b4cc2065',1,'FBE::GeneratorCSharp::Final(bool final) noexcept'],['../class_f_b_e_1_1_generator_go.html#ade423e9f8d5975006ecffeca04b23c23',1,'FBE::GeneratorGo::Final() const noexcept'],['../class_f_b_e_1_1_generator_go.html#abb489fd928fdbdb7b2d01b4da78ce2d1',1,'FBE::GeneratorGo::Final(bool final) noexcept'],['../class_f_b_e_1_1_generator_java.html#a9da2535b60312cd9e4903ae72cd3e6f4',1,'FBE::GeneratorJava::Final() const noexcept'],['../class_f_b_e_1_1_generator_java.html#ac783ca318f6d6abcda9e4384a28b7617',1,'FBE::GeneratorJava::Final(bool final) noexcept'],['../class_f_b_e_1_1_generator_java_script.html#a6adc06827967cc5763497c1359d73d10',1,'FBE::GeneratorJavaScript::Final() const noexcept'],['../class_f_b_e_1_1_generator_java_script.html#af6d488425efc985ae9a94e9a3ff50ee3',1,'FBE::GeneratorJavaScript::Final(bool final) noexcept'],['../class_f_b_e_1_1_generator_kotlin.html#a3016d74d2977a054b113e7121d80d505',1,'FBE::GeneratorKotlin::Final() const noexcept'],['../class_f_b_e_1_1_generator_kotlin.html#a37de5823e865fb8d9ee7941b407002a8',1,'FBE::GeneratorKotlin::Final(bool final) noexcept'],['../class_f_b_e_1_1_generator_python.html#aac3be31a88dc5dd3296db64173f97ad7',1,'FBE::GeneratorPython::Final() const noexcept'],['../class_f_b_e_1_1_generator_python.html#aa876e67b6b8e36f92630025e64b10c82',1,'FBE::GeneratorPython::Final(bool final) noexcept'],['../class_f_b_e_1_1_generator_ruby.html#a6470926e0c131680d0eb3fcda8833df4',1,'FBE::GeneratorRuby::Final() const noexcept'],['../class_f_b_e_1_1_generator_ruby.html#a6123259acbebd0646a760b1be07149b0',1,'FBE::GeneratorRuby::Final(bool final) noexcept'],['../class_f_b_e_1_1_generator_swift.html#aa471a671b1061ec632c6a26e6b0b3faa',1,'FBE::GeneratorSwift::Final() const noexcept'],['../class_f_b_e_1_1_generator_swift.html#a5d7fb9e34a6b813162a90e957f2c4fbb',1,'FBE::GeneratorSwift::Final(bool final) noexcept']]], + ['fixed_7',['fixed',['../struct_f_b_e_1_1_struct_type.html#aa203a6312a23884f0ee49eaee5f0f1d6',1,'FBE::StructType']]], + ['flags_8',['flags',['../struct_f_b_e_1_1_statements.html#a3bb7f47199357520365cb23a7bd7082a',1,'FBE::Statements']]], + ['flagsbody_9',['FlagsBody',['../struct_f_b_e_1_1_flags_body.html',1,'FBE']]], + ['flagsconst_10',['FlagsConst',['../struct_f_b_e_1_1_flags_const.html',1,'FBE']]], + ['flagstype_11',['FlagsType',['../struct_f_b_e_1_1_flags_type.html',1,'FBE']]], + ['flagsvalue_12',['FlagsValue',['../struct_f_b_e_1_1_flags_value.html',1,'FBE']]] +]; diff --git a/documents/html/search/all_7.js b/documents/html/search/all_7.js new file mode 100644 index 000000000..7ffec6f0b --- /dev/null +++ b/documents/html/search/all_7.js @@ -0,0 +1,36 @@ +var searchData= +[ + ['generate_0',['Generate',['../class_f_b_e_1_1_generator.html#a744839cb783ad52864d6cecbd04ff09a',1,'FBE::Generator::Generate()'],['../class_f_b_e_1_1_generator_cpp.html#a91a2efa87a5c45e40d5b03b1c7a76610',1,'FBE::GeneratorCpp::Generate()'],['../class_f_b_e_1_1_generator_c_sharp.html#ac72c8f4aad681644049a377e0c4fc4c3',1,'FBE::GeneratorCSharp::Generate()'],['../class_f_b_e_1_1_generator_go.html#a9b20af92e3c9ee3bdc3f768858de5bc9',1,'FBE::GeneratorGo::Generate()'],['../class_f_b_e_1_1_generator_java.html#af921daf5d4d4d0c327c99388b4d0e908',1,'FBE::GeneratorJava::Generate()'],['../class_f_b_e_1_1_generator_java_script.html#a3a5b3a0f66818adad49a53ed06fcd608',1,'FBE::GeneratorJavaScript::Generate()'],['../class_f_b_e_1_1_generator_kotlin.html#a62483d9cc0b16e35a22be745052017ad',1,'FBE::GeneratorKotlin::Generate()'],['../class_f_b_e_1_1_generator_python.html#ad683e5df22747b4e70016bf55136db45',1,'FBE::GeneratorPython::Generate()'],['../class_f_b_e_1_1_generator_ruby.html#afc18ab9b2996a61cce4006d4b5894599',1,'FBE::GeneratorRuby::Generate()'],['../class_f_b_e_1_1_generator_swift.html#a2dbcbe840b59de66e1a48e74377de938',1,'FBE::GeneratorSwift::Generate()']]], + ['generator_1',['Generator',['../class_f_b_e_1_1_generator.html',1,'FBE::Generator'],['../class_f_b_e_1_1_generator.html#ae4868002857269b698804523c861f833',1,'FBE::Generator::Generator()'],['../class_f_b_e_1_1_generator_cpp.html#ae4868002857269b698804523c861f833',1,'FBE::GeneratorCpp::Generator()'],['../class_f_b_e_1_1_generator_c_sharp.html#ae4868002857269b698804523c861f833',1,'FBE::GeneratorCSharp::Generator()'],['../class_f_b_e_1_1_generator_go.html#ae4868002857269b698804523c861f833',1,'FBE::GeneratorGo::Generator()'],['../class_f_b_e_1_1_generator_java.html#ae4868002857269b698804523c861f833',1,'FBE::GeneratorJava::Generator()'],['../class_f_b_e_1_1_generator_java_script.html#ae4868002857269b698804523c861f833',1,'FBE::GeneratorJavaScript::Generator()'],['../class_f_b_e_1_1_generator_kotlin.html#ae4868002857269b698804523c861f833',1,'FBE::GeneratorKotlin::Generator()'],['../class_f_b_e_1_1_generator_python.html#ae4868002857269b698804523c861f833',1,'FBE::GeneratorPython::Generator()'],['../class_f_b_e_1_1_generator_ruby.html#ae4868002857269b698804523c861f833',1,'FBE::GeneratorRuby::Generator()'],['../class_f_b_e_1_1_generator_swift.html#ae4868002857269b698804523c861f833',1,'FBE::GeneratorSwift::Generator()']]], + ['generator_2ecpp_2',['generator.cpp',['../generator_8cpp.html',1,'']]], + ['generator_2eh_3',['generator.h',['../generator_8h.html',1,'']]], + ['generator_2einl_4',['generator.inl',['../generator_8inl.html',1,'']]], + ['generator_5fcpp_2ecpp_5',['generator_cpp.cpp',['../generator__cpp_8cpp.html',1,'']]], + ['generator_5fcpp_2eh_6',['generator_cpp.h',['../generator__cpp_8h.html',1,'']]], + ['generator_5fcsharp_2ecpp_7',['generator_csharp.cpp',['../generator__csharp_8cpp.html',1,'']]], + ['generator_5fcsharp_2eh_8',['generator_csharp.h',['../generator__csharp_8h.html',1,'']]], + ['generator_5fgo_2ecpp_9',['generator_go.cpp',['../generator__go_8cpp.html',1,'']]], + ['generator_5fgo_2eh_10',['generator_go.h',['../generator__go_8h.html',1,'']]], + ['generator_5fjava_2ecpp_11',['generator_java.cpp',['../generator__java_8cpp.html',1,'']]], + ['generator_5fjava_2eh_12',['generator_java.h',['../generator__java_8h.html',1,'']]], + ['generator_5fjavascript_2ecpp_13',['generator_javascript.cpp',['../generator__javascript_8cpp.html',1,'']]], + ['generator_5fjavascript_2eh_14',['generator_javascript.h',['../generator__javascript_8h.html',1,'']]], + ['generator_5fkotlin_2ecpp_15',['generator_kotlin.cpp',['../generator__kotlin_8cpp.html',1,'']]], + ['generator_5fkotlin_2eh_16',['generator_kotlin.h',['../generator__kotlin_8h.html',1,'']]], + ['generator_5fpython_2ecpp_17',['generator_python.cpp',['../generator__python_8cpp.html',1,'']]], + ['generator_5fpython_2eh_18',['generator_python.h',['../generator__python_8h.html',1,'']]], + ['generator_5fruby_2ecpp_19',['generator_ruby.cpp',['../generator__ruby_8cpp.html',1,'']]], + ['generator_5fruby_2eh_20',['generator_ruby.h',['../generator__ruby_8h.html',1,'']]], + ['generator_5fswift_2ecpp_21',['generator_swift.cpp',['../generator__swift_8cpp.html',1,'']]], + ['generator_5fswift_2eh_22',['generator_swift.h',['../generator__swift_8h.html',1,'']]], + ['generatorcpp_23',['GeneratorCpp',['../class_f_b_e_1_1_generator_cpp.html',1,'FBE']]], + ['generatorcsharp_24',['GeneratorCSharp',['../class_f_b_e_1_1_generator_c_sharp.html',1,'FBE']]], + ['generatorgo_25',['GeneratorGo',['../class_f_b_e_1_1_generator_go.html',1,'FBE']]], + ['generatorjava_26',['GeneratorJava',['../class_f_b_e_1_1_generator_java.html',1,'FBE']]], + ['generatorjavascript_27',['GeneratorJavaScript',['../class_f_b_e_1_1_generator_java_script.html',1,'FBE']]], + ['generatorkotlin_28',['GeneratorKotlin',['../class_f_b_e_1_1_generator_kotlin.html',1,'FBE']]], + ['generatorpython_29',['GeneratorPython',['../class_f_b_e_1_1_generator_python.html',1,'FBE']]], + ['generatorruby_30',['GeneratorRuby',['../class_f_b_e_1_1_generator_ruby.html',1,'FBE']]], + ['generatorswift_31',['GeneratorSwift',['../class_f_b_e_1_1_generator_swift.html',1,'FBE']]], + ['global_32',['global',['../struct_f_b_e_1_1_struct_reject.html#a59cd39bf09d7aa32975ba71444a9f63c',1,'FBE::StructReject']]] +]; diff --git a/documents/html/search/all_8.js b/documents/html/search/all_8.js new file mode 100644 index 000000000..5416306a8 --- /dev/null +++ b/documents/html/search/all_8.js @@ -0,0 +1,5 @@ +var searchData= +[ + ['hash_0',['hash',['../struct_f_b_e_1_1_struct_field.html#aba260a25f93b5add8fc0465f9a23245b',1,'FBE::StructField']]], + ['hidden_1',['hidden',['../struct_f_b_e_1_1_attributes.html#a499bca8ed7f0f667d6b5a3963e9a63c0',1,'FBE::Attributes']]] +]; diff --git a/documents/html/search/all_9.js b/documents/html/search/all_9.js new file mode 100644 index 000000000..fdc664e18 --- /dev/null +++ b/documents/html/search/all_9.js @@ -0,0 +1,9 @@ +var searchData= +[ + ['id_0',['id',['../struct_f_b_e_1_1_struct_field.html#a99ea1f623606a77389d3a3659f92e211',1,'FBE::StructField::id'],['../struct_f_b_e_1_1_struct_type.html#a6b0840d6b4666520d53c30a72d41997d',1,'FBE::StructType::id']]], + ['import_1',['Import',['../struct_f_b_e_1_1_import.html',1,'FBE']]], + ['import_2',['import',['../struct_f_b_e_1_1_package.html#ab70df5e8c6136626b925e9c7c31881ed',1,'FBE::Package']]], + ['imports_3',['imports',['../struct_f_b_e_1_1_import.html#ad3d1377c703d954ed953c8379fc86199',1,'FBE::Import']]], + ['indent_4',['Indent',['../class_f_b_e_1_1_generator.html#af359602bb4cc0a2332ae2082a25616cf',1,'FBE::Generator']]], + ['initialize_5',['initialize',['../struct_f_b_e_1_1_package.html#a851ed0efc8a1fe5ce288e392d13c6ea3',1,'FBE::Package']]] +]; diff --git a/documents/html/search/all_a.js b/documents/html/search/all_a.js new file mode 100644 index 000000000..cb21f1814 --- /dev/null +++ b/documents/html/search/all_a.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['json_0',['JSON',['../class_f_b_e_1_1_generator_cpp.html#a8c0433f5aa6fa7dcdfecee6b979a15b1',1,'FBE::GeneratorCpp::JSON() const noexcept'],['../class_f_b_e_1_1_generator_cpp.html#a650a9479f7850561e8d6555a395ef1c7',1,'FBE::GeneratorCpp::JSON(bool json) noexcept'],['../class_f_b_e_1_1_generator_c_sharp.html#a5ef547c73730db4d753bf66d8a45ac6f',1,'FBE::GeneratorCSharp::JSON() const noexcept'],['../class_f_b_e_1_1_generator_c_sharp.html#ab406c4a9720174316c1387e90b2bdef5',1,'FBE::GeneratorCSharp::JSON(bool json) noexcept'],['../class_f_b_e_1_1_generator_go.html#aa212c137e60531e62c0ab6b777672bc9',1,'FBE::GeneratorGo::JSON() const noexcept'],['../class_f_b_e_1_1_generator_go.html#a81cefe8257c3b1e850e5aa1563b1b176',1,'FBE::GeneratorGo::JSON(bool json) noexcept'],['../class_f_b_e_1_1_generator_java.html#abc5ba964cadc533d30470a3dcf931e2c',1,'FBE::GeneratorJava::JSON() const noexcept'],['../class_f_b_e_1_1_generator_java.html#aa2759687b4b557b1678b335e1688d6c9',1,'FBE::GeneratorJava::JSON(bool json) noexcept'],['../class_f_b_e_1_1_generator_java_script.html#a6f3680ef225ef19821b17e1f7ab39918',1,'FBE::GeneratorJavaScript::JSON() const noexcept'],['../class_f_b_e_1_1_generator_java_script.html#a1308de27bbb9039e43e00cbe83afa77d',1,'FBE::GeneratorJavaScript::JSON(bool json) noexcept'],['../class_f_b_e_1_1_generator_kotlin.html#ae1e47fb1df0b9ea1e90bf0a83f7b0e8e',1,'FBE::GeneratorKotlin::JSON() const noexcept'],['../class_f_b_e_1_1_generator_kotlin.html#aae967b3270978ca9cfaeab3f04d73d1b',1,'FBE::GeneratorKotlin::JSON(bool json) noexcept'],['../class_f_b_e_1_1_generator_python.html#a0d16b0999af73dcbdf043decf62af561',1,'FBE::GeneratorPython::JSON() const noexcept'],['../class_f_b_e_1_1_generator_python.html#a979bdefe7a615d3aae14f251c2f1ed5b',1,'FBE::GeneratorPython::JSON(bool json) noexcept'],['../class_f_b_e_1_1_generator_ruby.html#aeb29f54ae136fdb0d2f4793d4b3f079c',1,'FBE::GeneratorRuby::JSON() const noexcept'],['../class_f_b_e_1_1_generator_ruby.html#aa39ee695b22960d5d8bef446de6eaa6e',1,'FBE::GeneratorRuby::JSON(bool json) noexcept'],['../class_f_b_e_1_1_generator_swift.html#aece3418f0aa1ca7628c1220dee568797',1,'FBE::GeneratorSwift::JSON() const noexcept'],['../class_f_b_e_1_1_generator_swift.html#aa0270c1aadad08190545471f3f2d1673',1,'FBE::GeneratorSwift::JSON(bool json) noexcept']]] +]; diff --git a/documents/html/search/all_b.js b/documents/html/search/all_b.js new file mode 100644 index 000000000..0cb6a73fe --- /dev/null +++ b/documents/html/search/all_b.js @@ -0,0 +1,5 @@ +var searchData= +[ + ['key_0',['key',['../struct_f_b_e_1_1_struct_field.html#a2933e5f6eb1ca9ee90052b28aed4c93c',1,'FBE::StructField']]], + ['keys_1',['keys',['../struct_f_b_e_1_1_struct_field.html#a6a5d97eb44d8a5107adaa33e125f824d',1,'FBE::StructField::keys'],['../struct_f_b_e_1_1_struct_type.html#afd2f60f01cf416735158b5e2ffca4cbc',1,'FBE::StructType::keys']]] +]; diff --git a/documents/html/search/all_c.js b/documents/html/search/all_c.js new file mode 100644 index 000000000..4a5390b22 --- /dev/null +++ b/documents/html/search/all_c.js @@ -0,0 +1,5 @@ +var searchData= +[ + ['list_0',['list',['../struct_f_b_e_1_1_struct_field.html#a66786365d04bb3dce302aa8b147088c8',1,'FBE::StructField']]], + ['logging_1',['Logging',['../class_f_b_e_1_1_generator_cpp.html#a6109a298c9f75f8247b8911eb4bd0afa',1,'FBE::GeneratorCpp::Logging() const noexcept'],['../class_f_b_e_1_1_generator_cpp.html#a9712ff5cdfdfb7a9602b477ed78e4221',1,'FBE::GeneratorCpp::Logging(bool logging) noexcept']]] +]; diff --git a/documents/html/search/all_d.js b/documents/html/search/all_d.js new file mode 100644 index 000000000..81ba45d50 --- /dev/null +++ b/documents/html/search/all_d.js @@ -0,0 +1,9 @@ +var searchData= +[ + ['main_0',['main',['../fbe_8l.html#a3c04138a5bfe5d72780bb7e82a18e627',1,'fbe.l']]], + ['major_1',['major',['../struct_f_b_e_1_1_version.html#a8ad5d9fa2a5ff6809602e473caa79aa0',1,'FBE::Version']]], + ['map_2',['map',['../struct_f_b_e_1_1_struct_field.html#a0f80f4c8d9204688577c23662cad66b6',1,'FBE::StructField']]], + ['merge_3',['Merge',['../struct_f_b_e_1_1_attributes.html#a8d969e71a5c481dd631f59667ead7be8',1,'FBE::Attributes']]], + ['message_4',['message',['../struct_f_b_e_1_1_struct_type.html#ad921b2d04a9d442f60c0032b40d7f6eb',1,'FBE::StructType']]], + ['minor_5',['minor',['../struct_f_b_e_1_1_version.html#a6bd77c8cadb526495fce7d00a9d4aeed',1,'FBE::Version']]] +]; diff --git a/documents/html/search/all_e.js b/documents/html/search/all_e.js new file mode 100644 index 000000000..1e4395916 --- /dev/null +++ b/documents/html/search/all_e.js @@ -0,0 +1,5 @@ +var searchData= +[ + ['n_0',['N',['../struct_f_b_e_1_1_struct_field.html#a3a42adeeb877ff9fb8aeba7269d38e2a',1,'FBE::StructField']]], + ['name_1',['name',['../struct_f_b_e_1_1_enum_value.html#a9bc4bafaa217f9dce5289ca8b4db8159',1,'FBE::EnumValue::name'],['../struct_f_b_e_1_1_enum_type.html#a115bc7fac55af2f4344881b0f85a1c4a',1,'FBE::EnumType::name'],['../struct_f_b_e_1_1_flags_value.html#a7433166ff6311b828e1aa03939c55e9e',1,'FBE::FlagsValue::name'],['../struct_f_b_e_1_1_flags_type.html#a91f33ec0d371971e45e89943b2155449',1,'FBE::FlagsType::name'],['../struct_f_b_e_1_1_struct_field.html#aab2400faafe597ca60c6a90c7f11b66c',1,'FBE::StructField::name'],['../struct_f_b_e_1_1_struct_type.html#ac438c967ec7448a77143156eaedd2acd',1,'FBE::StructType::name'],['../struct_f_b_e_1_1_package.html#aec996e375c657fb5d001b5c9a09a07b8',1,'FBE::Package::name']]] +]; diff --git a/documents/html/search/all_f.js b/documents/html/search/all_f.js new file mode 100644 index 000000000..d7fe6e31c --- /dev/null +++ b/documents/html/search/all_f.js @@ -0,0 +1,5 @@ +var searchData= +[ + ['offset_0',['offset',['../struct_f_b_e_1_1_package.html#a3e6b4bf776517b5f8f920fce2d1f1375',1,'FBE::Package']]], + ['optional_1',['optional',['../struct_f_b_e_1_1_struct_field.html#a97c0f2564202d9f2826c81f48414fc32',1,'FBE::StructField']]] +]; diff --git a/documents/html/search/classes_0.js b/documents/html/search/classes_0.js new file mode 100644 index 000000000..a67d070d9 --- /dev/null +++ b/documents/html/search/classes_0.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['attributes_0',['Attributes',['../struct_f_b_e_1_1_attributes.html',1,'FBE']]] +]; diff --git a/documents/html/search/classes_1.js b/documents/html/search/classes_1.js new file mode 100644 index 000000000..6ba45975e --- /dev/null +++ b/documents/html/search/classes_1.js @@ -0,0 +1,7 @@ +var searchData= +[ + ['enumbody_0',['EnumBody',['../struct_f_b_e_1_1_enum_body.html',1,'FBE']]], + ['enumconst_1',['EnumConst',['../struct_f_b_e_1_1_enum_const.html',1,'FBE']]], + ['enumtype_2',['EnumType',['../struct_f_b_e_1_1_enum_type.html',1,'FBE']]], + ['enumvalue_3',['EnumValue',['../struct_f_b_e_1_1_enum_value.html',1,'FBE']]] +]; diff --git a/documents/html/search/classes_2.js b/documents/html/search/classes_2.js new file mode 100644 index 000000000..4063987fb --- /dev/null +++ b/documents/html/search/classes_2.js @@ -0,0 +1,7 @@ +var searchData= +[ + ['flagsbody_0',['FlagsBody',['../struct_f_b_e_1_1_flags_body.html',1,'FBE']]], + ['flagsconst_1',['FlagsConst',['../struct_f_b_e_1_1_flags_const.html',1,'FBE']]], + ['flagstype_2',['FlagsType',['../struct_f_b_e_1_1_flags_type.html',1,'FBE']]], + ['flagsvalue_3',['FlagsValue',['../struct_f_b_e_1_1_flags_value.html',1,'FBE']]] +]; diff --git a/documents/html/search/classes_3.js b/documents/html/search/classes_3.js new file mode 100644 index 000000000..35fbd6ce5 --- /dev/null +++ b/documents/html/search/classes_3.js @@ -0,0 +1,13 @@ +var searchData= +[ + ['generator_0',['Generator',['../class_f_b_e_1_1_generator.html',1,'FBE']]], + ['generatorcpp_1',['GeneratorCpp',['../class_f_b_e_1_1_generator_cpp.html',1,'FBE']]], + ['generatorcsharp_2',['GeneratorCSharp',['../class_f_b_e_1_1_generator_c_sharp.html',1,'FBE']]], + ['generatorgo_3',['GeneratorGo',['../class_f_b_e_1_1_generator_go.html',1,'FBE']]], + ['generatorjava_4',['GeneratorJava',['../class_f_b_e_1_1_generator_java.html',1,'FBE']]], + ['generatorjavascript_5',['GeneratorJavaScript',['../class_f_b_e_1_1_generator_java_script.html',1,'FBE']]], + ['generatorkotlin_6',['GeneratorKotlin',['../class_f_b_e_1_1_generator_kotlin.html',1,'FBE']]], + ['generatorpython_7',['GeneratorPython',['../class_f_b_e_1_1_generator_python.html',1,'FBE']]], + ['generatorruby_8',['GeneratorRuby',['../class_f_b_e_1_1_generator_ruby.html',1,'FBE']]], + ['generatorswift_9',['GeneratorSwift',['../class_f_b_e_1_1_generator_swift.html',1,'FBE']]] +]; diff --git a/documents/html/search/classes_4.js b/documents/html/search/classes_4.js new file mode 100644 index 000000000..cbd22f818 --- /dev/null +++ b/documents/html/search/classes_4.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['import_0',['Import',['../struct_f_b_e_1_1_import.html',1,'FBE']]] +]; diff --git a/documents/html/search/classes_5.js b/documents/html/search/classes_5.js new file mode 100644 index 000000000..994c86666 --- /dev/null +++ b/documents/html/search/classes_5.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['package_0',['Package',['../struct_f_b_e_1_1_package.html',1,'FBE']]] +]; diff --git a/documents/html/search/classes_6.js b/documents/html/search/classes_6.js new file mode 100644 index 000000000..02ee4dfae --- /dev/null +++ b/documents/html/search/classes_6.js @@ -0,0 +1,12 @@ +var searchData= +[ + ['statement_0',['Statement',['../struct_f_b_e_1_1_statement.html',1,'FBE']]], + ['statements_1',['Statements',['../struct_f_b_e_1_1_statements.html',1,'FBE']]], + ['structbody_2',['StructBody',['../struct_f_b_e_1_1_struct_body.html',1,'FBE']]], + ['structfield_3',['StructField',['../struct_f_b_e_1_1_struct_field.html',1,'FBE']]], + ['structreject_4',['StructReject',['../struct_f_b_e_1_1_struct_reject.html',1,'FBE']]], + ['structrejects_5',['StructRejects',['../struct_f_b_e_1_1_struct_rejects.html',1,'FBE']]], + ['structrequest_6',['StructRequest',['../struct_f_b_e_1_1_struct_request.html',1,'FBE']]], + ['structresponse_7',['StructResponse',['../struct_f_b_e_1_1_struct_response.html',1,'FBE']]], + ['structtype_8',['StructType',['../struct_f_b_e_1_1_struct_type.html',1,'FBE']]] +]; diff --git a/documents/html/search/classes_7.js b/documents/html/search/classes_7.js new file mode 100644 index 000000000..c715fafe3 --- /dev/null +++ b/documents/html/search/classes_7.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['version_0',['Version',['../struct_f_b_e_1_1_version.html',1,'FBE']]] +]; diff --git a/documents/html/search/files_0.js b/documents/html/search/files_0.js new file mode 100644 index 000000000..84ecbed30 --- /dev/null +++ b/documents/html/search/files_0.js @@ -0,0 +1,6 @@ +var searchData= +[ + ['fbe_2ecpp_0',['fbe.cpp',['../fbe_8cpp.html',1,'']]], + ['fbe_2eh_1',['fbe.h',['../fbe_8h.html',1,'']]], + ['fbe_2el_2',['fbe.l',['../fbe_8l.html',1,'']]] +]; diff --git a/documents/html/search/files_1.js b/documents/html/search/files_1.js new file mode 100644 index 000000000..255a92784 --- /dev/null +++ b/documents/html/search/files_1.js @@ -0,0 +1,24 @@ +var searchData= +[ + ['generator_2ecpp_0',['generator.cpp',['../generator_8cpp.html',1,'']]], + ['generator_2eh_1',['generator.h',['../generator_8h.html',1,'']]], + ['generator_2einl_2',['generator.inl',['../generator_8inl.html',1,'']]], + ['generator_5fcpp_2ecpp_3',['generator_cpp.cpp',['../generator__cpp_8cpp.html',1,'']]], + ['generator_5fcpp_2eh_4',['generator_cpp.h',['../generator__cpp_8h.html',1,'']]], + ['generator_5fcsharp_2ecpp_5',['generator_csharp.cpp',['../generator__csharp_8cpp.html',1,'']]], + ['generator_5fcsharp_2eh_6',['generator_csharp.h',['../generator__csharp_8h.html',1,'']]], + ['generator_5fgo_2ecpp_7',['generator_go.cpp',['../generator__go_8cpp.html',1,'']]], + ['generator_5fgo_2eh_8',['generator_go.h',['../generator__go_8h.html',1,'']]], + ['generator_5fjava_2ecpp_9',['generator_java.cpp',['../generator__java_8cpp.html',1,'']]], + ['generator_5fjava_2eh_10',['generator_java.h',['../generator__java_8h.html',1,'']]], + ['generator_5fjavascript_2ecpp_11',['generator_javascript.cpp',['../generator__javascript_8cpp.html',1,'']]], + ['generator_5fjavascript_2eh_12',['generator_javascript.h',['../generator__javascript_8h.html',1,'']]], + ['generator_5fkotlin_2ecpp_13',['generator_kotlin.cpp',['../generator__kotlin_8cpp.html',1,'']]], + ['generator_5fkotlin_2eh_14',['generator_kotlin.h',['../generator__kotlin_8h.html',1,'']]], + ['generator_5fpython_2ecpp_15',['generator_python.cpp',['../generator__python_8cpp.html',1,'']]], + ['generator_5fpython_2eh_16',['generator_python.h',['../generator__python_8h.html',1,'']]], + ['generator_5fruby_2ecpp_17',['generator_ruby.cpp',['../generator__ruby_8cpp.html',1,'']]], + ['generator_5fruby_2eh_18',['generator_ruby.h',['../generator__ruby_8h.html',1,'']]], + ['generator_5fswift_2ecpp_19',['generator_swift.cpp',['../generator__swift_8cpp.html',1,'']]], + ['generator_5fswift_2eh_20',['generator_swift.h',['../generator__swift_8h.html',1,'']]] +]; diff --git a/documents/html/search/files_2.js b/documents/html/search/files_2.js new file mode 100644 index 000000000..7ac59491d --- /dev/null +++ b/documents/html/search/files_2.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['version_2eh_0',['version.h',['../version_8h.html',1,'']]] +]; diff --git a/documents/html/search/functions_0.js b/documents/html/search/functions_0.js new file mode 100644 index 000000000..8d0644e71 --- /dev/null +++ b/documents/html/search/functions_0.js @@ -0,0 +1,11 @@ +var searchData= +[ + ['addenum_0',['AddEnum',['../struct_f_b_e_1_1_statements.html#a6f741111b23b343cc3a81b3478f84471',1,'FBE::Statements']]], + ['addfield_1',['AddField',['../struct_f_b_e_1_1_struct_body.html#a4760c4da4fc917201f73e3fc12a6e572',1,'FBE::StructBody']]], + ['addflags_2',['AddFlags',['../struct_f_b_e_1_1_statements.html#a1cc1519825446a301deca7f9b8945135',1,'FBE::Statements']]], + ['addimport_3',['AddImport',['../struct_f_b_e_1_1_import.html#a77750b41d35db2e1e23f4670103dca0b',1,'FBE::Import']]], + ['addreject_4',['AddReject',['../struct_f_b_e_1_1_struct_rejects.html#a5172761722db77ec4f16aedd9629e4ca',1,'FBE::StructRejects']]], + ['addstatement_5',['AddStatement',['../struct_f_b_e_1_1_statements.html#aa267edbe1b0b702237fe2b7762c38e9e',1,'FBE::Statements']]], + ['addstruct_6',['AddStruct',['../struct_f_b_e_1_1_statements.html#a9c65826ba2117acd94cd70e09052e9d0',1,'FBE::Statements']]], + ['addvalue_7',['AddValue',['../struct_f_b_e_1_1_enum_body.html#a6e5dfd73a4a7cb509c44a085a391f087',1,'FBE::EnumBody::AddValue()'],['../struct_f_b_e_1_1_flags_body.html#a2fa3b0930898923930f1366eecbd5544',1,'FBE::FlagsBody::AddValue()']]] +]; diff --git a/documents/html/search/functions_1.js b/documents/html/search/functions_1.js new file mode 100644 index 000000000..b6e9aed41 --- /dev/null +++ b/documents/html/search/functions_1.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['endline_0',['EndLine',['../class_f_b_e_1_1_generator.html#a392f73b2ac0ece7b0f7ae0c035907cd5',1,'FBE::Generator']]] +]; diff --git a/documents/html/search/functions_2.js b/documents/html/search/functions_2.js new file mode 100644 index 000000000..3e61ff319 --- /dev/null +++ b/documents/html/search/functions_2.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['final_0',['Final',['../class_f_b_e_1_1_generator_cpp.html#af8c12f24e00cfff97ab1b7fbce070074',1,'FBE::GeneratorCpp::Final() const noexcept'],['../class_f_b_e_1_1_generator_cpp.html#ad66fe901546003265f3a478eae7d9da6',1,'FBE::GeneratorCpp::Final(bool final) noexcept'],['../class_f_b_e_1_1_generator_c_sharp.html#a3a34e76fc43b82179560153ac14203f0',1,'FBE::GeneratorCSharp::Final() const noexcept'],['../class_f_b_e_1_1_generator_c_sharp.html#a67cce180607164b764071919b4cc2065',1,'FBE::GeneratorCSharp::Final(bool final) noexcept'],['../class_f_b_e_1_1_generator_go.html#ade423e9f8d5975006ecffeca04b23c23',1,'FBE::GeneratorGo::Final() const noexcept'],['../class_f_b_e_1_1_generator_go.html#abb489fd928fdbdb7b2d01b4da78ce2d1',1,'FBE::GeneratorGo::Final(bool final) noexcept'],['../class_f_b_e_1_1_generator_java.html#a9da2535b60312cd9e4903ae72cd3e6f4',1,'FBE::GeneratorJava::Final() const noexcept'],['../class_f_b_e_1_1_generator_java.html#ac783ca318f6d6abcda9e4384a28b7617',1,'FBE::GeneratorJava::Final(bool final) noexcept'],['../class_f_b_e_1_1_generator_java_script.html#a6adc06827967cc5763497c1359d73d10',1,'FBE::GeneratorJavaScript::Final() const noexcept'],['../class_f_b_e_1_1_generator_java_script.html#af6d488425efc985ae9a94e9a3ff50ee3',1,'FBE::GeneratorJavaScript::Final(bool final) noexcept'],['../class_f_b_e_1_1_generator_kotlin.html#a3016d74d2977a054b113e7121d80d505',1,'FBE::GeneratorKotlin::Final() const noexcept'],['../class_f_b_e_1_1_generator_kotlin.html#a37de5823e865fb8d9ee7941b407002a8',1,'FBE::GeneratorKotlin::Final(bool final) noexcept'],['../class_f_b_e_1_1_generator_python.html#aac3be31a88dc5dd3296db64173f97ad7',1,'FBE::GeneratorPython::Final() const noexcept'],['../class_f_b_e_1_1_generator_python.html#aa876e67b6b8e36f92630025e64b10c82',1,'FBE::GeneratorPython::Final(bool final) noexcept'],['../class_f_b_e_1_1_generator_ruby.html#a6470926e0c131680d0eb3fcda8833df4',1,'FBE::GeneratorRuby::Final() const noexcept'],['../class_f_b_e_1_1_generator_ruby.html#a6123259acbebd0646a760b1be07149b0',1,'FBE::GeneratorRuby::Final(bool final) noexcept'],['../class_f_b_e_1_1_generator_swift.html#aa471a671b1061ec632c6a26e6b0b3faa',1,'FBE::GeneratorSwift::Final() const noexcept'],['../class_f_b_e_1_1_generator_swift.html#a5d7fb9e34a6b813162a90e957f2c4fbb',1,'FBE::GeneratorSwift::Final(bool final) noexcept']]] +]; diff --git a/documents/html/search/functions_3.js b/documents/html/search/functions_3.js new file mode 100644 index 000000000..0e1d1b117 --- /dev/null +++ b/documents/html/search/functions_3.js @@ -0,0 +1,5 @@ +var searchData= +[ + ['generate_0',['Generate',['../class_f_b_e_1_1_generator.html#a744839cb783ad52864d6cecbd04ff09a',1,'FBE::Generator::Generate()'],['../class_f_b_e_1_1_generator_cpp.html#a91a2efa87a5c45e40d5b03b1c7a76610',1,'FBE::GeneratorCpp::Generate()'],['../class_f_b_e_1_1_generator_c_sharp.html#ac72c8f4aad681644049a377e0c4fc4c3',1,'FBE::GeneratorCSharp::Generate()'],['../class_f_b_e_1_1_generator_go.html#a9b20af92e3c9ee3bdc3f768858de5bc9',1,'FBE::GeneratorGo::Generate()'],['../class_f_b_e_1_1_generator_java.html#af921daf5d4d4d0c327c99388b4d0e908',1,'FBE::GeneratorJava::Generate()'],['../class_f_b_e_1_1_generator_java_script.html#a3a5b3a0f66818adad49a53ed06fcd608',1,'FBE::GeneratorJavaScript::Generate()'],['../class_f_b_e_1_1_generator_kotlin.html#a62483d9cc0b16e35a22be745052017ad',1,'FBE::GeneratorKotlin::Generate()'],['../class_f_b_e_1_1_generator_python.html#ad683e5df22747b4e70016bf55136db45',1,'FBE::GeneratorPython::Generate()'],['../class_f_b_e_1_1_generator_ruby.html#afc18ab9b2996a61cce4006d4b5894599',1,'FBE::GeneratorRuby::Generate()'],['../class_f_b_e_1_1_generator_swift.html#a2dbcbe840b59de66e1a48e74377de938',1,'FBE::GeneratorSwift::Generate()']]], + ['generator_1',['Generator',['../class_f_b_e_1_1_generator.html#ae4868002857269b698804523c861f833',1,'FBE::Generator::Generator()'],['../class_f_b_e_1_1_generator_cpp.html#ae4868002857269b698804523c861f833',1,'FBE::GeneratorCpp::Generator()'],['../class_f_b_e_1_1_generator_c_sharp.html#ae4868002857269b698804523c861f833',1,'FBE::GeneratorCSharp::Generator()'],['../class_f_b_e_1_1_generator_go.html#ae4868002857269b698804523c861f833',1,'FBE::GeneratorGo::Generator()'],['../class_f_b_e_1_1_generator_java.html#ae4868002857269b698804523c861f833',1,'FBE::GeneratorJava::Generator()'],['../class_f_b_e_1_1_generator_java_script.html#ae4868002857269b698804523c861f833',1,'FBE::GeneratorJavaScript::Generator()'],['../class_f_b_e_1_1_generator_kotlin.html#ae4868002857269b698804523c861f833',1,'FBE::GeneratorKotlin::Generator()'],['../class_f_b_e_1_1_generator_python.html#ae4868002857269b698804523c861f833',1,'FBE::GeneratorPython::Generator()'],['../class_f_b_e_1_1_generator_ruby.html#ae4868002857269b698804523c861f833',1,'FBE::GeneratorRuby::Generator()'],['../class_f_b_e_1_1_generator_swift.html#ae4868002857269b698804523c861f833',1,'FBE::GeneratorSwift::Generator()']]] +]; diff --git a/documents/html/search/functions_4.js b/documents/html/search/functions_4.js new file mode 100644 index 000000000..2b1402cf8 --- /dev/null +++ b/documents/html/search/functions_4.js @@ -0,0 +1,5 @@ +var searchData= +[ + ['indent_0',['Indent',['../class_f_b_e_1_1_generator.html#af359602bb4cc0a2332ae2082a25616cf',1,'FBE::Generator']]], + ['initialize_1',['initialize',['../struct_f_b_e_1_1_package.html#a851ed0efc8a1fe5ce288e392d13c6ea3',1,'FBE::Package']]] +]; diff --git a/documents/html/search/functions_5.js b/documents/html/search/functions_5.js new file mode 100644 index 000000000..cb21f1814 --- /dev/null +++ b/documents/html/search/functions_5.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['json_0',['JSON',['../class_f_b_e_1_1_generator_cpp.html#a8c0433f5aa6fa7dcdfecee6b979a15b1',1,'FBE::GeneratorCpp::JSON() const noexcept'],['../class_f_b_e_1_1_generator_cpp.html#a650a9479f7850561e8d6555a395ef1c7',1,'FBE::GeneratorCpp::JSON(bool json) noexcept'],['../class_f_b_e_1_1_generator_c_sharp.html#a5ef547c73730db4d753bf66d8a45ac6f',1,'FBE::GeneratorCSharp::JSON() const noexcept'],['../class_f_b_e_1_1_generator_c_sharp.html#ab406c4a9720174316c1387e90b2bdef5',1,'FBE::GeneratorCSharp::JSON(bool json) noexcept'],['../class_f_b_e_1_1_generator_go.html#aa212c137e60531e62c0ab6b777672bc9',1,'FBE::GeneratorGo::JSON() const noexcept'],['../class_f_b_e_1_1_generator_go.html#a81cefe8257c3b1e850e5aa1563b1b176',1,'FBE::GeneratorGo::JSON(bool json) noexcept'],['../class_f_b_e_1_1_generator_java.html#abc5ba964cadc533d30470a3dcf931e2c',1,'FBE::GeneratorJava::JSON() const noexcept'],['../class_f_b_e_1_1_generator_java.html#aa2759687b4b557b1678b335e1688d6c9',1,'FBE::GeneratorJava::JSON(bool json) noexcept'],['../class_f_b_e_1_1_generator_java_script.html#a6f3680ef225ef19821b17e1f7ab39918',1,'FBE::GeneratorJavaScript::JSON() const noexcept'],['../class_f_b_e_1_1_generator_java_script.html#a1308de27bbb9039e43e00cbe83afa77d',1,'FBE::GeneratorJavaScript::JSON(bool json) noexcept'],['../class_f_b_e_1_1_generator_kotlin.html#ae1e47fb1df0b9ea1e90bf0a83f7b0e8e',1,'FBE::GeneratorKotlin::JSON() const noexcept'],['../class_f_b_e_1_1_generator_kotlin.html#aae967b3270978ca9cfaeab3f04d73d1b',1,'FBE::GeneratorKotlin::JSON(bool json) noexcept'],['../class_f_b_e_1_1_generator_python.html#a0d16b0999af73dcbdf043decf62af561',1,'FBE::GeneratorPython::JSON() const noexcept'],['../class_f_b_e_1_1_generator_python.html#a979bdefe7a615d3aae14f251c2f1ed5b',1,'FBE::GeneratorPython::JSON(bool json) noexcept'],['../class_f_b_e_1_1_generator_ruby.html#aeb29f54ae136fdb0d2f4793d4b3f079c',1,'FBE::GeneratorRuby::JSON() const noexcept'],['../class_f_b_e_1_1_generator_ruby.html#aa39ee695b22960d5d8bef446de6eaa6e',1,'FBE::GeneratorRuby::JSON(bool json) noexcept'],['../class_f_b_e_1_1_generator_swift.html#aece3418f0aa1ca7628c1220dee568797',1,'FBE::GeneratorSwift::JSON() const noexcept'],['../class_f_b_e_1_1_generator_swift.html#aa0270c1aadad08190545471f3f2d1673',1,'FBE::GeneratorSwift::JSON(bool json) noexcept']]] +]; diff --git a/documents/html/search/functions_6.js b/documents/html/search/functions_6.js new file mode 100644 index 000000000..ef63ec4be --- /dev/null +++ b/documents/html/search/functions_6.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['logging_0',['Logging',['../class_f_b_e_1_1_generator_cpp.html#a6109a298c9f75f8247b8911eb4bd0afa',1,'FBE::GeneratorCpp::Logging() const noexcept'],['../class_f_b_e_1_1_generator_cpp.html#a9712ff5cdfdfb7a9602b477ed78e4221',1,'FBE::GeneratorCpp::Logging(bool logging) noexcept']]] +]; diff --git a/documents/html/search/functions_7.js b/documents/html/search/functions_7.js new file mode 100644 index 000000000..89cb5f974 --- /dev/null +++ b/documents/html/search/functions_7.js @@ -0,0 +1,5 @@ +var searchData= +[ + ['main_0',['main',['../fbe_8l.html#a3c04138a5bfe5d72780bb7e82a18e627',1,'fbe.l']]], + ['merge_1',['Merge',['../struct_f_b_e_1_1_attributes.html#a8d969e71a5c481dd631f59667ead7be8',1,'FBE::Attributes']]] +]; diff --git a/documents/html/search/functions_8.js b/documents/html/search/functions_8.js new file mode 100644 index 000000000..514886905 --- /dev/null +++ b/documents/html/search/functions_8.js @@ -0,0 +1,5 @@ +var searchData= +[ + ['package_0',['Package',['../struct_f_b_e_1_1_package.html#aa2a5a2ba45503345e6c016508fceeeaa',1,'FBE::Package']]], + ['proto_1',['Proto',['../class_f_b_e_1_1_generator_cpp.html#a21ab15f74b25f32b709ba00e4aa7d622',1,'FBE::GeneratorCpp::Proto() const noexcept'],['../class_f_b_e_1_1_generator_cpp.html#a2e6583e9a7ba00edbb75aff09835efb7',1,'FBE::GeneratorCpp::Proto(bool proto) noexcept'],['../class_f_b_e_1_1_generator_c_sharp.html#ab9398c91d39f3c3318f832a26d30a647',1,'FBE::GeneratorCSharp::Proto() const noexcept'],['../class_f_b_e_1_1_generator_c_sharp.html#a704d83732c9fc16c57e182dafac31a91',1,'FBE::GeneratorCSharp::Proto(bool proto) noexcept'],['../class_f_b_e_1_1_generator_go.html#ade7ac2f7121d8964de6debcba416bfc6',1,'FBE::GeneratorGo::Proto() const noexcept'],['../class_f_b_e_1_1_generator_go.html#a309d080fd76fed3083172ff24b6446e2',1,'FBE::GeneratorGo::Proto(bool proto) noexcept'],['../class_f_b_e_1_1_generator_java.html#abd9b4d911301864ec9885c8b41f644e4',1,'FBE::GeneratorJava::Proto() const noexcept'],['../class_f_b_e_1_1_generator_java.html#a8fc27769454046d8f95d5b3b6f904145',1,'FBE::GeneratorJava::Proto(bool proto) noexcept'],['../class_f_b_e_1_1_generator_java_script.html#a18127dd7e5ea89376107f5666ef28a48',1,'FBE::GeneratorJavaScript::Proto() const noexcept'],['../class_f_b_e_1_1_generator_java_script.html#abb53e364ff969810b80b530ea2247fc2',1,'FBE::GeneratorJavaScript::Proto(bool proto) noexcept'],['../class_f_b_e_1_1_generator_kotlin.html#afb64fab23bdb33f8dfad9aee2efa5757',1,'FBE::GeneratorKotlin::Proto() const noexcept'],['../class_f_b_e_1_1_generator_kotlin.html#acfa2d83b57f112c6eddb3f00b0034048',1,'FBE::GeneratorKotlin::Proto(bool proto) noexcept'],['../class_f_b_e_1_1_generator_python.html#a08968f6d5774caaf11361efbafe96d5d',1,'FBE::GeneratorPython::Proto() const noexcept'],['../class_f_b_e_1_1_generator_python.html#a0839e975c597e26f8bfe165220c68ec2',1,'FBE::GeneratorPython::Proto(bool proto) noexcept'],['../class_f_b_e_1_1_generator_ruby.html#ac8760a0e0f5f10f84a0cdc98e47a4cee',1,'FBE::GeneratorRuby::Proto() const noexcept'],['../class_f_b_e_1_1_generator_ruby.html#acc41fb8d2f9fa5cc34e80a769e7d0e4b',1,'FBE::GeneratorRuby::Proto(bool proto) noexcept'],['../class_f_b_e_1_1_generator_swift.html#a43a38724df66b64dcc20a054ba0c1600',1,'FBE::GeneratorSwift::Proto() const noexcept'],['../class_f_b_e_1_1_generator_swift.html#a44a3146ef4c453b3322d0b19e7352602',1,'FBE::GeneratorSwift::Proto(bool proto) noexcept']]] +]; diff --git a/documents/html/search/functions_9.js b/documents/html/search/functions_9.js new file mode 100644 index 000000000..bd5517071 --- /dev/null +++ b/documents/html/search/functions_9.js @@ -0,0 +1,6 @@ +var searchData= +[ + ['setarraysize_0',['SetArraySize',['../struct_f_b_e_1_1_struct_field.html#a37590ebb3e5bb54b86245597100a9154',1,'FBE::StructField']]], + ['store_1',['Store',['../class_f_b_e_1_1_generator.html#a317020135e1df2b12cb4b28f80e02d8b',1,'FBE::Generator']]], + ['structtype_2',['StructType',['../struct_f_b_e_1_1_struct_type.html#abe2e58bd721ed0e1df3b4070445c38ec',1,'FBE::StructType']]] +]; diff --git a/documents/html/search/functions_a.js b/documents/html/search/functions_a.js new file mode 100644 index 000000000..39178a900 --- /dev/null +++ b/documents/html/search/functions_a.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['version_0',['Version',['../struct_f_b_e_1_1_version.html#ae2b1d0e5a6bfbc6718cd6f6d4f62ac4d',1,'FBE::Version::Version()=default'],['../struct_f_b_e_1_1_version.html#a97dcc94bdd0ec98f14ffb59ca1aef00b',1,'FBE::Version::Version(const std::string &v)'],['../class_f_b_e_1_1_generator_java.html#ab1d6ac3883e4bfa3e3c0f2526b751c6f',1,'FBE::GeneratorJava::Version() const noexcept'],['../class_f_b_e_1_1_generator_java.html#adc1faed80996bc9b68342c4cb7dc76bd',1,'FBE::GeneratorJava::Version(int v) noexcept'],['../class_f_b_e_1_1_generator_kotlin.html#a6dcf38a5a5b4d30ab1199775285e20c9',1,'FBE::GeneratorKotlin::Version() const noexcept'],['../class_f_b_e_1_1_generator_kotlin.html#a87b8027c47b4ade6d4211629219b1dad',1,'FBE::GeneratorKotlin::Version(int v) noexcept']]] +]; diff --git a/documents/html/search/functions_b.js b/documents/html/search/functions_b.js new file mode 100644 index 000000000..001ff321d --- /dev/null +++ b/documents/html/search/functions_b.js @@ -0,0 +1,9 @@ +var searchData= +[ + ['write_0',['Write',['../class_f_b_e_1_1_generator.html#ae55fd80c0b9d0ef6190a2887d84f2639',1,'FBE::Generator']]], + ['writebegin_1',['WriteBegin',['../class_f_b_e_1_1_generator.html#a037a8f7b1c2f6df995bea922ded418d8',1,'FBE::Generator']]], + ['writeend_2',['WriteEnd',['../class_f_b_e_1_1_generator.html#aed2498685efcd442908c0c8e62fa0c8a',1,'FBE::Generator']]], + ['writeindent_3',['WriteIndent',['../class_f_b_e_1_1_generator.html#af7140aa26c3e38d967d8c4ae31963a37',1,'FBE::Generator::WriteIndent()'],['../class_f_b_e_1_1_generator.html#aa906b53274f2768bef7cb4b9c3f5ff75',1,'FBE::Generator::WriteIndent(const std::string &str)']]], + ['writeline_4',['WriteLine',['../class_f_b_e_1_1_generator.html#a9cddebdbffb75de7aca0c6a54cad4729',1,'FBE::Generator::WriteLine()'],['../class_f_b_e_1_1_generator.html#a872432c6fddf6e35f19911bf6cf494f8',1,'FBE::Generator::WriteLine(const std::string &str)']]], + ['writelineindent_5',['WriteLineIndent',['../class_f_b_e_1_1_generator.html#ab3b100edfa26f498801b910bbd4b49bd',1,'FBE::Generator']]] +]; diff --git a/documents/html/search/functions_c.js b/documents/html/search/functions_c.js new file mode 100644 index 000000000..2af213c1e --- /dev/null +++ b/documents/html/search/functions_c.js @@ -0,0 +1,10 @@ +var searchData= +[ + ['yychar_0',['yychar',['../fbe_8l.html#a7b17763b4208d3203bdc74b82653d232',1,'fbe.l']]], + ['yycount_1',['yycount',['../fbe_8l.html#a055a5458b38b06fd55209e5df6406979',1,'fbe.l']]], + ['yyerror_2',['yyerror',['../fbe_8h.html#a5f1ec9d89d16809037ec688e8c2223c8',1,'yyerror(const char *msg): fbe.l'],['../fbe_8h.html#a69d2be71b2fb587c8a37ce51b7554993',1,'yyerror(const std::string &msg): fbe.l'],['../fbe_8l.html#a5f1ec9d89d16809037ec688e8c2223c8',1,'yyerror(const char *msg): fbe.l'],['../fbe_8l.html#a69d2be71b2fb587c8a37ce51b7554993',1,'yyerror(const std::string &msg): fbe.l']]], + ['yylex_3',['yylex',['../fbe_8l.html#a9a7bd1b3d14701eb97c03f3ef34deff1',1,'fbe.l']]], + ['yyparse_4',['yyparse',['../fbe_8l.html#acd8617a8f2ac0de8bc1cc032cf449e19',1,'fbe.l']]], + ['yystring_5',['yystring',['../fbe_8l.html#ac266565ec4b56884d76333eac74928c6',1,'fbe.l']]], + ['yytoken_6',['yytoken',['../fbe_8l.html#a593c3cc55c469994e350c7f394161eb2',1,'fbe.l']]] +]; diff --git a/documents/html/search/namespaces_0.js b/documents/html/search/namespaces_0.js new file mode 100644 index 000000000..9199af16c --- /dev/null +++ b/documents/html/search/namespaces_0.js @@ -0,0 +1,4 @@ +var searchData= +[ + ['fbe_0',['FBE',['../namespace_f_b_e.html',1,'']]] +]; diff --git a/documents/html/search/search.css b/documents/html/search/search.css new file mode 100644 index 000000000..043d32d98 --- /dev/null +++ b/documents/html/search/search.css @@ -0,0 +1,377 @@ +/*---------------- Search Box positioning */ + +#main-menu > li:last-child { + /* This
  • object is the parent of the search bar */ + display: flex; + justify-content: center; + align-items: center; + height: 43px; + margin-right: 0; +} + +/*---------------- Search box styling */ + +.SRPage * { + font-weight: normal; + line-height: normal; +} + +dark-mode-toggle { + margin-left: 5px; + display: flex; + float: right; +} + +#MSearchBox { + display: inline-block; + white-space : nowrap; + background: var(--search-background-color); + border-radius: 0.65em; + border: 1px solid var(--search-box-border-color); + z-index: 102; + margin-right: 4px; +} + +#MSearchBox .left { + display: inline-block; + vertical-align: middle; + height: 1.6em; +} + +#MSearchField { + display: inline-block; + vertical-align: top; + width: 7.5em; + height: 22px; + margin: 0 0 0 0.15em; + padding: 0; + line-height: 1em; + border:none; + color: var(--search-foreground-color); + outline: none; + font-family: var(--font-family-search); + -webkit-border-radius: 0px; + border-radius: 0px; + background: none; +} + +@media(hover: none) { + /* to avoid zooming on iOS */ + #MSearchField { + font-size: 16px; + } +} + +#MSearchBox .right { + display: inline-block; + vertical-align: middle; + width: 1.4em; + height: 1.6em; +} + +#MSearchClose { + display: none; + font-size: inherit; + background : none; + border: none; + margin: 0; + padding: 0; + outline: none; + +} + +#MSearchCloseImg { + margin: 6px 0 0 4px; +} + +.close-icon { + width: 11px; + height: 11px; + background-color: var(--search-close-icon-bg-color); + border-radius: 50%; + position: relative; + display: flex; + justify-content: center; + align-items: center; + box-sizing: content-box; +} + +.close-icon:before, +.close-icon:after { + content: ''; + position: absolute; + width: 7px; + height: 1px; + background-color: var(--search-close-icon-fg-color); +} + +.close-icon:before { + transform: rotate(45deg); +} + +.close-icon:after { + transform: rotate(-45deg); +} + + +.MSearchBoxActive #MSearchField { + color: var(--search-active-color); +} + +.search-icon { + width: 20px; + height: 20px; + display: inline-block; + position: relative; + margin-left: 3px; +} + +#MSearchSelectExt.search-icon { + width: 10px; +} + +#MSearchSelectExt + input { + margin-left: 5px; +} + +.search-icon::before, .search-icon::after { + content: ''; + position: absolute; + border: 1.5px solid var(--search-foreground-color); + box-sizing: content-box; +} + +.search-icon::before { + width: 6px; + height: 6px; + border-radius: 50%; + top: 7px; + left: 2px; + background: var(--search-background-color); +} + +.search-icon::after { + border: 1px solid var(--search-foreground-color); + width: 0px; + height: 3px; + border-radius: 2px; + top: 15px; + left: 8px; + transform: rotate(-45deg); + transform-origin: top left; +} + +.search-icon-dropdown { + content: ''; + width: 0; + height: 0; + border-left: 3px solid transparent; + border-right: 3px solid transparent; + border-top: 3px solid var(--search-foreground-color); + top: 8px; + left: 15px; + transform: translateX(-50%); + position: absolute; +} + + + + +/*---------------- Search filter selection */ + +#MSearchSelectWindow { + display: none; + position: absolute; + left: 0; top: 0; + border: 1px solid var(--search-filter-border-color); + background-color: var(--search-filter-background-color); + backdrop-filter: var(--search-filter-backdrop-filter); + -webkit-backdrop-filter: var(--search-filter-backdrop-filter); + z-index: 10001; + padding-top: 4px; + padding-bottom: 4px; + border-radius: 4px; +} + +.SelectItem { + font: 8pt var(--font-family-search); + padding-left: 2px; + padding-right: 12px; + border: 0px; +} + +span.SelectionMark { + margin-right: 4px; + font-family: var(--font-family-monospace); + outline-style: none; + text-decoration: none; +} + +a.SelectItem { + display: block; + outline-style: none; + color: var(--search-filter-foreground-color); + text-decoration: none; + padding-left: 6px; + padding-right: 12px; +} + +a.SelectItem:focus, +a.SelectItem:active { + color: var(--search-filter-foreground-color); + outline-style: none; + text-decoration: none; +} + +a.SelectItem:hover { + color: var(--search-filter-highlight-text-color); + background-color: var(--search-filter-highlight-bg-color); + outline-style: none; + text-decoration: none; + cursor: pointer; + display: block; +} + +/*---------------- Search results window */ + +iframe#MSearchResults { + /*width: 60ex;*/ + height: 15em; +} + +@keyframes slideInSearchResults { + from { + opacity: 0; + transform: translate(0, 15px); + } + + to { + opacity: 1; + transform: translate(0, 20px); + } +} + +#MSearchResultsWindow { + display: none; + position: absolute; + left: auto; + right: 4px; + top: 0; + border: 1px solid var(--search-results-border-color); + background-color: var(--search-results-background-color); + backdrop-filter: var(--search-results-backdrop-filter); + -webkit-backdrop-filter: var(--search-results-backdrop-filter); + z-index:10000; + width: 300px; + height: 400px; + overflow: auto; + border-radius: 8px; + transform: translate(0, 20px); + animation: ease-out 280ms slideInSearchResults; + box-shadow: 0 2px 8px 0 rgba(0,0,0,.075); +} + + +/* ----------------------------------- */ + + +#SRIndex { + clear:both; +} + +.SREntry { + font-size: 10pt; + padding-left: 1ex; +} + +.SRPage .SREntry { + font-size: 10pt; + padding: 2px 5px; +} + +div.SRPage { + margin: 5px 2px; +} + +.SRChildren { + padding-left: 3ex; padding-bottom: .5em +} + +.SRPage .SRChildren { + display: none; +} + +.SRSymbol { + font-weight: bold; + color: var(--search-results-foreground-color); + font-family: var(--font-family-search); + text-decoration: none; + outline: none; +} + +a.SRScope { + display: block; + color: var(--search-results-foreground-color); + font-family: var(--font-family-search); + font-size: 8pt; + text-decoration: none; + outline: none; +} + +a.SRSymbol:focus, a.SRSymbol:active, +a.SRScope:focus, a.SRScope:active { + text-decoration: underline; +} + +span.SRScope { + padding-left: 4px; + font-family: var(--font-family-search); +} + +.SRPage .SRStatus { + padding: 2px 5px; + font-size: 8pt; + font-style: italic; + font-family: var(--font-family-search); +} + +.SRResult { + display: none; +} + +div.searchresults { + margin-left: 10px; + margin-right: 10px; +} + +#searchBoxPos1 dark-mode-toggle { + margin-top: 4px; +} + +/*---------------- External search page results */ + +.pages b { + color: var(--nav-foreground-color); + padding: 5px 5px 3px 5px; + background-color: var(--nav-menu-active-bg); + border-radius: 4px; +} + +.pages { + line-height: 17px; + margin-left: 4px; + text-decoration: none; +} + +.hl { + font-weight: bold; +} + +#searchresults { + margin-bottom: 20px; +} + +.searchpages { + margin-top: 10px; +} + diff --git a/documents/html/search/search.js b/documents/html/search/search.js new file mode 100644 index 000000000..dc14410fb --- /dev/null +++ b/documents/html/search/search.js @@ -0,0 +1,708 @@ +/* + @licstart The following is the entire license notice for the JavaScript code in this file. + + The MIT License (MIT) + + Copyright (C) 1997-2020 by Dimitri van Heesch + + Permission is hereby granted, free of charge, to any person obtaining a copy of this software + and associated documentation files (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, publish, distribute, + sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or + substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING + BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + @licend The above is the entire license notice for the JavaScript code in this file + */ +const SEARCH_COOKIE_NAME = ''+'search_grp'; + +const searchResults = new SearchResults(); + +/* A class handling everything associated with the search panel. + + Parameters: + name - The name of the global variable that will be + storing this instance. Is needed to be able to set timeouts. + resultPath - path to use for external files +*/ +function SearchBox(name, resultsPath, extension) { + if (!name || !resultsPath) { alert("Missing parameters to SearchBox."); } + if (!extension || extension == "") { extension = ".html"; } + + function getXPos(item) { + let x = 0; + if (item.offsetWidth) { + while (item && item!=document.body) { + x += item.offsetLeft; + item = item.offsetParent; + } + } + return x; + } + + function getYPos(item) { + let y = 0; + if (item.offsetWidth) { + while (item && item!=document.body) { + y += item.offsetTop; + item = item.offsetParent; + } + } + return y; + } + + // ---------- Instance variables + this.name = name; + this.resultsPath = resultsPath; + this.keyTimeout = 0; + this.keyTimeoutLength = 500; + this.closeSelectionTimeout = 300; + this.lastSearchValue = ""; + this.lastResultsPage = ""; + this.hideTimeout = 0; + this.searchIndex = 0; + this.searchActive = false; + this.extension = extension; + + // ----------- DOM Elements + + this.DOMSearchField = () => document.getElementById("MSearchField"); + this.DOMSearchSelect = () => document.getElementById("MSearchSelect"); + this.DOMSearchSelectWindow = () => document.getElementById("MSearchSelectWindow"); + this.DOMPopupSearchResults = () => document.getElementById("MSearchResults"); + this.DOMPopupSearchResultsWindow = () => document.getElementById("MSearchResultsWindow"); + this.DOMSearchClose = () => document.getElementById("MSearchClose"); + this.DOMSearchBox = () => document.getElementById("MSearchBox"); + + // ------------ Event Handlers + + // Called when focus is added or removed from the search field. + this.OnSearchFieldFocus = function(isActive) { + this.Activate(isActive); + } + + this.OnSearchSelectShow = function() { + const searchSelectWindow = this.DOMSearchSelectWindow(); + const searchField = this.DOMSearchSelect(); + + const left = getXPos(searchField); + const top = getYPos(searchField) + searchField.offsetHeight; + + // show search selection popup + searchSelectWindow.style.display='block'; + searchSelectWindow.style.left = left + 'px'; + searchSelectWindow.style.top = top + 'px'; + + // stop selection hide timer + if (this.hideTimeout) { + clearTimeout(this.hideTimeout); + this.hideTimeout=0; + } + return false; // to avoid "image drag" default event + } + + this.OnSearchSelectHide = function() { + this.hideTimeout = setTimeout(this.CloseSelectionWindow.bind(this), + this.closeSelectionTimeout); + } + + // Called when the content of the search field is changed. + this.OnSearchFieldChange = function(evt) { + if (this.keyTimeout) { // kill running timer + clearTimeout(this.keyTimeout); + this.keyTimeout = 0; + } + + const e = evt ? evt : window.event; // for IE + if (e.keyCode==40 || e.keyCode==13) { + if (e.shiftKey==1) { + this.OnSearchSelectShow(); + const win=this.DOMSearchSelectWindow(); + for (let i=0;i do a search + this.Search(); + } + } + + this.OnSearchSelectKey = function(evt) { + const e = (evt) ? evt : window.event; // for IE + if (e.keyCode==40 && this.searchIndex0) { // Up + this.searchIndex--; + this.OnSelectItem(this.searchIndex); + } else if (e.keyCode==13 || e.keyCode==27) { + e.stopPropagation(); + this.OnSelectItem(this.searchIndex); + this.CloseSelectionWindow(); + this.DOMSearchField().focus(); + } + return false; + } + + // --------- Actions + + // Closes the results window. + this.CloseResultsWindow = function() { + this.DOMPopupSearchResultsWindow().style.display = 'none'; + this.DOMSearchClose().style.display = 'none'; + this.Activate(false); + } + + this.CloseSelectionWindow = function() { + this.DOMSearchSelectWindow().style.display = 'none'; + } + + // Performs a search. + this.Search = function() { + this.keyTimeout = 0; + + // strip leading whitespace + const searchValue = this.DOMSearchField().value.replace(/^ +/, ""); + + const code = searchValue.toLowerCase().charCodeAt(0); + let idxChar = searchValue.substr(0, 1).toLowerCase(); + if ( 0xD800 <= code && code <= 0xDBFF && searchValue > 1) { // surrogate pair + idxChar = searchValue.substr(0, 2); + } + + let jsFile; + let idx = indexSectionsWithContent[this.searchIndex].indexOf(idxChar); + if (idx!=-1) { + const hexCode=idx.toString(16); + jsFile = this.resultsPath + indexSectionNames[this.searchIndex] + '_' + hexCode + '.js'; + } + + const loadJS = function(url, impl, loc) { + const scriptTag = document.createElement('script'); + scriptTag.src = url; + scriptTag.onload = impl; + scriptTag.onreadystatechange = impl; + loc.appendChild(scriptTag); + } + + const domPopupSearchResultsWindow = this.DOMPopupSearchResultsWindow(); + const domSearchBox = this.DOMSearchBox(); + const domPopupSearchResults = this.DOMPopupSearchResults(); + const domSearchClose = this.DOMSearchClose(); + const resultsPath = this.resultsPath; + + const handleResults = function() { + document.getElementById("Loading").style.display="none"; + if (typeof searchData !== 'undefined') { + createResults(resultsPath); + document.getElementById("NoMatches").style.display="none"; + } + + if (idx!=-1) { + searchResults.Search(searchValue); + } else { // no file with search results => force empty search results + searchResults.Search('===='); + } + + if (domPopupSearchResultsWindow.style.display!='block') { + domSearchClose.style.display = 'inline-block'; + let left = getXPos(domSearchBox) + 150; + let top = getYPos(domSearchBox) + 20; + domPopupSearchResultsWindow.style.display = 'block'; + left -= domPopupSearchResults.offsetWidth; + const maxWidth = document.body.clientWidth; + const maxHeight = document.body.clientHeight; + let width = 300; + if (left<10) left=10; + if (width+left+8>maxWidth) width=maxWidth-left-8; + let height = 400; + if (height+top+8>maxHeight) height=maxHeight-top-8; + domPopupSearchResultsWindow.style.top = top + 'px'; + domPopupSearchResultsWindow.style.left = left + 'px'; + domPopupSearchResultsWindow.style.width = width + 'px'; + domPopupSearchResultsWindow.style.height = height + 'px'; + } + } + + if (jsFile) { + loadJS(jsFile, handleResults, this.DOMPopupSearchResultsWindow()); + } else { + handleResults(); + } + + this.lastSearchValue = searchValue; + } + + // -------- Activation Functions + + // Activates or deactivates the search panel, resetting things to + // their default values if necessary. + this.Activate = function(isActive) { + if (isActive || // open it + this.DOMPopupSearchResultsWindow().style.display == 'block' + ) { + this.DOMSearchBox().className = 'MSearchBoxActive'; + this.searchActive = true; + } else if (!isActive) { // directly remove the panel + this.DOMSearchBox().className = 'MSearchBoxInactive'; + this.searchActive = false; + this.lastSearchValue = '' + this.lastResultsPage = ''; + this.DOMSearchField().value = ''; + } + } +} + +// ----------------------------------------------------------------------- + +// The class that handles everything on the search results page. +function SearchResults() { + + function convertToId(search) { + let result = ''; + for (let i=0;i. + this.lastMatchCount = 0; + this.lastKey = 0; + this.repeatOn = false; + + // Toggles the visibility of the passed element ID. + this.FindChildElement = function(id) { + const parentElement = document.getElementById(id); + let element = parentElement.firstChild; + + while (element && element!=parentElement) { + if (element.nodeName.toLowerCase() == 'div' && element.className == 'SRChildren') { + return element; + } + + if (element.nodeName.toLowerCase() == 'div' && element.hasChildNodes()) { + element = element.firstChild; + } else if (element.nextSibling) { + element = element.nextSibling; + } else { + do { + element = element.parentNode; + } + while (element && element!=parentElement && !element.nextSibling); + + if (element && element!=parentElement) { + element = element.nextSibling; + } + } + } + } + + this.Toggle = function(id) { + const element = this.FindChildElement(id); + if (element) { + if (element.style.display == 'block') { + element.style.display = 'none'; + } else { + element.style.display = 'block'; + } + } + } + + // Searches for the passed string. If there is no parameter, + // it takes it from the URL query. + // + // Always returns true, since other documents may try to call it + // and that may or may not be possible. + this.Search = function(search) { + if (!search) { // get search word from URL + search = window.location.search; + search = search.substring(1); // Remove the leading '?' + search = unescape(search); + } + + search = search.replace(/^ +/, ""); // strip leading spaces + search = search.replace(/ +$/, ""); // strip trailing spaces + search = search.toLowerCase(); + search = convertToId(search); + + const resultRows = document.getElementsByTagName("div"); + let matches = 0; + + let i = 0; + while (i < resultRows.length) { + const row = resultRows.item(i); + if (row.className == "SRResult") { + let rowMatchName = row.id.toLowerCase(); + rowMatchName = rowMatchName.replace(/^sr\d*_/, ''); // strip 'sr123_' + + if (search.length<=rowMatchName.length && + rowMatchName.substr(0, search.length)==search) { + row.style.display = 'block'; + matches++; + } else { + row.style.display = 'none'; + } + } + i++; + } + document.getElementById("Searching").style.display='none'; + if (matches == 0) { // no results + document.getElementById("NoMatches").style.display='block'; + } else { // at least one result + document.getElementById("NoMatches").style.display='none'; + } + this.lastMatchCount = matches; + return true; + } + + // return the first item with index index or higher that is visible + this.NavNext = function(index) { + let focusItem; + for (;;) { + const focusName = 'Item'+index; + focusItem = document.getElementById(focusName); + if (focusItem && focusItem.parentNode.parentNode.style.display=='block') { + break; + } else if (!focusItem) { // last element + break; + } + focusItem=null; + index++; + } + return focusItem; + } + + this.NavPrev = function(index) { + let focusItem; + for (;;) { + const focusName = 'Item'+index; + focusItem = document.getElementById(focusName); + if (focusItem && focusItem.parentNode.parentNode.style.display=='block') { + break; + } else if (!focusItem) { // last element + break; + } + focusItem=null; + index--; + } + return focusItem; + } + + this.ProcessKeys = function(e) { + if (e.type == "keydown") { + this.repeatOn = false; + this.lastKey = e.keyCode; + } else if (e.type == "keypress") { + if (!this.repeatOn) { + if (this.lastKey) this.repeatOn = true; + return false; // ignore first keypress after keydown + } + } else if (e.type == "keyup") { + this.lastKey = 0; + this.repeatOn = false; + } + return this.lastKey!=0; + } + + this.Nav = function(evt,itemIndex) { + const e = (evt) ? evt : window.event; // for IE + if (e.keyCode==13) return true; + if (!this.ProcessKeys(e)) return false; + + if (this.lastKey==38) { // Up + const newIndex = itemIndex-1; + let focusItem = this.NavPrev(newIndex); + if (focusItem) { + let child = this.FindChildElement(focusItem.parentNode.parentNode.id); + if (child && child.style.display == 'block') { // children visible + let n=0; + let tmpElem; + for (;;) { // search for last child + tmpElem = document.getElementById('Item'+newIndex+'_c'+n); + if (tmpElem) { + focusItem = tmpElem; + } else { // found it! + break; + } + n++; + } + } + } + if (focusItem) { + focusItem.focus(); + } else { // return focus to search field + document.getElementById("MSearchField").focus(); + } + } else if (this.lastKey==40) { // Down + const newIndex = itemIndex+1; + let focusItem; + const item = document.getElementById('Item'+itemIndex); + const elem = this.FindChildElement(item.parentNode.parentNode.id); + if (elem && elem.style.display == 'block') { // children visible + focusItem = document.getElementById('Item'+itemIndex+'_c0'); + } + if (!focusItem) focusItem = this.NavNext(newIndex); + if (focusItem) focusItem.focus(); + } else if (this.lastKey==39) { // Right + const item = document.getElementById('Item'+itemIndex); + const elem = this.FindChildElement(item.parentNode.parentNode.id); + if (elem) elem.style.display = 'block'; + } else if (this.lastKey==37) { // Left + const item = document.getElementById('Item'+itemIndex); + const elem = this.FindChildElement(item.parentNode.parentNode.id); + if (elem) elem.style.display = 'none'; + } else if (this.lastKey==27) { // Escape + e.stopPropagation(); + searchBox.CloseResultsWindow(); + document.getElementById("MSearchField").focus(); + } else if (this.lastKey==13) { // Enter + return true; + } + return false; + } + + this.NavChild = function(evt,itemIndex,childIndex) { + const e = (evt) ? evt : window.event; // for IE + if (e.keyCode==13) return true; + if (!this.ProcessKeys(e)) return false; + + if (this.lastKey==38) { // Up + if (childIndex>0) { + const newIndex = childIndex-1; + document.getElementById('Item'+itemIndex+'_c'+newIndex).focus(); + } else { // already at first child, jump to parent + document.getElementById('Item'+itemIndex).focus(); + } + } else if (this.lastKey==40) { // Down + const newIndex = childIndex+1; + let elem = document.getElementById('Item'+itemIndex+'_c'+newIndex); + if (!elem) { // last child, jump to parent next parent + elem = this.NavNext(itemIndex+1); + } + if (elem) { + elem.focus(); + } + } else if (this.lastKey==27) { // Escape + e.stopPropagation(); + searchBox.CloseResultsWindow(); + document.getElementById("MSearchField").focus(); + } else if (this.lastKey==13) { // Enter + return true; + } + return false; + } +} + +function createResults(resultsPath) { + + function setKeyActions(elem,action) { + elem.setAttribute('onkeydown',action); + elem.setAttribute('onkeypress',action); + elem.setAttribute('onkeyup',action); + } + + function setClassAttr(elem,attr) { + elem.setAttribute('class',attr); + elem.setAttribute('className',attr); + } + + const decodeHtml = (html) => { + const txt = document.createElement("textarea"); + txt.innerHTML = html; + return txt.value; + }; + + const results = document.getElementById("SRResults"); + results.innerHTML = ''; + searchData.forEach((elem,index) => { + const id = elem[0]; + const srResult = document.createElement('div'); + srResult.setAttribute('id','SR_'+id); + setClassAttr(srResult,'SRResult'); + const srEntry = document.createElement('div'); + setClassAttr(srEntry,'SREntry'); + const srLink = document.createElement('a'); + srLink.setAttribute('id','Item'+index); + setKeyActions(srLink,'return searchResults.Nav(event,'+index+')'); + setClassAttr(srLink,'SRSymbol'); + srLink.innerHTML = decodeHtml(elem[1][0]); + srEntry.appendChild(srLink); + if (elem[1].length==2) { // single result + if (elem[1][1][0].startsWith('http://') || elem[1][1][0].startsWith('https://')) { // absolute path + srLink.setAttribute('href',elem[1][1][0]); + } else { // relative path + srLink.setAttribute('href',resultsPath+elem[1][1][0]); + } + srLink.setAttribute('onclick','searchBox.CloseResultsWindow()'); + if (elem[1][1][1]) { + srLink.setAttribute('target','_parent'); + } else { + srLink.setAttribute('target','_blank'); + } + const srScope = document.createElement('span'); + setClassAttr(srScope,'SRScope'); + srScope.innerHTML = decodeHtml(elem[1][1][2]); + srEntry.appendChild(srScope); + } else { // multiple results + srLink.setAttribute('href','javascript:searchResults.Toggle("SR_'+id+'")'); + const srChildren = document.createElement('div'); + setClassAttr(srChildren,'SRChildren'); + for (let c=0; c + + + + + + +FastBinaryEncoding: Member List + + + + + + + + + + + +
    +
    + + + + + + +
    +
    FastBinaryEncoding 1.15.0.0 +
    +
    Fast Binary Encoding
    +
    +
    + + + + + + + + + +
    +
    + + +
    +
    +
    +
    +
    +
    Loading...
    +
    Searching...
    +
    No Matches
    +
    +
    +
    +
    + + +
    +
    +
    +
    FBE::Attributes Member List
    +
    +
    + +

    This is the complete list of members for FBE::Attributes, including all inherited members.

    + + + + +
    deprecatedFBE::Attributes
    hiddenFBE::Attributes
    Merge(Attributes *attributes)FBE::Attributes
    + + +
    + + diff --git a/documents/html/struct_f_b_e_1_1_attributes.html b/documents/html/struct_f_b_e_1_1_attributes.html new file mode 100644 index 000000000..089f06a7b --- /dev/null +++ b/documents/html/struct_f_b_e_1_1_attributes.html @@ -0,0 +1,165 @@ + + + + + + + +FastBinaryEncoding: FBE::Attributes Struct Reference + + + + + + + + + + + +
    +
    + + + + + + +
    +
    FastBinaryEncoding 1.15.0.0 +
    +
    Fast Binary Encoding
    +
    +
    + + + + + + + + + +
    +
    + + +
    +
    +
    +
    +
    +
    Loading...
    +
    Searching...
    +
    No Matches
    +
    +
    +
    +
    + + +
    +
    +
    + +
    FBE::Attributes Struct Reference
    +
    +
    + +

    #include <fbe.h>

    + + + +

    +Public Member Functions

    void Merge (Attributes *attributes)
    + + + +

    +Public Attributes

    bool deprecated {false}
    bool hidden {false}
    +

    Detailed Description

    +
    +

    Definition at line 35 of file fbe.h.

    +

    Member Function Documentation

    + +

    ◆ Merge()

    + +
    +
    + + + + + + + +
    void FBE::Attributes::Merge (Attributes * attributes)
    +
    + +

    Definition at line 13 of file fbe.cpp.

    + +
    +
    +

    Member Data Documentation

    + +

    ◆ deprecated

    + +
    +
    + + + + +
    bool FBE::Attributes::deprecated {false}
    +
    + +

    Definition at line 37 of file fbe.h.

    + +
    +
    + +

    ◆ hidden

    + +
    +
    + + + + +
    bool FBE::Attributes::hidden {false}
    +
    + +

    Definition at line 38 of file fbe.h.

    + +
    +
    +
    The documentation for this struct was generated from the following files: +
    + + +
    + + diff --git a/documents/html/struct_f_b_e_1_1_enum_body-members.html b/documents/html/struct_f_b_e_1_1_enum_body-members.html new file mode 100644 index 000000000..7b4770d9a --- /dev/null +++ b/documents/html/struct_f_b_e_1_1_enum_body-members.html @@ -0,0 +1,94 @@ + + + + + + + +FastBinaryEncoding: Member List + + + + + + + + + + + +
    +
    + + + + + + +
    +
    FastBinaryEncoding 1.15.0.0 +
    +
    Fast Binary Encoding
    +
    +
    + + + + + + + + + +
    +
    + + +
    +
    +
    +
    +
    +
    Loading...
    +
    Searching...
    +
    No Matches
    +
    +
    +
    +
    + + +
    +
    +
    +
    FBE::EnumBody Member List
    +
    +
    + +

    This is the complete list of members for FBE::EnumBody, including all inherited members.

    + + + +
    AddValue(EnumValue *v)FBE::EnumBody
    valuesFBE::EnumBody
    + + +
    + + diff --git a/documents/html/struct_f_b_e_1_1_enum_body.html b/documents/html/struct_f_b_e_1_1_enum_body.html new file mode 100644 index 000000000..c938542f8 --- /dev/null +++ b/documents/html/struct_f_b_e_1_1_enum_body.html @@ -0,0 +1,148 @@ + + + + + + + +FastBinaryEncoding: FBE::EnumBody Struct Reference + + + + + + + + + + + +
    +
    + + + + + + +
    +
    FastBinaryEncoding 1.15.0.0 +
    +
    Fast Binary Encoding
    +
    +
    + + + + + + + + + +
    +
    + + +
    +
    +
    +
    +
    +
    Loading...
    +
    Searching...
    +
    No Matches
    +
    +
    +
    +
    + + +
    +
    +
    + +
    FBE::EnumBody Struct Reference
    +
    +
    + +

    #include <fbe.h>

    + + + +

    +Public Member Functions

    void AddValue (EnumValue *v)
    + + +

    +Public Attributes

    std::vector< std::shared_ptr< EnumValue > > values
    +

    Detailed Description

    +
    +

    Definition at line 56 of file fbe.h.

    +

    Member Function Documentation

    + +

    ◆ AddValue()

    + +
    +
    + + + + + + + +
    void FBE::EnumBody::AddValue (EnumValue * v)
    +
    + +

    Definition at line 19 of file fbe.cpp.

    + +
    +
    +

    Member Data Documentation

    + +

    ◆ values

    + +
    +
    + + + + +
    std::vector<std::shared_ptr<EnumValue> > FBE::EnumBody::values
    +
    + +

    Definition at line 58 of file fbe.h.

    + +
    +
    +
    The documentation for this struct was generated from the following files: +
    + + +
    + + diff --git a/documents/html/struct_f_b_e_1_1_enum_const-members.html b/documents/html/struct_f_b_e_1_1_enum_const-members.html new file mode 100644 index 000000000..bb725a3d8 --- /dev/null +++ b/documents/html/struct_f_b_e_1_1_enum_const-members.html @@ -0,0 +1,94 @@ + + + + + + + +FastBinaryEncoding: Member List + + + + + + + + + + + +
    +
    + + + + + + +
    +
    FastBinaryEncoding 1.15.0.0 +
    +
    Fast Binary Encoding
    +
    +
    + + + + + + + + + +
    +
    + + +
    +
    +
    +
    +
    +
    Loading...
    +
    Searching...
    +
    No Matches
    +
    +
    +
    +
    + + +
    +
    +
    +
    FBE::EnumConst Member List
    +
    +
    + +

    This is the complete list of members for FBE::EnumConst, including all inherited members.

    + + + +
    constantFBE::EnumConst
    referenceFBE::EnumConst
    + + +
    + + diff --git a/documents/html/struct_f_b_e_1_1_enum_const.html b/documents/html/struct_f_b_e_1_1_enum_const.html new file mode 100644 index 000000000..eee60f32e --- /dev/null +++ b/documents/html/struct_f_b_e_1_1_enum_const.html @@ -0,0 +1,139 @@ + + + + + + + +FastBinaryEncoding: FBE::EnumConst Struct Reference + + + + + + + + + + + +
    +
    + + + + + + +
    +
    FastBinaryEncoding 1.15.0.0 +
    +
    Fast Binary Encoding
    +
    +
    + + + + + + + + + +
    +
    + + +
    +
    +
    +
    +
    +
    Loading...
    +
    Searching...
    +
    No Matches
    +
    +
    +
    +
    + + +
    +
    +
    + +
    FBE::EnumConst Struct Reference
    +
    +
    + +

    #include <fbe.h>

    + + + + +

    +Public Attributes

    std::shared_ptr< std::string > constant
    std::shared_ptr< std::string > reference
    +

    Detailed Description

    +
    +

    Definition at line 43 of file fbe.h.

    +

    Member Data Documentation

    + +

    ◆ constant

    + +
    +
    + + + + +
    std::shared_ptr<std::string> FBE::EnumConst::constant
    +
    + +

    Definition at line 45 of file fbe.h.

    + +
    +
    + +

    ◆ reference

    + +
    +
    + + + + +
    std::shared_ptr<std::string> FBE::EnumConst::reference
    +
    + +

    Definition at line 46 of file fbe.h.

    + +
    +
    +
    The documentation for this struct was generated from the following file: +
    + + +
    + + diff --git a/documents/html/struct_f_b_e_1_1_enum_type-members.html b/documents/html/struct_f_b_e_1_1_enum_type-members.html new file mode 100644 index 000000000..fc98f2424 --- /dev/null +++ b/documents/html/struct_f_b_e_1_1_enum_type-members.html @@ -0,0 +1,96 @@ + + + + + + + +FastBinaryEncoding: Member List + + + + + + + + + + + +
    +
    + + + + + + +
    +
    FastBinaryEncoding 1.15.0.0 +
    +
    Fast Binary Encoding
    +
    +
    + + + + + + + + + +
    +
    + + +
    +
    +
    +
    +
    +
    Loading...
    +
    Searching...
    +
    No Matches
    +
    +
    +
    +
    + + +
    +
    +
    +
    FBE::EnumType Member List
    +
    +
    + +

    This is the complete list of members for FBE::EnumType, including all inherited members.

    + + + + + +
    attributesFBE::EnumType
    baseFBE::EnumType
    bodyFBE::EnumType
    nameFBE::EnumType
    + + +
    + + diff --git a/documents/html/struct_f_b_e_1_1_enum_type.html b/documents/html/struct_f_b_e_1_1_enum_type.html new file mode 100644 index 000000000..5a88b7bc7 --- /dev/null +++ b/documents/html/struct_f_b_e_1_1_enum_type.html @@ -0,0 +1,173 @@ + + + + + + + +FastBinaryEncoding: FBE::EnumType Struct Reference + + + + + + + + + + + +
    +
    + + + + + + +
    +
    FastBinaryEncoding 1.15.0.0 +
    +
    Fast Binary Encoding
    +
    +
    + + + + + + + + + +
    +
    + + +
    +
    +
    +
    +
    +
    Loading...
    +
    Searching...
    +
    No Matches
    +
    +
    +
    +
    + + +
    +
    +
    + +
    FBE::EnumType Struct Reference
    +
    +
    + +

    #include <fbe.h>

    + + + + + + +

    +Public Attributes

    std::shared_ptr< Attributes > attributes
    std::shared_ptr< std::string > name
    std::shared_ptr< std::string > base
    std::shared_ptr< EnumBody > body
    +

    Detailed Description

    +
    +

    Definition at line 63 of file fbe.h.

    +

    Member Data Documentation

    + +

    ◆ attributes

    + +
    +
    + + + + +
    std::shared_ptr<Attributes> FBE::EnumType::attributes
    +
    + +

    Definition at line 65 of file fbe.h.

    + +
    +
    + +

    ◆ base

    + +
    +
    + + + + +
    std::shared_ptr<std::string> FBE::EnumType::base
    +
    + +

    Definition at line 67 of file fbe.h.

    + +
    +
    + +

    ◆ body

    + +
    +
    + + + + +
    std::shared_ptr<EnumBody> FBE::EnumType::body
    +
    + +

    Definition at line 68 of file fbe.h.

    + +
    +
    + +

    ◆ name

    + +
    +
    + + + + +
    std::shared_ptr<std::string> FBE::EnumType::name
    +
    + +

    Definition at line 66 of file fbe.h.

    + +
    +
    +
    The documentation for this struct was generated from the following file: +
    + + +
    + + diff --git a/documents/html/struct_f_b_e_1_1_enum_value-members.html b/documents/html/struct_f_b_e_1_1_enum_value-members.html new file mode 100644 index 000000000..9f434fb44 --- /dev/null +++ b/documents/html/struct_f_b_e_1_1_enum_value-members.html @@ -0,0 +1,95 @@ + + + + + + + +FastBinaryEncoding: Member List + + + + + + + + + + + +
    +
    + + + + + + +
    +
    FastBinaryEncoding 1.15.0.0 +
    +
    Fast Binary Encoding
    +
    +
    + + + + + + + + + +
    +
    + + +
    +
    +
    +
    +
    +
    Loading...
    +
    Searching...
    +
    No Matches
    +
    +
    +
    +
    + + +
    +
    +
    +
    FBE::EnumValue Member List
    +
    +
    + +

    This is the complete list of members for FBE::EnumValue, including all inherited members.

    + + + + +
    attributesFBE::EnumValue
    nameFBE::EnumValue
    valueFBE::EnumValue
    + + +
    + + diff --git a/documents/html/struct_f_b_e_1_1_enum_value.html b/documents/html/struct_f_b_e_1_1_enum_value.html new file mode 100644 index 000000000..aa6307895 --- /dev/null +++ b/documents/html/struct_f_b_e_1_1_enum_value.html @@ -0,0 +1,156 @@ + + + + + + + +FastBinaryEncoding: FBE::EnumValue Struct Reference + + + + + + + + + + + +
    +
    + + + + + + +
    +
    FastBinaryEncoding 1.15.0.0 +
    +
    Fast Binary Encoding
    +
    +
    + + + + + + + + + +
    +
    + + +
    +
    +
    +
    +
    +
    Loading...
    +
    Searching...
    +
    No Matches
    +
    +
    +
    +
    + + +
    +
    +
    + +
    FBE::EnumValue Struct Reference
    +
    +
    + +

    #include <fbe.h>

    + + + + + +

    +Public Attributes

    std::shared_ptr< Attributes > attributes
    std::shared_ptr< std::string > name
    std::shared_ptr< EnumConst > value
    +

    Detailed Description

    +
    +

    Definition at line 49 of file fbe.h.

    +

    Member Data Documentation

    + +

    ◆ attributes

    + +
    +
    + + + + +
    std::shared_ptr<Attributes> FBE::EnumValue::attributes
    +
    + +

    Definition at line 51 of file fbe.h.

    + +
    +
    + +

    ◆ name

    + +
    +
    + + + + +
    std::shared_ptr<std::string> FBE::EnumValue::name
    +
    + +

    Definition at line 52 of file fbe.h.

    + +
    +
    + +

    ◆ value

    + +
    +
    + + + + +
    std::shared_ptr<EnumConst> FBE::EnumValue::value
    +
    + +

    Definition at line 53 of file fbe.h.

    + +
    +
    +
    The documentation for this struct was generated from the following file: +
    + + +
    + + diff --git a/documents/html/struct_f_b_e_1_1_flags_body-members.html b/documents/html/struct_f_b_e_1_1_flags_body-members.html new file mode 100644 index 000000000..fb98b3b33 --- /dev/null +++ b/documents/html/struct_f_b_e_1_1_flags_body-members.html @@ -0,0 +1,94 @@ + + + + + + + +FastBinaryEncoding: Member List + + + + + + + + + + + +
    +
    + + + + + + +
    +
    FastBinaryEncoding 1.15.0.0 +
    +
    Fast Binary Encoding
    +
    +
    + + + + + + + + + +
    +
    + + +
    +
    +
    +
    +
    +
    Loading...
    +
    Searching...
    +
    No Matches
    +
    +
    +
    +
    + + +
    +
    +
    +
    FBE::FlagsBody Member List
    +
    +
    + +

    This is the complete list of members for FBE::FlagsBody, including all inherited members.

    + + + +
    AddValue(FlagsValue *v)FBE::FlagsBody
    valuesFBE::FlagsBody
    + + +
    + + diff --git a/documents/html/struct_f_b_e_1_1_flags_body.html b/documents/html/struct_f_b_e_1_1_flags_body.html new file mode 100644 index 000000000..e6567cf2e --- /dev/null +++ b/documents/html/struct_f_b_e_1_1_flags_body.html @@ -0,0 +1,148 @@ + + + + + + + +FastBinaryEncoding: FBE::FlagsBody Struct Reference + + + + + + + + + + + +
    +
    + + + + + + +
    +
    FastBinaryEncoding 1.15.0.0 +
    +
    Fast Binary Encoding
    +
    +
    + + + + + + + + + +
    +
    + + +
    +
    +
    +
    +
    +
    Loading...
    +
    Searching...
    +
    No Matches
    +
    +
    +
    +
    + + +
    +
    +
    + +
    FBE::FlagsBody Struct Reference
    +
    +
    + +

    #include <fbe.h>

    + + + +

    +Public Member Functions

    void AddValue (FlagsValue *v)
    + + +

    +Public Attributes

    std::vector< std::shared_ptr< FlagsValue > > values
    +

    Detailed Description

    +
    +

    Definition at line 84 of file fbe.h.

    +

    Member Function Documentation

    + +

    ◆ AddValue()

    + +
    +
    + + + + + + + +
    void FBE::FlagsBody::AddValue (FlagsValue * v)
    +
    + +

    Definition at line 34 of file fbe.cpp.

    + +
    +
    +

    Member Data Documentation

    + +

    ◆ values

    + +
    +
    + + + + +
    std::vector<std::shared_ptr<FlagsValue> > FBE::FlagsBody::values
    +
    + +

    Definition at line 86 of file fbe.h.

    + +
    +
    +
    The documentation for this struct was generated from the following files: +
    + + +
    + + diff --git a/documents/html/struct_f_b_e_1_1_flags_const-members.html b/documents/html/struct_f_b_e_1_1_flags_const-members.html new file mode 100644 index 000000000..04e589453 --- /dev/null +++ b/documents/html/struct_f_b_e_1_1_flags_const-members.html @@ -0,0 +1,94 @@ + + + + + + + +FastBinaryEncoding: Member List + + + + + + + + + + + +
    +
    + + + + + + +
    +
    FastBinaryEncoding 1.15.0.0 +
    +
    Fast Binary Encoding
    +
    +
    + + + + + + + + + +
    +
    + + +
    +
    +
    +
    +
    +
    Loading...
    +
    Searching...
    +
    No Matches
    +
    +
    +
    +
    + + +
    +
    +
    +
    FBE::FlagsConst Member List
    +
    +
    + +

    This is the complete list of members for FBE::FlagsConst, including all inherited members.

    + + + +
    constantFBE::FlagsConst
    referenceFBE::FlagsConst
    + + +
    + + diff --git a/documents/html/struct_f_b_e_1_1_flags_const.html b/documents/html/struct_f_b_e_1_1_flags_const.html new file mode 100644 index 000000000..f60316c19 --- /dev/null +++ b/documents/html/struct_f_b_e_1_1_flags_const.html @@ -0,0 +1,139 @@ + + + + + + + +FastBinaryEncoding: FBE::FlagsConst Struct Reference + + + + + + + + + + + +
    +
    + + + + + + +
    +
    FastBinaryEncoding 1.15.0.0 +
    +
    Fast Binary Encoding
    +
    +
    + + + + + + + + + +
    +
    + + +
    +
    +
    +
    +
    +
    Loading...
    +
    Searching...
    +
    No Matches
    +
    +
    +
    +
    + + +
    +
    +
    + +
    FBE::FlagsConst Struct Reference
    +
    +
    + +

    #include <fbe.h>

    + + + + +

    +Public Attributes

    std::shared_ptr< std::string > constant
    std::shared_ptr< std::string > reference
    +

    Detailed Description

    +
    +

    Definition at line 71 of file fbe.h.

    +

    Member Data Documentation

    + +

    ◆ constant

    + +
    +
    + + + + +
    std::shared_ptr<std::string> FBE::FlagsConst::constant
    +
    + +

    Definition at line 73 of file fbe.h.

    + +
    +
    + +

    ◆ reference

    + +
    +
    + + + + +
    std::shared_ptr<std::string> FBE::FlagsConst::reference
    +
    + +

    Definition at line 74 of file fbe.h.

    + +
    +
    +
    The documentation for this struct was generated from the following file: +
    + + +
    + + diff --git a/documents/html/struct_f_b_e_1_1_flags_type-members.html b/documents/html/struct_f_b_e_1_1_flags_type-members.html new file mode 100644 index 000000000..91c57df3d --- /dev/null +++ b/documents/html/struct_f_b_e_1_1_flags_type-members.html @@ -0,0 +1,96 @@ + + + + + + + +FastBinaryEncoding: Member List + + + + + + + + + + + +
    +
    + + + + + + +
    +
    FastBinaryEncoding 1.15.0.0 +
    +
    Fast Binary Encoding
    +
    +
    + + + + + + + + + +
    +
    + + +
    +
    +
    +
    +
    +
    Loading...
    +
    Searching...
    +
    No Matches
    +
    +
    +
    +
    + + +
    +
    +
    +
    FBE::FlagsType Member List
    +
    +
    + +

    This is the complete list of members for FBE::FlagsType, including all inherited members.

    + + + + + +
    attributesFBE::FlagsType
    baseFBE::FlagsType
    bodyFBE::FlagsType
    nameFBE::FlagsType
    + + +
    + + diff --git a/documents/html/struct_f_b_e_1_1_flags_type.html b/documents/html/struct_f_b_e_1_1_flags_type.html new file mode 100644 index 000000000..93b39b8ae --- /dev/null +++ b/documents/html/struct_f_b_e_1_1_flags_type.html @@ -0,0 +1,173 @@ + + + + + + + +FastBinaryEncoding: FBE::FlagsType Struct Reference + + + + + + + + + + + +
    +
    + + + + + + +
    +
    FastBinaryEncoding 1.15.0.0 +
    +
    Fast Binary Encoding
    +
    +
    + + + + + + + + + +
    +
    + + +
    +
    +
    +
    +
    +
    Loading...
    +
    Searching...
    +
    No Matches
    +
    +
    +
    +
    + + +
    +
    +
    + +
    FBE::FlagsType Struct Reference
    +
    +
    + +

    #include <fbe.h>

    + + + + + + +

    +Public Attributes

    std::shared_ptr< Attributes > attributes
    std::shared_ptr< std::string > name
    std::shared_ptr< std::string > base
    std::shared_ptr< FlagsBody > body
    +

    Detailed Description

    +
    +

    Definition at line 91 of file fbe.h.

    +

    Member Data Documentation

    + +

    ◆ attributes

    + +
    +
    + + + + +
    std::shared_ptr<Attributes> FBE::FlagsType::attributes
    +
    + +

    Definition at line 93 of file fbe.h.

    + +
    +
    + +

    ◆ base

    + +
    +
    + + + + +
    std::shared_ptr<std::string> FBE::FlagsType::base
    +
    + +

    Definition at line 95 of file fbe.h.

    + +
    +
    + +

    ◆ body

    + +
    +
    + + + + +
    std::shared_ptr<FlagsBody> FBE::FlagsType::body
    +
    + +

    Definition at line 96 of file fbe.h.

    + +
    +
    + +

    ◆ name

    + +
    +
    + + + + +
    std::shared_ptr<std::string> FBE::FlagsType::name
    +
    + +

    Definition at line 94 of file fbe.h.

    + +
    +
    +
    The documentation for this struct was generated from the following file: +
    + + +
    + + diff --git a/documents/html/struct_f_b_e_1_1_flags_value-members.html b/documents/html/struct_f_b_e_1_1_flags_value-members.html new file mode 100644 index 000000000..86c012246 --- /dev/null +++ b/documents/html/struct_f_b_e_1_1_flags_value-members.html @@ -0,0 +1,95 @@ + + + + + + + +FastBinaryEncoding: Member List + + + + + + + + + + + +
    +
    + + + + + + +
    +
    FastBinaryEncoding 1.15.0.0 +
    +
    Fast Binary Encoding
    +
    +
    + + + + + + + + + +
    +
    + + +
    +
    +
    +
    +
    +
    Loading...
    +
    Searching...
    +
    No Matches
    +
    +
    +
    +
    + + +
    +
    +
    +
    FBE::FlagsValue Member List
    +
    +
    + +

    This is the complete list of members for FBE::FlagsValue, including all inherited members.

    + + + + +
    attributesFBE::FlagsValue
    nameFBE::FlagsValue
    valueFBE::FlagsValue
    + + +
    + + diff --git a/documents/html/struct_f_b_e_1_1_flags_value.html b/documents/html/struct_f_b_e_1_1_flags_value.html new file mode 100644 index 000000000..bc7c3d146 --- /dev/null +++ b/documents/html/struct_f_b_e_1_1_flags_value.html @@ -0,0 +1,156 @@ + + + + + + + +FastBinaryEncoding: FBE::FlagsValue Struct Reference + + + + + + + + + + + +
    +
    + + + + + + +
    +
    FastBinaryEncoding 1.15.0.0 +
    +
    Fast Binary Encoding
    +
    +
    + + + + + + + + + +
    +
    + + +
    +
    +
    +
    +
    +
    Loading...
    +
    Searching...
    +
    No Matches
    +
    +
    +
    +
    + + +
    +
    +
    + +
    FBE::FlagsValue Struct Reference
    +
    +
    + +

    #include <fbe.h>

    + + + + + +

    +Public Attributes

    std::shared_ptr< Attributes > attributes
    std::shared_ptr< std::string > name
    std::shared_ptr< FlagsConst > value
    +

    Detailed Description

    +
    +

    Definition at line 77 of file fbe.h.

    +

    Member Data Documentation

    + +

    ◆ attributes

    + +
    +
    + + + + +
    std::shared_ptr<Attributes> FBE::FlagsValue::attributes
    +
    + +

    Definition at line 79 of file fbe.h.

    + +
    +
    + +

    ◆ name

    + +
    +
    + + + + +
    std::shared_ptr<std::string> FBE::FlagsValue::name
    +
    + +

    Definition at line 80 of file fbe.h.

    + +
    +
    + +

    ◆ value

    + +
    +
    + + + + +
    std::shared_ptr<FlagsConst> FBE::FlagsValue::value
    +
    + +

    Definition at line 81 of file fbe.h.

    + +
    +
    +
    The documentation for this struct was generated from the following file: +
    + + +
    + + diff --git a/documents/html/struct_f_b_e_1_1_import-members.html b/documents/html/struct_f_b_e_1_1_import-members.html new file mode 100644 index 000000000..745647832 --- /dev/null +++ b/documents/html/struct_f_b_e_1_1_import-members.html @@ -0,0 +1,94 @@ + + + + + + + +FastBinaryEncoding: Member List + + + + + + + + + + + +
    +
    + + + + + + +
    +
    FastBinaryEncoding 1.15.0.0 +
    +
    Fast Binary Encoding
    +
    +
    + + + + + + + + + +
    +
    + + +
    +
    +
    +
    +
    +
    Loading...
    +
    Searching...
    +
    No Matches
    +
    +
    +
    +
    + + +
    +
    +
    +
    FBE::Import Member List
    +
    +
    + +

    This is the complete list of members for FBE::Import, including all inherited members.

    + + + +
    AddImport(std::string *i)FBE::Import
    importsFBE::Import
    + + +
    + + diff --git a/documents/html/struct_f_b_e_1_1_import.html b/documents/html/struct_f_b_e_1_1_import.html new file mode 100644 index 000000000..64ab53fb7 --- /dev/null +++ b/documents/html/struct_f_b_e_1_1_import.html @@ -0,0 +1,148 @@ + + + + + + + +FastBinaryEncoding: FBE::Import Struct Reference + + + + + + + + + + + +
    +
    + + + + + + +
    +
    FastBinaryEncoding 1.15.0.0 +
    +
    Fast Binary Encoding
    +
    +
    + + + + + + + + + +
    +
    + + +
    +
    +
    +
    +
    +
    Loading...
    +
    Searching...
    +
    No Matches
    +
    +
    +
    +
    + + +
    +
    +
    + +
    FBE::Import Struct Reference
    +
    +
    + +

    #include <fbe.h>

    + + + +

    +Public Member Functions

    void AddImport (std::string *i)
    + + +

    +Public Attributes

    std::vector< std::shared_ptr< std::string > > imports
    +

    Detailed Description

    +
    +

    Definition at line 190 of file fbe.h.

    +

    Member Function Documentation

    + +

    ◆ AddImport()

    + +
    +
    + + + + + + + +
    void FBE::Import::AddImport (std::string * i)
    +
    + +

    Definition at line 176 of file fbe.cpp.

    + +
    +
    +

    Member Data Documentation

    + +

    ◆ imports

    + +
    +
    + + + + +
    std::vector<std::shared_ptr<std::string> > FBE::Import::imports
    +
    + +

    Definition at line 192 of file fbe.h.

    + +
    +
    +
    The documentation for this struct was generated from the following files: +
    + + +
    + + diff --git a/documents/html/struct_f_b_e_1_1_package-members.html b/documents/html/struct_f_b_e_1_1_package-members.html new file mode 100644 index 000000000..ed776e975 --- /dev/null +++ b/documents/html/struct_f_b_e_1_1_package-members.html @@ -0,0 +1,101 @@ + + + + + + + +FastBinaryEncoding: Member List + + + + + + + + + + + +
    +
    + + + + + + +
    +
    FastBinaryEncoding 1.15.0.0 +
    +
    Fast Binary Encoding
    +
    +
    + + + + + + + + + +
    +
    + + +
    +
    +
    +
    +
    +
    Loading...
    +
    Searching...
    +
    No Matches
    +
    +
    +
    +
    + + +
    +
    +
    +
    FBE::Package Member List
    +
    +
    + +

    This is the complete list of members for FBE::Package, including all inherited members.

    + + + + + + + + + + +
    bodyFBE::Package
    domainFBE::Package
    importFBE::Package
    initialize()FBE::Package
    nameFBE::Package
    offsetFBE::Package
    Package(int o)FBE::Package
    rootFBE::Packagestatic
    versionFBE::Package
    + + +
    + + diff --git a/documents/html/struct_f_b_e_1_1_package.html b/documents/html/struct_f_b_e_1_1_package.html new file mode 100644 index 000000000..1ef5c9791 --- /dev/null +++ b/documents/html/struct_f_b_e_1_1_package.html @@ -0,0 +1,283 @@ + + + + + + + +FastBinaryEncoding: FBE::Package Struct Reference + + + + + + + + + + + +
    +
    + + + + + + +
    +
    FastBinaryEncoding 1.15.0.0 +
    +
    Fast Binary Encoding
    +
    +
    + + + + + + + + + +
    +
    + + +
    +
    +
    +
    +
    +
    Loading...
    +
    Searching...
    +
    No Matches
    +
    +
    +
    +
    + + +
    +
    + +
    + +

    #include <fbe.h>

    + + + + +

    +Public Member Functions

     Package (int o)
    void initialize ()
    + + + + + + + +

    +Public Attributes

    int offset
    std::shared_ptr< std::string > domain
    std::shared_ptr< std::string > name
    std::shared_ptr< Import > import
    std::shared_ptr< Version > version
    std::shared_ptr< Statements > body
    + + +

    +Static Public Attributes

    static std::shared_ptr< Package > root = std::make_shared<Package>(0)
    +

    Detailed Description

    +
    +

    Definition at line 206 of file fbe.h.

    +

    Constructor & Destructor Documentation

    + +

    ◆ Package()

    + +
    +
    + + + + + + + +
    FBE::Package::Package (int o)
    +
    + +

    Definition at line 205 of file fbe.cpp.

    + +
    +
    +

    Member Function Documentation

    + +

    ◆ initialize()

    + +
    +
    + + + + + + + +
    void FBE::Package::initialize ()
    +
    + +

    Definition at line 211 of file fbe.cpp.

    + +
    +
    +

    Member Data Documentation

    + +

    ◆ body

    + +
    +
    + + + + +
    std::shared_ptr<Statements> FBE::Package::body
    +
    + +

    Definition at line 213 of file fbe.h.

    + +
    +
    + +

    ◆ domain

    + +
    +
    + + + + +
    std::shared_ptr<std::string> FBE::Package::domain
    +
    + +

    Definition at line 209 of file fbe.h.

    + +
    +
    + +

    ◆ import

    + +
    +
    + + + + +
    std::shared_ptr<Import> FBE::Package::import
    +
    + +

    Definition at line 211 of file fbe.h.

    + +
    +
    + +

    ◆ name

    + +
    +
    + + + + +
    std::shared_ptr<std::string> FBE::Package::name
    +
    + +

    Definition at line 210 of file fbe.h.

    + +
    +
    + +

    ◆ offset

    + +
    +
    + + + + +
    int FBE::Package::offset
    +
    + +

    Definition at line 208 of file fbe.h.

    + +
    +
    + +

    ◆ root

    + +
    +
    + + + + + +
    + + + + +
    std::shared_ptr< Package > FBE::Package::root = std::make_shared<Package>(0)
    +
    +static
    +
    + +

    Definition at line 215 of file fbe.h.

    + +
    +
    + +

    ◆ version

    + +
    +
    + + + + +
    std::shared_ptr<Version> FBE::Package::version
    +
    + +

    Definition at line 212 of file fbe.h.

    + +
    +
    +
    The documentation for this struct was generated from the following files: +
    + + +
    + + diff --git a/documents/html/struct_f_b_e_1_1_statement-members.html b/documents/html/struct_f_b_e_1_1_statement-members.html new file mode 100644 index 000000000..b72a1861f --- /dev/null +++ b/documents/html/struct_f_b_e_1_1_statement-members.html @@ -0,0 +1,95 @@ + + + + + + + +FastBinaryEncoding: Member List + + + + + + + + + + + +
    +
    + + + + + + +
    +
    FastBinaryEncoding 1.15.0.0 +
    +
    Fast Binary Encoding
    +
    +
    + + + + + + + + + +
    +
    + + +
    +
    +
    +
    +
    +
    Loading...
    +
    Searching...
    +
    No Matches
    +
    +
    +
    +
    + + +
    +
    +
    +
    FBE::Statement Member List
    +
    +
    + +

    This is the complete list of members for FBE::Statement, including all inherited members.

    + + + + +
    eFBE::Statement
    fFBE::Statement
    sFBE::Statement
    + + +
    + + diff --git a/documents/html/struct_f_b_e_1_1_statement.html b/documents/html/struct_f_b_e_1_1_statement.html new file mode 100644 index 000000000..b63fcf504 --- /dev/null +++ b/documents/html/struct_f_b_e_1_1_statement.html @@ -0,0 +1,156 @@ + + + + + + + +FastBinaryEncoding: FBE::Statement Struct Reference + + + + + + + + + + + +
    +
    + + + + + + +
    +
    FastBinaryEncoding 1.15.0.0 +
    +
    Fast Binary Encoding
    +
    +
    + + + + + + + + + +
    +
    + + +
    +
    +
    +
    +
    +
    Loading...
    +
    Searching...
    +
    No Matches
    +
    +
    +
    +
    + + +
    +
    +
    + +
    FBE::Statement Struct Reference
    +
    +
    + +

    #include <fbe.h>

    + + + + + +

    +Public Attributes

    std::shared_ptr< EnumType > e
    std::shared_ptr< FlagsType > f
    std::shared_ptr< StructType > s
    +

    Detailed Description

    +
    +

    Definition at line 170 of file fbe.h.

    +

    Member Data Documentation

    + +

    ◆ e

    + +
    +
    + + + + +
    std::shared_ptr<EnumType> FBE::Statement::e
    +
    + +

    Definition at line 172 of file fbe.h.

    + +
    +
    + +

    ◆ f

    + +
    +
    + + + + +
    std::shared_ptr<FlagsType> FBE::Statement::f
    +
    + +

    Definition at line 173 of file fbe.h.

    + +
    +
    + +

    ◆ s

    + +
    +
    + + + + +
    std::shared_ptr<StructType> FBE::Statement::s
    +
    + +

    Definition at line 174 of file fbe.h.

    + +
    +
    +
    The documentation for this struct was generated from the following file: +
    + + +
    + + diff --git a/documents/html/struct_f_b_e_1_1_statements-members.html b/documents/html/struct_f_b_e_1_1_statements-members.html new file mode 100644 index 000000000..9b8ccb757 --- /dev/null +++ b/documents/html/struct_f_b_e_1_1_statements-members.html @@ -0,0 +1,99 @@ + + + + + + + +FastBinaryEncoding: Member List + + + + + + + + + + + +
    +
    + + + + + + +
    +
    FastBinaryEncoding 1.15.0.0 +
    +
    Fast Binary Encoding
    +
    +
    + + + + + + + + + +
    +
    + + +
    +
    +
    +
    +
    +
    Loading...
    +
    Searching...
    +
    No Matches
    +
    +
    +
    +
    + + +
    +
    +
    +
    FBE::Statements Member List
    +
    +
    + +

    This is the complete list of members for FBE::Statements, including all inherited members.

    + + + + + + + + +
    AddEnum(std::shared_ptr< EnumType > &e)FBE::Statements
    AddFlags(std::shared_ptr< FlagsType > &f)FBE::Statements
    AddStatement(Statement *st)FBE::Statements
    AddStruct(std::shared_ptr< StructType > &s)FBE::Statements
    enumsFBE::Statements
    flagsFBE::Statements
    structsFBE::Statements
    + + +
    + + diff --git a/documents/html/struct_f_b_e_1_1_statements.html b/documents/html/struct_f_b_e_1_1_statements.html new file mode 100644 index 000000000..d258f6104 --- /dev/null +++ b/documents/html/struct_f_b_e_1_1_statements.html @@ -0,0 +1,242 @@ + + + + + + + +FastBinaryEncoding: FBE::Statements Struct Reference + + + + + + + + + + + +
    +
    + + + + + + +
    +
    FastBinaryEncoding 1.15.0.0 +
    +
    Fast Binary Encoding
    +
    +
    + + + + + + + + + +
    +
    + + +
    +
    +
    +
    +
    +
    Loading...
    +
    Searching...
    +
    No Matches
    +
    +
    +
    +
    + + +
    +
    +
    + +
    FBE::Statements Struct Reference
    +
    +
    + +

    #include <fbe.h>

    + + + + + + +

    +Public Member Functions

    void AddStatement (Statement *st)
    void AddEnum (std::shared_ptr< EnumType > &e)
    void AddFlags (std::shared_ptr< FlagsType > &f)
    void AddStruct (std::shared_ptr< StructType > &s)
    + + + + +

    +Public Attributes

    std::vector< std::shared_ptr< EnumType > > enums
    std::vector< std::shared_ptr< FlagsType > > flags
    std::vector< std::shared_ptr< StructType > > structs
    +

    Detailed Description

    +
    +

    Definition at line 177 of file fbe.h.

    +

    Member Function Documentation

    + +

    ◆ AddEnum()

    + +
    +
    + + + + + + + +
    void FBE::Statements::AddEnum (std::shared_ptr< EnumType > & e)
    +
    + +

    Definition at line 122 of file fbe.cpp.

    + +
    +
    + +

    ◆ AddFlags()

    + +
    +
    + + + + + + + +
    void FBE::Statements::AddFlags (std::shared_ptr< FlagsType > & f)
    +
    + +

    Definition at line 139 of file fbe.cpp.

    + +
    +
    + +

    ◆ AddStatement()

    + +
    +
    + + + + + + + +
    void FBE::Statements::AddStatement (Statement * st)
    +
    + +

    Definition at line 107 of file fbe.cpp.

    + +
    +
    + +

    ◆ AddStruct()

    + +
    +
    + + + + + + + +
    void FBE::Statements::AddStruct (std::shared_ptr< StructType > & s)
    +
    + +

    Definition at line 156 of file fbe.cpp.

    + +
    +
    +

    Member Data Documentation

    + +

    ◆ enums

    + +
    +
    + + + + +
    std::vector<std::shared_ptr<EnumType> > FBE::Statements::enums
    +
    + +

    Definition at line 179 of file fbe.h.

    + +
    +
    + +

    ◆ flags

    + +
    +
    + + + + +
    std::vector<std::shared_ptr<FlagsType> > FBE::Statements::flags
    +
    + +

    Definition at line 180 of file fbe.h.

    + +
    +
    + +

    ◆ structs

    + +
    +
    + + + + +
    std::vector<std::shared_ptr<StructType> > FBE::Statements::structs
    +
    + +

    Definition at line 181 of file fbe.h.

    + +
    +
    +
    The documentation for this struct was generated from the following files: +
    + + +
    + + diff --git a/documents/html/struct_f_b_e_1_1_struct_body-members.html b/documents/html/struct_f_b_e_1_1_struct_body-members.html new file mode 100644 index 000000000..9d01cf3e1 --- /dev/null +++ b/documents/html/struct_f_b_e_1_1_struct_body-members.html @@ -0,0 +1,94 @@ + + + + + + + +FastBinaryEncoding: Member List + + + + + + + + + + + +
    +
    + + + + + + +
    +
    FastBinaryEncoding 1.15.0.0 +
    +
    Fast Binary Encoding
    +
    +
    + + + + + + + + + +
    +
    + + +
    +
    +
    +
    +
    +
    Loading...
    +
    Searching...
    +
    No Matches
    +
    +
    +
    +
    + + +
    +
    +
    +
    FBE::StructBody Member List
    +
    +
    + +

    This is the complete list of members for FBE::StructBody, including all inherited members.

    + + + +
    AddField(StructField *field)FBE::StructBody
    fieldsFBE::StructBody
    + + +
    + + diff --git a/documents/html/struct_f_b_e_1_1_struct_body.html b/documents/html/struct_f_b_e_1_1_struct_body.html new file mode 100644 index 000000000..61240d05e --- /dev/null +++ b/documents/html/struct_f_b_e_1_1_struct_body.html @@ -0,0 +1,148 @@ + + + + + + + +FastBinaryEncoding: FBE::StructBody Struct Reference + + + + + + + + + + + +
    +
    + + + + + + +
    +
    FastBinaryEncoding 1.15.0.0 +
    +
    Fast Binary Encoding
    +
    +
    + + + + + + + + + +
    +
    + + +
    +
    +
    +
    +
    +
    Loading...
    +
    Searching...
    +
    No Matches
    +
    +
    +
    +
    + + +
    +
    +
    + +
    FBE::StructBody Struct Reference
    +
    +
    + +

    #include <fbe.h>

    + + + +

    +Public Member Functions

    void AddField (StructField *field)
    + + +

    +Public Attributes

    std::vector< std::shared_ptr< StructField > > fields
    +

    Detailed Description

    +
    +

    Definition at line 121 of file fbe.h.

    +

    Member Function Documentation

    + +

    ◆ AddField()

    + +
    +
    + + + + + + + +
    void FBE::StructBody::AddField (StructField * field)
    +
    + +

    Definition at line 59 of file fbe.cpp.

    + +
    +
    +

    Member Data Documentation

    + +

    ◆ fields

    + +
    +
    + + + + +
    std::vector<std::shared_ptr<StructField> > FBE::StructBody::fields
    +
    + +

    Definition at line 123 of file fbe.h.

    + +
    +
    +
    The documentation for this struct was generated from the following files: +
    + + +
    + + diff --git a/documents/html/struct_f_b_e_1_1_struct_field-members.html b/documents/html/struct_f_b_e_1_1_struct_field-members.html new file mode 100644 index 000000000..dec5f3ef3 --- /dev/null +++ b/documents/html/struct_f_b_e_1_1_struct_field-members.html @@ -0,0 +1,109 @@ + + + + + + + +FastBinaryEncoding: Member List + + + + + + + + + + + +
    +
    + + + + + + +
    +
    FastBinaryEncoding 1.15.0.0 +
    +
    Fast Binary Encoding
    +
    +
    + + + + + + + + + +
    +
    + + +
    +
    +
    +
    +
    +
    Loading...
    +
    Searching...
    +
    No Matches
    +
    +
    +
    +
    + + +
    + + + diff --git a/documents/html/struct_f_b_e_1_1_struct_field.html b/documents/html/struct_f_b_e_1_1_struct_field.html new file mode 100644 index 000000000..6e86c47b7 --- /dev/null +++ b/documents/html/struct_f_b_e_1_1_struct_field.html @@ -0,0 +1,403 @@ + + + + + + + +FastBinaryEncoding: FBE::StructField Struct Reference + + + + + + + + + + + +
    +
    + + + + + + +
    +
    FastBinaryEncoding 1.15.0.0 +
    +
    Fast Binary Encoding
    +
    +
    + + + + + + + + + +
    +
    + + +
    +
    +
    +
    +
    +
    Loading...
    +
    Searching...
    +
    No Matches
    +
    +
    +
    +
    + + +
    +
    +
    + +
    FBE::StructField Struct Reference
    +
    +
    + +

    #include <fbe.h>

    + + + +

    +Public Member Functions

    void SetArraySize (int size)
    + + + + + + + + + + + + + + + + + +

    +Public Attributes

    std::shared_ptr< Attributes > attributes
    std::shared_ptr< std::string > name
    std::shared_ptr< std::string > key
    std::shared_ptr< std::string > type
    std::shared_ptr< std::string > value
    bool id {false}
    bool keys {false}
    bool optional {false}
    bool reseter {false}
    bool array {false}
    bool vector {false}
    bool list {false}
    bool set {false}
    bool map {false}
    bool hash {false}
    int N {0}
    +

    Detailed Description

    +
    +

    Definition at line 99 of file fbe.h.

    +

    Member Function Documentation

    + +

    ◆ SetArraySize()

    + +
    +
    + + + + + + + +
    void FBE::StructField::SetArraySize (int size)
    +
    + +

    Definition at line 51 of file fbe.cpp.

    + +
    +
    +

    Member Data Documentation

    + +

    ◆ array

    + +
    +
    + + + + +
    bool FBE::StructField::array {false}
    +
    + +

    Definition at line 110 of file fbe.h.

    + +
    +
    + +

    ◆ attributes

    + +
    +
    + + + + +
    std::shared_ptr<Attributes> FBE::StructField::attributes
    +
    + +

    Definition at line 101 of file fbe.h.

    + +
    +
    + +

    ◆ hash

    + +
    +
    + + + + +
    bool FBE::StructField::hash {false}
    +
    + +

    Definition at line 115 of file fbe.h.

    + +
    +
    + +

    ◆ id

    + +
    +
    + + + + +
    bool FBE::StructField::id {false}
    +
    + +

    Definition at line 106 of file fbe.h.

    + +
    +
    + +

    ◆ key

    + +
    +
    + + + + +
    std::shared_ptr<std::string> FBE::StructField::key
    +
    + +

    Definition at line 103 of file fbe.h.

    + +
    +
    + +

    ◆ keys

    + +
    +
    + + + + +
    bool FBE::StructField::keys {false}
    +
    + +

    Definition at line 107 of file fbe.h.

    + +
    +
    + +

    ◆ list

    + +
    +
    + + + + +
    bool FBE::StructField::list {false}
    +
    + +

    Definition at line 112 of file fbe.h.

    + +
    +
    + +

    ◆ map

    + +
    +
    + + + + +
    bool FBE::StructField::map {false}
    +
    + +

    Definition at line 114 of file fbe.h.

    + +
    +
    + +

    ◆ N

    + +
    +
    + + + + +
    int FBE::StructField::N {0}
    +
    + +

    Definition at line 116 of file fbe.h.

    + +
    +
    + +

    ◆ name

    + +
    +
    + + + + +
    std::shared_ptr<std::string> FBE::StructField::name
    +
    + +

    Definition at line 102 of file fbe.h.

    + +
    +
    + +

    ◆ optional

    + +
    +
    + + + + +
    bool FBE::StructField::optional {false}
    +
    + +

    Definition at line 108 of file fbe.h.

    + +
    +
    + +

    ◆ reseter

    + +
    +
    + + + + +
    bool FBE::StructField::reseter {false}
    +
    + +

    Definition at line 109 of file fbe.h.

    + +
    +
    + +

    ◆ set

    + +
    +
    + + + + +
    bool FBE::StructField::set {false}
    +
    + +

    Definition at line 113 of file fbe.h.

    + +
    +
    + +

    ◆ type

    + +
    +
    + + + + +
    std::shared_ptr<std::string> FBE::StructField::type
    +
    + +

    Definition at line 104 of file fbe.h.

    + +
    +
    + +

    ◆ value

    + +
    +
    + + + + +
    std::shared_ptr<std::string> FBE::StructField::value
    +
    + +

    Definition at line 105 of file fbe.h.

    + +
    +
    + +

    ◆ vector

    + +
    +
    + + + + +
    bool FBE::StructField::vector {false}
    +
    + +

    Definition at line 111 of file fbe.h.

    + +
    +
    +
    The documentation for this struct was generated from the following files: +
    + + +
    + + diff --git a/documents/html/struct_f_b_e_1_1_struct_reject-members.html b/documents/html/struct_f_b_e_1_1_struct_reject-members.html new file mode 100644 index 000000000..fad9f0c0b --- /dev/null +++ b/documents/html/struct_f_b_e_1_1_struct_reject-members.html @@ -0,0 +1,94 @@ + + + + + + + +FastBinaryEncoding: Member List + + + + + + + + + + + +
    +
    + + + + + + +
    +
    FastBinaryEncoding 1.15.0.0 +
    +
    Fast Binary Encoding
    +
    +
    + + + + + + + + + +
    +
    + + +
    +
    +
    +
    +
    +
    Loading...
    +
    Searching...
    +
    No Matches
    +
    +
    +
    +
    + + +
    +
    +
    +
    FBE::StructReject Member List
    +
    +
    + +

    This is the complete list of members for FBE::StructReject, including all inherited members.

    + + + +
    globalFBE::StructReject
    rejectFBE::StructReject
    + + +
    + + diff --git a/documents/html/struct_f_b_e_1_1_struct_reject.html b/documents/html/struct_f_b_e_1_1_struct_reject.html new file mode 100644 index 000000000..285031933 --- /dev/null +++ b/documents/html/struct_f_b_e_1_1_struct_reject.html @@ -0,0 +1,139 @@ + + + + + + + +FastBinaryEncoding: FBE::StructReject Struct Reference + + + + + + + + + + + +
    +
    + + + + + + +
    +
    FastBinaryEncoding 1.15.0.0 +
    +
    Fast Binary Encoding
    +
    +
    + + + + + + + + + +
    +
    + + +
    +
    +
    +
    +
    +
    Loading...
    +
    Searching...
    +
    No Matches
    +
    +
    +
    +
    + + +
    +
    +
    + +
    FBE::StructReject Struct Reference
    +
    +
    + +

    #include <fbe.h>

    + + + + +

    +Public Attributes

    std::shared_ptr< std::string > reject
    bool global
    +

    Detailed Description

    +
    +

    Definition at line 137 of file fbe.h.

    +

    Member Data Documentation

    + +

    ◆ global

    + +
    +
    + + + + +
    bool FBE::StructReject::global
    +
    + +

    Definition at line 140 of file fbe.h.

    + +
    +
    + +

    ◆ reject

    + +
    +
    + + + + +
    std::shared_ptr<std::string> FBE::StructReject::reject
    +
    + +

    Definition at line 139 of file fbe.h.

    + +
    +
    +
    The documentation for this struct was generated from the following file: +
    + + +
    + + diff --git a/documents/html/struct_f_b_e_1_1_struct_rejects-members.html b/documents/html/struct_f_b_e_1_1_struct_rejects-members.html new file mode 100644 index 000000000..48554be33 --- /dev/null +++ b/documents/html/struct_f_b_e_1_1_struct_rejects-members.html @@ -0,0 +1,94 @@ + + + + + + + +FastBinaryEncoding: Member List + + + + + + + + + + + +
    +
    + + + + + + +
    +
    FastBinaryEncoding 1.15.0.0 +
    +
    Fast Binary Encoding
    +
    +
    + + + + + + + + + +
    +
    + + +
    +
    +
    +
    +
    +
    Loading...
    +
    Searching...
    +
    No Matches
    +
    +
    +
    +
    + + +
    +
    +
    +
    FBE::StructRejects Member List
    +
    +
    + +

    This is the complete list of members for FBE::StructRejects, including all inherited members.

    + + + +
    AddReject(std::string *r, bool g)FBE::StructRejects
    rejectsFBE::StructRejects
    + + +
    + + diff --git a/documents/html/struct_f_b_e_1_1_struct_rejects.html b/documents/html/struct_f_b_e_1_1_struct_rejects.html new file mode 100644 index 000000000..08acfec87 --- /dev/null +++ b/documents/html/struct_f_b_e_1_1_struct_rejects.html @@ -0,0 +1,152 @@ + + + + + + + +FastBinaryEncoding: FBE::StructRejects Struct Reference + + + + + + + + + + + +
    +
    + + + + + + +
    +
    FastBinaryEncoding 1.15.0.0 +
    +
    Fast Binary Encoding
    +
    +
    + + + + + + + + + +
    +
    + + +
    +
    +
    +
    +
    +
    Loading...
    +
    Searching...
    +
    No Matches
    +
    +
    +
    +
    + + +
    +
    +
    + +
    FBE::StructRejects Struct Reference
    +
    +
    + +

    #include <fbe.h>

    + + + +

    +Public Member Functions

    void AddReject (std::string *r, bool g)
    + + +

    +Public Attributes

    std::vector< StructReject > rejects
    +

    Detailed Description

    +
    +

    Definition at line 143 of file fbe.h.

    +

    Member Function Documentation

    + +

    ◆ AddReject()

    + +
    +
    + + + + + + + + + + + +
    void FBE::StructRejects::AddReject (std::string * r,
    bool g )
    +
    + +

    Definition at line 76 of file fbe.cpp.

    + +
    +
    +

    Member Data Documentation

    + +

    ◆ rejects

    + +
    +
    + + + + +
    std::vector<StructReject> FBE::StructRejects::rejects
    +
    + +

    Definition at line 145 of file fbe.h.

    + +
    +
    +
    The documentation for this struct was generated from the following files: +
    + + +
    + + diff --git a/documents/html/struct_f_b_e_1_1_struct_request.html b/documents/html/struct_f_b_e_1_1_struct_request.html new file mode 100644 index 000000000..76e31b2c3 --- /dev/null +++ b/documents/html/struct_f_b_e_1_1_struct_request.html @@ -0,0 +1,97 @@ + + + + + + + +FastBinaryEncoding: FBE::StructRequest Struct Reference + + + + + + + + + + + +
    +
    + + + + + + +
    +
    FastBinaryEncoding 1.15.0.0 +
    +
    Fast Binary Encoding
    +
    +
    + + + + + + + + + +
    +
    + + +
    +
    +
    +
    +
    +
    Loading...
    +
    Searching...
    +
    No Matches
    +
    +
    +
    +
    + + +
    +
    +
    +
    FBE::StructRequest Struct Reference
    +
    +
    + +

    #include <fbe.h>

    +

    Detailed Description

    +
    +

    Definition at line 128 of file fbe.h.

    +

    The documentation for this struct was generated from the following file: +
    + + +
    + + diff --git a/documents/html/struct_f_b_e_1_1_struct_response-members.html b/documents/html/struct_f_b_e_1_1_struct_response-members.html new file mode 100644 index 000000000..4171fff6e --- /dev/null +++ b/documents/html/struct_f_b_e_1_1_struct_response-members.html @@ -0,0 +1,93 @@ + + + + + + + +FastBinaryEncoding: Member List + + + + + + + + + + + +
    +
    + + + + + + +
    +
    FastBinaryEncoding 1.15.0.0 +
    +
    Fast Binary Encoding
    +
    +
    + + + + + + + + + +
    +
    + + +
    +
    +
    +
    +
    +
    Loading...
    +
    Searching...
    +
    No Matches
    +
    +
    +
    +
    + + +
    +
    +
    +
    FBE::StructResponse Member List
    +
    +
    + +

    This is the complete list of members for FBE::StructResponse, including all inherited members.

    + + +
    responseFBE::StructResponse
    + + +
    + + diff --git a/documents/html/struct_f_b_e_1_1_struct_response.html b/documents/html/struct_f_b_e_1_1_struct_response.html new file mode 100644 index 000000000..2d206a213 --- /dev/null +++ b/documents/html/struct_f_b_e_1_1_struct_response.html @@ -0,0 +1,122 @@ + + + + + + + +FastBinaryEncoding: FBE::StructResponse Struct Reference + + + + + + + + + + + +
    +
    + + + + + + +
    +
    FastBinaryEncoding 1.15.0.0 +
    +
    Fast Binary Encoding
    +
    +
    + + + + + + + + + +
    +
    + + +
    +
    +
    +
    +
    +
    Loading...
    +
    Searching...
    +
    No Matches
    +
    +
    +
    +
    + + +
    +
    +
    + +
    FBE::StructResponse Struct Reference
    +
    +
    + +

    #include <fbe.h>

    + + + +

    +Public Attributes

    std::shared_ptr< std::string > response
    +

    Detailed Description

    +
    +

    Definition at line 132 of file fbe.h.

    +

    Member Data Documentation

    + +

    ◆ response

    + +
    +
    + + + + +
    std::shared_ptr<std::string> FBE::StructResponse::response
    +
    + +

    Definition at line 134 of file fbe.h.

    + +
    +
    +
    The documentation for this struct was generated from the following file: +
    + + +
    + + diff --git a/documents/html/struct_f_b_e_1_1_struct_type-members.html b/documents/html/struct_f_b_e_1_1_struct_type-members.html new file mode 100644 index 000000000..8116ff2b4 --- /dev/null +++ b/documents/html/struct_f_b_e_1_1_struct_type-members.html @@ -0,0 +1,106 @@ + + + + + + + +FastBinaryEncoding: Member List + + + + + + + + + + + +
    +
    + + + + + + +
    +
    FastBinaryEncoding 1.15.0.0 +
    +
    Fast Binary Encoding
    +
    +
    + + + + + + + + + +
    +
    + + +
    +
    +
    +
    +
    +
    Loading...
    +
    Searching...
    +
    No Matches
    +
    +
    +
    +
    + + +
    + + + diff --git a/documents/html/struct_f_b_e_1_1_struct_type.html b/documents/html/struct_f_b_e_1_1_struct_type.html new file mode 100644 index 000000000..71eb780c1 --- /dev/null +++ b/documents/html/struct_f_b_e_1_1_struct_type.html @@ -0,0 +1,368 @@ + + + + + + + +FastBinaryEncoding: FBE::StructType Struct Reference + + + + + + + + + + + +
    +
    + + + + + + +
    +
    FastBinaryEncoding 1.15.0.0 +
    +
    Fast Binary Encoding
    +
    +
    + + + + + + + + + +
    +
    + + +
    +
    +
    +
    +
    +
    Loading...
    +
    Searching...
    +
    No Matches
    +
    +
    +
    +
    + + +
    +
    + +
    + +

    #include <fbe.h>

    + + + +

    +Public Member Functions

     StructType (int t, bool f)
    + + + + + + + + + + + + + +

    +Public Attributes

    int type
    bool fixed
    bool id {false}
    bool keys {false}
    bool message {false}
    std::shared_ptr< Attributes > attributes
    std::shared_ptr< std::string > name
    std::shared_ptr< std::string > base
    std::shared_ptr< StructRequest > request
    std::shared_ptr< StructResponse > response
    std::shared_ptr< StructRejects > rejects
    std::shared_ptr< StructBody > body
    + + +

    +Static Public Attributes

    static int stype = 0
    +

    Detailed Description

    +
    +

    Definition at line 150 of file fbe.h.

    +

    Constructor & Destructor Documentation

    + +

    ◆ StructType()

    + +
    +
    + + + + + + + + + + + +
    FBE::StructType::StructType (int t,
    bool f )
    +
    + +

    Definition at line 93 of file fbe.cpp.

    + +
    +
    +

    Member Data Documentation

    + +

    ◆ attributes

    + +
    +
    + + + + +
    std::shared_ptr<Attributes> FBE::StructType::attributes
    +
    + +

    Definition at line 157 of file fbe.h.

    + +
    +
    + +

    ◆ base

    + +
    +
    + + + + +
    std::shared_ptr<std::string> FBE::StructType::base
    +
    + +

    Definition at line 159 of file fbe.h.

    + +
    +
    + +

    ◆ body

    + +
    +
    + + + + +
    std::shared_ptr<StructBody> FBE::StructType::body
    +
    + +

    Definition at line 163 of file fbe.h.

    + +
    +
    + +

    ◆ fixed

    + +
    +
    + + + + +
    bool FBE::StructType::fixed
    +
    + +

    Definition at line 153 of file fbe.h.

    + +
    +
    + +

    ◆ id

    + +
    +
    + + + + +
    bool FBE::StructType::id {false}
    +
    + +

    Definition at line 154 of file fbe.h.

    + +
    +
    + +

    ◆ keys

    + +
    +
    + + + + +
    bool FBE::StructType::keys {false}
    +
    + +

    Definition at line 155 of file fbe.h.

    + +
    +
    + +

    ◆ message

    + +
    +
    + + + + +
    bool FBE::StructType::message {false}
    +
    + +

    Definition at line 156 of file fbe.h.

    + +
    +
    + +

    ◆ name

    + +
    +
    + + + + +
    std::shared_ptr<std::string> FBE::StructType::name
    +
    + +

    Definition at line 158 of file fbe.h.

    + +
    +
    + +

    ◆ rejects

    + +
    +
    + + + + +
    std::shared_ptr<StructRejects> FBE::StructType::rejects
    +
    + +

    Definition at line 162 of file fbe.h.

    + +
    +
    + +

    ◆ request

    + +
    +
    + + + + +
    std::shared_ptr<StructRequest> FBE::StructType::request
    +
    + +

    Definition at line 160 of file fbe.h.

    + +
    +
    + +

    ◆ response

    + +
    +
    + + + + +
    std::shared_ptr<StructResponse> FBE::StructType::response
    +
    + +

    Definition at line 161 of file fbe.h.

    + +
    +
    + +

    ◆ stype

    + +
    +
    + + + + + +
    + + + + +
    int FBE::StructType::stype = 0
    +
    +static
    +
    + +

    Definition at line 165 of file fbe.h.

    + +
    +
    + +

    ◆ type

    + +
    +
    + + + + +
    int FBE::StructType::type
    +
    + +

    Definition at line 152 of file fbe.h.

    + +
    +
    +
    The documentation for this struct was generated from the following files: +
    + + +
    + + diff --git a/documents/html/struct_f_b_e_1_1_version-members.html b/documents/html/struct_f_b_e_1_1_version-members.html new file mode 100644 index 000000000..302cb19f7 --- /dev/null +++ b/documents/html/struct_f_b_e_1_1_version-members.html @@ -0,0 +1,96 @@ + + + + + + + +FastBinaryEncoding: Member List + + + + + + + + + + + +
    +
    + + + + + + +
    +
    FastBinaryEncoding 1.15.0.0 +
    +
    Fast Binary Encoding
    +
    +
    + + + + + + + + + +
    +
    + + +
    +
    +
    +
    +
    +
    Loading...
    +
    Searching...
    +
    No Matches
    +
    +
    +
    +
    + + +
    +
    +
    +
    FBE::Version Member List
    +
    +
    + +

    This is the complete list of members for FBE::Version, including all inherited members.

    + + + + + +
    majorFBE::Version
    minorFBE::Version
    Version()=defaultFBE::Version
    Version(const std::string &v)FBE::Version
    + + +
    + + diff --git a/documents/html/struct_f_b_e_1_1_version.html b/documents/html/struct_f_b_e_1_1_version.html new file mode 100644 index 000000000..c7fc26728 --- /dev/null +++ b/documents/html/struct_f_b_e_1_1_version.html @@ -0,0 +1,191 @@ + + + + + + + +FastBinaryEncoding: FBE::Version Struct Reference + + + + + + + + + + + +
    +
    + + + + + + +
    +
    FastBinaryEncoding 1.15.0.0 +
    +
    Fast Binary Encoding
    +
    +
    + + + + + + + + + +
    +
    + + +
    +
    +
    +
    +
    +
    Loading...
    +
    Searching...
    +
    No Matches
    +
    +
    +
    +
    + + +
    +
    +
    + +
    FBE::Version Struct Reference
    +
    +
    + +

    #include <fbe.h>

    + + + + +

    +Public Member Functions

     Version ()=default
     Version (const std::string &v)
    + + + +

    +Public Attributes

    int major {0}
    int minor {0}
    +

    Detailed Description

    +
    +

    Definition at line 197 of file fbe.h.

    +

    Constructor & Destructor Documentation

    + +

    ◆ Version() [1/2]

    + +
    +
    + + + + + +
    + + + + + + + +
    FBE::Version::Version ()
    +
    +default
    +
    + +
    +
    + +

    ◆ Version() [2/2]

    + +
    +
    + + + + + + + +
    FBE::Version::Version (const std::string & v)
    +
    + +

    Definition at line 191 of file fbe.cpp.

    + +
    +
    +

    Member Data Documentation

    + +

    ◆ major

    + +
    +
    + + + + +
    int FBE::Version::major {0}
    +
    + +

    Definition at line 199 of file fbe.h.

    + +
    +
    + +

    ◆ minor

    + +
    +
    + + + + +
    int FBE::Version::minor {0}
    +
    + +

    Definition at line 200 of file fbe.h.

    + +
    +
    +
    The documentation for this struct was generated from the following files: +
    + + +
    + + diff --git a/documents/html/tabs.css b/documents/html/tabs.css new file mode 100644 index 000000000..84f33ae76 --- /dev/null +++ b/documents/html/tabs.css @@ -0,0 +1 @@ +.sm{position:relative;z-index:9999}.sm,.sm ul,.sm li{display:block;list-style:none;margin:0;padding:0;line-height:normal;direction:ltr;text-align:left;-webkit-tap-highlight-color:rgba(0,0,0,0)}.sm-rtl,.sm-rtl ul,.sm-rtl li{direction:rtl;text-align:right}.sm>li>h1,.sm>li>h2,.sm>li>h3,.sm>li>h4,.sm>li>h5,.sm>li>h6{margin:0;padding:0}.sm ul{display:none}.sm li,.sm a{position:relative}.sm a{display:block}.sm a.disabled{cursor:not-allowed}.sm:after{content:"\00a0";display:block;height:0;font:0/0 serif;clear:both;visibility:hidden;overflow:hidden}.sm,.sm *,.sm *:before,.sm *:after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.main-menu-btn{position:relative;display:inline-block;width:36px;height:36px;text-indent:36px;margin-left:8px;white-space:nowrap;overflow:hidden;cursor:pointer;-webkit-tap-highlight-color:rgba(0,0,0,0)}.main-menu-btn-icon,.main-menu-btn-icon:before,.main-menu-btn-icon:after{position:absolute;top:50%;left:2px;height:2px;width:24px;background:var(--nav-menu-button-color);-webkit-transition:all .25s;transition:all .25s}.main-menu-btn-icon:before{content:'';top:-7px;left:0}.main-menu-btn-icon:after{content:'';top:7px;left:0}#main-menu-state:checked ~ .main-menu-btn .main-menu-btn-icon{height:0}#main-menu-state:checked ~ .main-menu-btn .main-menu-btn-icon:before{top:0;-webkit-transform:rotate(-45deg);transform:rotate(-45deg)}#main-menu-state:checked ~ .main-menu-btn .main-menu-btn-icon:after{top:0;-webkit-transform:rotate(45deg);transform:rotate(45deg)}#main-menu-state{position:absolute;width:1px;height:1px;margin:-1px;border:0;padding:0;overflow:hidden;clip:rect(1px,1px,1px,1px)}#main-menu-state:not(:checked) ~ #main-menu{display:none}#main-menu-state:checked ~ #main-menu{display:block}@media(min-width:768px){.main-menu-btn{position:absolute;top:-99999px}#main-menu-state:not(:checked) ~ #main-menu{display:block}}.sm-dox{background-color:var(--nav-menu-background-color)}.sm-dox a,.sm-dox a:focus,.sm-dox a:hover,.sm-dox a:active{padding:0 12px;padding-right:43px;font-family:var(--font-family-nav);font-size:13px;line-height:36px;text-decoration:none;color:var(--nav-text-normal-color);outline:0}.sm-dox a:hover{background-color:var(--nav-menu-active-bg);border-radius:5px}.sm-dox a.current{color:#d23600}.sm-dox a.disabled{color:#bbb}.sm-dox a span.sub-arrow{position:absolute;top:50%;margin-top:-14px;left:auto;right:3px;width:28px;height:28px;overflow:hidden;font:bold 12px/28px monospace !important;text-align:center;text-shadow:none;-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px}.sm-dox a span.sub-arrow:before{display:block;content:'+'}.sm-dox a.highlighted span.sub-arrow:before{display:block;content:'-'}.sm-dox>li:first-child>a,.sm-dox>li:first-child>:not(ul) a{-moz-border-radius:5px 5px 0 0;-webkit-border-radius:5px;border-radius:5px 5px 0 0}.sm-dox>li:last-child>a,.sm-dox>li:last-child>*:not(ul) a,.sm-dox>li:last-child>ul,.sm-dox>li:last-child>ul>li:last-child>a,.sm-dox>li:last-child>ul>li:last-child>*:not(ul) a,.sm-dox>li:last-child>ul>li:last-child>ul,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul{-moz-border-radius:0 0 5px 5px;-webkit-border-radius:0;border-radius:0 0 5px 5px}.sm-dox>li:last-child>a.highlighted,.sm-dox>li:last-child>*:not(ul) a.highlighted,.sm-dox>li:last-child>ul>li:last-child>a.highlighted,.sm-dox>li:last-child>ul>li:last-child>*:not(ul) a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a.highlighted{-moz-border-radius:0;-webkit-border-radius:0;border-radius:0}.sm-dox ul{background:var(--nav-menu-background-color)}.sm-dox ul a,.sm-dox ul a:focus,.sm-dox ul a:hover,.sm-dox ul a:active{font-size:12px;border-left:8px solid transparent;line-height:36px;text-shadow:none;background-color:var(--nav-menu-background-color);background-image:none}.sm-dox ul a:hover{background-color:var(--nav-menu-active-bg);border-radius:5px}.sm-dox ul ul a,.sm-dox ul ul a:hover,.sm-dox ul ul a:focus,.sm-dox ul ul a:active{border-left:16px solid transparent}.sm-dox ul ul ul a,.sm-dox ul ul ul a:hover,.sm-dox ul ul ul a:focus,.sm-dox ul ul ul a:active{border-left:24px solid transparent}.sm-dox ul ul ul ul a,.sm-dox ul ul ul ul a:hover,.sm-dox ul ul ul ul a:focus,.sm-dox ul ul ul ul a:active{border-left:32px solid transparent}.sm-dox ul ul ul ul ul a,.sm-dox ul ul ul ul ul a:hover,.sm-dox ul ul ul ul ul a:focus,.sm-dox ul ul ul ul ul a:active{border-left:40px solid transparent}@media(min-width:768px){.sm-dox ul{position:absolute;width:12em}.sm-dox li{float:left}.sm-dox.sm-rtl li{float:right}.sm-dox ul li,.sm-dox.sm-rtl ul li,.sm-dox.sm-vertical li{float:none}.sm-dox a{white-space:nowrap}.sm-dox ul a,.sm-dox.sm-vertical a{white-space:normal}.sm-dox .sm-nowrap>li>a,.sm-dox .sm-nowrap>li>:not(ul) a{white-space:nowrap}.sm-dox{padding:0 10px;background-color:var(--nav-menu-background-color);line-height:36px}.sm-dox a span.sub-arrow{top:15px;right:10px;box-sizing:content-box;padding:0;margin:0;display:inline-block;width:5px;height:5px;background-color:var(--nav-menu-background-color);border-right:2px solid var(--nav-arrow-color);border-bottom:2px solid var(--nav-arrow-color);transform:rotate(45deg);-moz-border-radius:0;-webkit-border-radius:0;border-radius:0}.sm-dox a,.sm-dox a:focus,.sm-dox a:active,.sm-dox a:hover,.sm-dox a.highlighted{padding:0 6px}.sm-dox a:hover{background-color:var(--nav-menu-active-bg);border-radius:5px !important}.sm-dox a:hover span.sub-arrow{background-color:var(--nav-menu-active-bg);border-right:2px solid var(--nav-arrow-selected-color);border-bottom:2px solid var(--nav-arrow-selected-color)}.sm-dox a.has-submenu{padding-right:24px}.sm-dox li{border-top:0;padding:3px}.sm-dox>li>ul:before,.sm-dox>li>ul:after{content:'';position:absolute;top:-18px;left:30px;width:0;height:0;overflow:hidden;border-width:9px;border-style:dashed dashed solid dashed;border-color:transparent transparent #bbb transparent}.sm-dox>li>ul:after{top:-16px;left:31px;border-width:8px;border-color:transparent transparent var(--nav-menu-background-color) transparent}.sm-dox ul{border:1px solid #bbb;padding:5px 0;background:var(--nav-menu-background-color);-moz-border-radius:5px !important;-webkit-border-radius:5px;border-radius:5px !important;-moz-box-shadow:0 5px 9px rgba(0,0,0,0.2);-webkit-box-shadow:0 5px 9px rgba(0,0,0,0.2);box-shadow:0 5px 9px rgba(0,0,0,0.2)}.sm-dox ul a span.sub-arrow{transform:rotate(-45deg)}.sm-dox ul a,.sm-dox ul a:hover,.sm-dox ul a:focus,.sm-dox ul a:active,.sm-dox ul a.highlighted{color:var(--nav-menu-foreground-color);background-image:none;border:0 !important}.sm-dox ul a:hover{background-color:var(--nav-menu-active-bg);border-radius:5px}.sm-dox span.scroll-up,.sm-dox span.scroll-down{position:absolute;display:none;visibility:hidden;overflow:hidden;background:var(--nav-menu-background-color);height:36px}.sm-dox span.scroll-up:hover,.sm-dox span.scroll-down:hover{background:#eee}.sm-dox span.scroll-up:hover span.scroll-up-arrow,.sm-dox span.scroll-up:hover span.scroll-down-arrow{border-color:transparent transparent #d23600 transparent}.sm-dox span.scroll-down:hover span.scroll-down-arrow{border-color:#d23600 transparent transparent transparent}.sm-dox span.scroll-up-arrow,.sm-dox span.scroll-down-arrow{position:absolute;top:0;left:50%;margin-left:-6px;width:0;height:0;overflow:hidden;border-width:6px;border-style:dashed dashed solid dashed;border-color:transparent transparent var(--nav-menu-foreground-color) transparent}.sm-dox span.scroll-down-arrow{top:8px;border-style:solid dashed dashed dashed;border-color:var(--nav-menu-foreground-color) transparent transparent transparent}.sm-dox.sm-rtl a.has-submenu{padding-right:6px;padding-left:24px}.sm-dox.sm-rtl a span.sub-arrow{right:auto;left:6px}.sm-dox.sm-rtl.sm-vertical a.has-submenu{padding:10px 20px}.sm-dox.sm-rtl.sm-vertical a span.sub-arrow{right:auto;left:8px;border-style:dashed solid dashed dashed;border-color:transparent #555 transparent transparent}.sm-dox.sm-rtl>li>ul:before{left:auto;right:30px}.sm-dox.sm-rtl>li>ul:after{left:auto;right:31px}.sm-dox.sm-rtl ul a.has-submenu{padding:10px 20px !important}.sm-dox.sm-rtl ul a span.sub-arrow{right:auto;left:8px;border-style:dashed solid dashed dashed;border-color:transparent #555 transparent transparent}.sm-dox.sm-vertical{padding:10px 0;-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px}.sm-dox.sm-vertical a{padding:10px 20px}.sm-dox.sm-vertical a:hover,.sm-dox.sm-vertical a:focus,.sm-dox.sm-vertical a:active,.sm-dox.sm-vertical a.highlighted{background:#fff}.sm-dox.sm-vertical a span.sub-arrow{right:8px;top:50%;margin-top:-5px;border-width:5px;border-style:dashed dashed dashed solid;border-color:transparent transparent transparent #555}.sm-dox.sm-vertical>li>ul:before,.sm-dox.sm-vertical>li>ul:after{display:none}.sm-dox.sm-vertical ul a{padding:10px 20px}.sm-dox.sm-vertical ul a:hover,.sm-dox.sm-vertical ul a:focus,.sm-dox.sm-vertical ul a:active,.sm-dox.sm-vertical ul a.highlighted{background:#eee}.sm-dox.sm-vertical ul a.disabled{background:var(--nav-menu-background-color)}} diff --git a/documents/html/version_8h.html b/documents/html/version_8h.html new file mode 100644 index 000000000..23fe20350 --- /dev/null +++ b/documents/html/version_8h.html @@ -0,0 +1,113 @@ + + + + + + + +FastBinaryEncoding: include/version.h File Reference + + + + + + + + + + + +
    +
    + + + + + + +
    +
    FastBinaryEncoding 1.15.0.0 +
    +
    Fast Binary Encoding
    +
    +
    + + + + + + + + + +
    +
    + + +
    +
    +
    +
    +
    +
    Loading...
    +
    Searching...
    +
    No Matches
    +
    +
    +
    +
    + + +
    +
    +
    + +
    version.h File Reference
    +
    +
    + +

    Version definition. +More...

    + +

    Go to the source code of this file.

    + + + +

    +Namespaces

    namespace  FBE
    + + +

    +Variables

    const char FBE::version [] = "1.15.0.0"
    +

    Detailed Description

    +

    Version definition.

    +
    Author
    Ivan Shynkarenka
    +
    Date
    11.04.2018
    + + +

    Definition in file version.h.

    +
    + + +
    + + diff --git a/documents/html/version_8h_source.html b/documents/html/version_8h_source.html new file mode 100644 index 000000000..503d8d5cb --- /dev/null +++ b/documents/html/version_8h_source.html @@ -0,0 +1,104 @@ + + + + + + + +FastBinaryEncoding: include/version.h Source File + + + + + + + + + + + +
    +
    + + + + + + +
    +
    FastBinaryEncoding 1.15.0.0 +
    +
    Fast Binary Encoding
    +
    +
    + + + + + + + + + +
    +
    + + +
    +
    +
    +
    +
    +
    Loading...
    +
    Searching...
    +
    No Matches
    +
    +
    +
    +
    + + +
    +
    +
    +
    version.h
    +
    +
    +Go to the documentation of this file.
    1
    +
    8
    +
    9#ifndef VERSION_H
    +
    10#define VERSION_H
    +
    11
    +
    12namespace FBE {
    +
    13
    +
    14// Fast binary encoding version
    +
    15const char version[] = "1.15.0.0";
    +
    16
    +
    17} // namespace FBE
    +
    18
    +
    19#endif // VERSION_H
    +
    Definition fbe.h:33
    +
    const char version[]
    Definition version.h:15
    +
    + + +
    + +